+doc #17613 document persistence schema evolution

This commit is contained in:
Konrad Malawski 2015-07-22 16:25:17 +02:00 committed by Konrad Malawski
parent 20352562e1
commit 270c566fea
31 changed files with 5334 additions and 19 deletions

View file

@ -178,3 +178,6 @@ strong {color: #0B5567; }
.section-marker { position: absolute; width: 1em; margin-left: -1em; display: block; text-decoration: none; visibility: hidden; text-align: center; font-weight: normal; } .section-marker { position: absolute; width: 1em; margin-left: -1em; display: block; text-decoration: none; visibility: hidden; text-align: center; font-weight: normal; }
.section-marker:hover { text-decoration: none; } .section-marker:hover { text-decoration: none; }
.section h2:hover > a,.section h3:hover > a,.section h4:hover > a,.section h5:hover > a { visibility: visible; } .section h2:hover > a,.section h3:hover > a,.section h4:hover > a,.section h5:hover > a { visibility: visible; }
div.align-center { width: 100%; text-align: center; }
p.caption { width: 80%; text-align: justify; font-size: 0.95em; font-style: italic; position: relative; left: 10%; }

View file

@ -20,6 +20,7 @@ prior deprecation.
:maxdepth: 1 :maxdepth: 1
../scala/persistence ../scala/persistence
../scala/persistence-schema-evolution
../dev/multi-node-testing ../dev/multi-node-testing
../java/lambda-actors ../java/lambda-actors
../java/lambda-fsm ../java/lambda-fsm

View file

@ -0,0 +1,596 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>ActiveLayerIndex</key>
<integer>0</integer>
<key>ApplicationVersion</key>
<array>
<string>com.omnigroup.OmniGrafflePro</string>
<string>139.18.0.187838</string>
</array>
<key>AutoAdjust</key>
<true/>
<key>BackgroundGraphic</key>
<dict>
<key>Bounds</key>
<string>{{0, 0}, {559.28997802734375, 782.8900146484375}}</string>
<key>Class</key>
<string>SolidGraphic</string>
<key>ID</key>
<integer>2</integer>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>stroke</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
</dict>
<key>BaseZoom</key>
<integer>0</integer>
<key>CanvasOrigin</key>
<string>{0, 0}</string>
<key>ColumnAlign</key>
<integer>1</integer>
<key>ColumnSpacing</key>
<real>36</real>
<key>CreationDate</key>
<string>2015-07-23 08:51:08 +0000</string>
<key>Creator</key>
<string>Konrad Malawski</string>
<key>DisplayScale</key>
<string>1 0/72 in = 1.0000 in</string>
<key>ExportLineEnds</key>
<array>
<dict>
<key>Gap</key>
<real>0.5</real>
<key>LineGap</key>
<real>1</real>
<key>Name</key>
<string>NonNavigable</string>
<key>Path</key>
<dict>
<key>elements</key>
<array>
<dict>
<key>element</key>
<string>MOVETO</string>
<key>point</key>
<string>{0, 0}</string>
</dict>
<dict>
<key>element</key>
<string>LINETO</string>
<key>point</key>
<string>{14, 0}</string>
</dict>
<dict>
<key>element</key>
<string>MOVETO</string>
<key>point</key>
<string>{6, -4}</string>
</dict>
<dict>
<key>element</key>
<string>LINETO</string>
<key>point</key>
<string>{14, 4}</string>
</dict>
<dict>
<key>element</key>
<string>MOVETO</string>
<key>point</key>
<string>{14, -4}</string>
</dict>
<dict>
<key>element</key>
<string>LINETO</string>
<key>point</key>
<string>{6, 4}</string>
</dict>
</array>
</dict>
<key>ShouldExport</key>
<string>YES</string>
<key>Width</key>
<real>14</real>
</dict>
</array>
<key>GraphDocumentVersion</key>
<integer>8</integer>
<key>GraphicsList</key>
<array>
<dict>
<key>Bounds</key>
<string>{{145.63265806103379, 72.749998636153364}, {19, 24}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>FitText</key>
<string>YES</string>
<key>Flow</key>
<string>Resize</string>
<key>FontInfo</key>
<dict>
<key>Color</key>
<dict>
<key>w</key>
<string>0</string>
</dict>
<key>Font</key>
<string>Helvetica</string>
<key>Size</key>
<real>12</real>
</dict>
<key>ID</key>
<integer>55</integer>
<key>Line</key>
<dict>
<key>ID</key>
<integer>54</integer>
<key>Position</key>
<real>0.43243709206581116</real>
<key>RotationType</key>
<integer>0</integer>
</dict>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>stroke</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170
\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 E}</string>
</dict>
<key>Wrap</key>
<string>NO</string>
</dict>
<dict>
<key>Class</key>
<string>LineGraphic</string>
<key>ID</key>
<integer>54</integer>
<key>Points</key>
<array>
<string>{187.09439086914062, 84.749998636153364}</string>
<string>{113.18368016802742, 84.749998636153364}</string>
</array>
<key>Style</key>
<dict>
<key>stroke</key>
<dict>
<key>HeadArrow</key>
<string>FilledArrow</string>
<key>Legacy</key>
<true/>
<key>LineType</key>
<integer>1</integer>
<key>TailArrow</key>
<string>0</string>
</dict>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{280.05209427608111, 48.612242837540641}, {20, 24}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>FitText</key>
<string>YES</string>
<key>Flow</key>
<string>Resize</string>
<key>FontInfo</key>
<dict>
<key>Color</key>
<dict>
<key>w</key>
<string>0</string>
</dict>
<key>Font</key>
<string>Helvetica</string>
<key>Size</key>
<real>12</real>
</dict>
<key>ID</key>
<integer>51</integer>
<key>Line</key>
<dict>
<key>ID</key>
<integer>50</integer>
<key>Position</key>
<real>0.46999874711036682</real>
<key>RotationType</key>
<integer>0</integer>
</dict>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>stroke</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170
\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 O}</string>
</dict>
<key>Wrap</key>
<string>NO</string>
</dict>
<dict>
<key>Class</key>
<string>LineGraphic</string>
<key>ID</key>
<integer>50</integer>
<key>Points</key>
<array>
<string>{329.8431396484375, 60.612242837540641}</string>
<string>{245.18111529837574, 60.612242837540641}</string>
</array>
<key>Style</key>
<dict>
<key>stroke</key>
<dict>
<key>HeadArrow</key>
<string>NonNavigable</string>
<key>Legacy</key>
<true/>
<key>LineType</key>
<integer>1</integer>
<key>TailArrow</key>
<string>0</string>
</dict>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{280.55209530438208, 70.749999613371074}, {19, 24}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>FitText</key>
<string>YES</string>
<key>Flow</key>
<string>Resize</string>
<key>FontInfo</key>
<dict>
<key>Color</key>
<dict>
<key>w</key>
<string>0</string>
</dict>
<key>Font</key>
<string>Helvetica</string>
<key>Size</key>
<real>12</real>
</dict>
<key>ID</key>
<integer>49</integer>
<key>Line</key>
<dict>
<key>ID</key>
<integer>48</integer>
<key>Position</key>
<real>0.46999874711036682</real>
<key>RotationType</key>
<integer>0</integer>
</dict>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>stroke</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170
\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 E}</string>
</dict>
<key>Wrap</key>
<string>NO</string>
</dict>
<dict>
<key>Class</key>
<string>LineGraphic</string>
<key>ID</key>
<integer>48</integer>
<key>Points</key>
<array>
<string>{329.84314158862338, 82.749999613371074}</string>
<string>{245.18111529837574, 82.749999613371074}</string>
</array>
<key>Style</key>
<dict>
<key>stroke</key>
<dict>
<key>HeadArrow</key>
<string>FilledArrow</string>
<key>Legacy</key>
<true/>
<key>LineType</key>
<integer>1</integer>
<key>TailArrow</key>
<string>0</string>
</dict>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{329.84315457120567, 27.964286256094354}, {54, 79.897956848144531}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>10</integer>
<key>Magnets</key>
<array>
<string>{0, 1}</string>
<string>{0, -1}</string>
<string>{1, 0}</string>
<string>{-1, 0}</string>
</array>
<key>Shape</key>
<string>Cylinder</string>
<key>Style</key>
<dict/>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170
\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
\f0\fs20 \cf0 Journal}</string>
<key>VerticalPad</key>
<integer>0</integer>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{187.09438968957969, 27.964285076097411}, {57.586738586425781, 79.897956848144531}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>13</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170
\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 Event\
Adapter}</string>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{9.9872450012231155, 51.61224533855227}, {102.19643402099609, 45.275508880615234}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>1</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170
\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 PersistentActor}</string>
</dict>
</dict>
</array>
<key>GridInfo</key>
<dict/>
<key>GuidesLocked</key>
<string>NO</string>
<key>GuidesVisible</key>
<string>YES</string>
<key>HPages</key>
<integer>1</integer>
<key>ImageCounter</key>
<integer>1</integer>
<key>KeepToScale</key>
<false/>
<key>Layers</key>
<array>
<dict>
<key>Lock</key>
<string>NO</string>
<key>Name</key>
<string>Layer 1</string>
<key>Print</key>
<string>YES</string>
<key>View</key>
<string>YES</string>
</dict>
</array>
<key>LayoutInfo</key>
<dict>
<key>Animate</key>
<string>NO</string>
<key>circoMinDist</key>
<real>18</real>
<key>circoSeparation</key>
<real>0.0</real>
<key>layoutEngine</key>
<string>dot</string>
<key>neatoSeparation</key>
<real>0.0</real>
<key>twopiSeparation</key>
<real>0.0</real>
</dict>
<key>LinksVisible</key>
<string>NO</string>
<key>MagnetsVisible</key>
<string>NO</string>
<key>MasterSheets</key>
<array/>
<key>ModificationDate</key>
<string>2015-07-24 08:44:48 +0000</string>
<key>Modifier</key>
<string>Konrad Malawski</string>
<key>NotesVisible</key>
<string>NO</string>
<key>Orientation</key>
<integer>2</integer>
<key>OriginVisible</key>
<string>NO</string>
<key>PageBreaks</key>
<string>YES</string>
<key>PrintInfo</key>
<dict>
<key>NSBottomMargin</key>
<array>
<string>float</string>
<string>41</string>
</array>
<key>NSHorizonalPagination</key>
<array>
<string>coded</string>
<string>BAtzdHJlYW10eXBlZIHoA4QBQISEhAhOU051bWJlcgCEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAFxlwCG</string>
</array>
<key>NSLeftMargin</key>
<array>
<string>float</string>
<string>18</string>
</array>
<key>NSPaperSize</key>
<array>
<string>size</string>
<string>{595.28997802734375, 841.8900146484375}</string>
</array>
<key>NSPrintReverseOrientation</key>
<array>
<string>int</string>
<string>0</string>
</array>
<key>NSRightMargin</key>
<array>
<string>float</string>
<string>18</string>
</array>
<key>NSTopMargin</key>
<array>
<string>float</string>
<string>18</string>
</array>
</dict>
<key>PrintOnePage</key>
<false/>
<key>ReadOnly</key>
<string>NO</string>
<key>RowAlign</key>
<integer>1</integer>
<key>RowSpacing</key>
<real>36</real>
<key>SheetTitle</key>
<string>Canvas 1</string>
<key>SmartAlignmentGuidesActive</key>
<string>YES</string>
<key>SmartDistanceGuidesActive</key>
<string>YES</string>
<key>UniqueID</key>
<integer>1</integer>
<key>UseEntirePage</key>
<false/>
<key>VPages</key>
<integer>1</integer>
<key>WindowInfo</key>
<dict>
<key>CurrentSheet</key>
<integer>0</integer>
<key>ExpandedCanvases</key>
<array>
<dict>
<key>name</key>
<string>Canvas 1</string>
</dict>
</array>
<key>FitInWindow</key>
<true/>
<key>Frame</key>
<string>{{288, -0}, {1920, 1417}}</string>
<key>ListView</key>
<true/>
<key>OutlineWidth</key>
<integer>142</integer>
<key>RightSidebar</key>
<false/>
<key>ShowRuler</key>
<true/>
<key>Sidebar</key>
<true/>
<key>SidebarWidth</key>
<integer>120</integer>
<key>VisibleRegion</key>
<string>{{-268, 0}, {1096.1999781692175, 782.99998440658374}}</string>
<key>Zoom</key>
<real>1.6283525228500366</real>
<key>ZoomValues</key>
<array>
<array>
<string>Canvas 1</string>
<real>0.0</real>
<real>1</real>
</array>
</array>
</dict>
</dict>
</plist>

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6 KiB

View file

@ -0,0 +1,786 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>ActiveLayerIndex</key>
<integer>0</integer>
<key>ApplicationVersion</key>
<array>
<string>com.omnigroup.OmniGrafflePro</string>
<string>139.18.0.187838</string>
</array>
<key>AutoAdjust</key>
<true/>
<key>BackgroundGraphic</key>
<dict>
<key>Bounds</key>
<string>{{0, 0}, {559.28997802734375, 782.8900146484375}}</string>
<key>Class</key>
<string>SolidGraphic</string>
<key>ID</key>
<integer>2</integer>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>stroke</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
</dict>
<key>BaseZoom</key>
<integer>0</integer>
<key>CanvasOrigin</key>
<string>{0, 0}</string>
<key>ColumnAlign</key>
<integer>1</integer>
<key>ColumnSpacing</key>
<real>36</real>
<key>CreationDate</key>
<string>2015-07-23 08:51:08 +0000</string>
<key>Creator</key>
<string>Konrad Malawski</string>
<key>DisplayScale</key>
<string>1 0/72 in = 1.0000 in</string>
<key>ExportLineEnds</key>
<array>
<dict>
<key>Gap</key>
<real>0.5</real>
<key>LineGap</key>
<real>1</real>
<key>Name</key>
<string>NonNavigable</string>
<key>Path</key>
<dict>
<key>elements</key>
<array>
<dict>
<key>element</key>
<string>MOVETO</string>
<key>point</key>
<string>{0, 0}</string>
</dict>
<dict>
<key>element</key>
<string>LINETO</string>
<key>point</key>
<string>{14, 0}</string>
</dict>
<dict>
<key>element</key>
<string>MOVETO</string>
<key>point</key>
<string>{6, -4}</string>
</dict>
<dict>
<key>element</key>
<string>LINETO</string>
<key>point</key>
<string>{14, 4}</string>
</dict>
<dict>
<key>element</key>
<string>MOVETO</string>
<key>point</key>
<string>{14, -4}</string>
</dict>
<dict>
<key>element</key>
<string>LINETO</string>
<key>point</key>
<string>{6, 4}</string>
</dict>
</array>
</dict>
<key>ShouldExport</key>
<string>YES</string>
<key>Width</key>
<real>14</real>
</dict>
</array>
<key>GraphDocumentVersion</key>
<integer>8</integer>
<key>GraphicsList</key>
<array>
<dict>
<key>Bounds</key>
<string>{{263.4039515357976, 48.112230402415705}, {18, 24}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>FitText</key>
<string>YES</string>
<key>Flow</key>
<string>Resize</string>
<key>FontInfo</key>
<dict>
<key>Color</key>
<dict>
<key>w</key>
<string>0</string>
</dict>
<key>Font</key>
<string>Helvetica</string>
<key>Size</key>
<real>12</real>
</dict>
<key>ID</key>
<integer>61</integer>
<key>Line</key>
<dict>
<key>ID</key>
<integer>60</integer>
<key>Position</key>
<real>0.46999874711036682</real>
<key>RotationType</key>
<integer>0</integer>
</dict>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>stroke</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170
\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 T}</string>
</dict>
<key>Wrap</key>
<string>NO</string>
</dict>
<dict>
<key>Class</key>
<string>LineGraphic</string>
<key>ID</key>
<integer>60</integer>
<key>Points</key>
<array>
<string>{296.98822404239763, 60.112230402415705}</string>
<string>{244.68112182617185, 60.112230402415705}</string>
</array>
<key>Style</key>
<dict>
<key>stroke</key>
<dict>
<key>HeadArrow</key>
<string>NonNavigable</string>
<key>Legacy</key>
<true/>
<key>LineType</key>
<integer>1</integer>
<key>TailArrow</key>
<string>0</string>
</dict>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{262.90395153579766, 70.874989110500337}, {19, 24}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>FitText</key>
<string>YES</string>
<key>Flow</key>
<string>Resize</string>
<key>FontInfo</key>
<dict>
<key>Color</key>
<dict>
<key>w</key>
<string>0</string>
</dict>
<key>Font</key>
<string>Helvetica</string>
<key>Size</key>
<real>12</real>
</dict>
<key>ID</key>
<integer>59</integer>
<key>Line</key>
<dict>
<key>ID</key>
<integer>58</integer>
<key>Position</key>
<real>0.46999874711036682</real>
<key>RotationType</key>
<integer>0</integer>
</dict>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>stroke</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170
\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 E}</string>
</dict>
<key>Wrap</key>
<string>NO</string>
</dict>
<dict>
<key>Class</key>
<string>LineGraphic</string>
<key>ID</key>
<integer>58</integer>
<key>Points</key>
<array>
<string>{296.98822404239769, 82.874989110500337}</string>
<string>{244.68112182617188, 82.874989110500337}</string>
</array>
<key>Style</key>
<dict>
<key>stroke</key>
<dict>
<key>HeadArrow</key>
<string>FilledArrow</string>
<key>Legacy</key>
<true/>
<key>LineType</key>
<integer>1</integer>
<key>TailArrow</key>
<string>0</string>
</dict>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{296.34996616998893, 27.964282227528443}, {63.018733978271484, 79.897956848144531}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>57</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170
\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 Serializer}</string>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{145.63265806103379, 72.749998636153364}, {19, 24}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>FitText</key>
<string>YES</string>
<key>Flow</key>
<string>Resize</string>
<key>FontInfo</key>
<dict>
<key>Color</key>
<dict>
<key>w</key>
<string>0</string>
</dict>
<key>Font</key>
<string>Helvetica</string>
<key>Size</key>
<real>12</real>
</dict>
<key>ID</key>
<integer>55</integer>
<key>Line</key>
<dict>
<key>ID</key>
<integer>54</integer>
<key>Position</key>
<real>0.43243709206581116</real>
<key>RotationType</key>
<integer>0</integer>
</dict>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>stroke</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170
\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 E}</string>
</dict>
<key>Wrap</key>
<string>NO</string>
</dict>
<dict>
<key>Class</key>
<string>LineGraphic</string>
<key>ID</key>
<integer>54</integer>
<key>Points</key>
<array>
<string>{187.09439086914062, 84.749998636153364}</string>
<string>{113.18368016802742, 84.749998636153364}</string>
</array>
<key>Style</key>
<dict>
<key>stroke</key>
<dict>
<key>HeadArrow</key>
<string>FilledArrow</string>
<key>Legacy</key>
<true/>
<key>LineType</key>
<integer>1</integer>
<key>TailArrow</key>
<string>0</string>
</dict>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{394.23969235661161, 48.612232334669955}, {20, 24}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>FitText</key>
<string>YES</string>
<key>Flow</key>
<string>Resize</string>
<key>FontInfo</key>
<dict>
<key>Color</key>
<dict>
<key>w</key>
<string>0</string>
</dict>
<key>Font</key>
<string>Helvetica</string>
<key>Size</key>
<real>12</real>
</dict>
<key>ID</key>
<integer>51</integer>
<key>Line</key>
<dict>
<key>ID</key>
<integer>50</integer>
<key>Position</key>
<real>0.46999874711036682</real>
<key>RotationType</key>
<integer>0</integer>
</dict>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>stroke</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170
\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 O}</string>
</dict>
<key>Wrap</key>
<string>NO</string>
</dict>
<dict>
<key>Class</key>
<string>LineGraphic</string>
<key>ID</key>
<integer>50</integer>
<key>Points</key>
<array>
<string>{444.03073772896801, 60.612232334669955}</string>
<string>{359.36871337890625, 60.612232334669955}</string>
</array>
<key>Style</key>
<dict>
<key>stroke</key>
<dict>
<key>HeadArrow</key>
<string>FilledArrow</string>
<key>Legacy</key>
<true/>
<key>LineType</key>
<integer>1</integer>
<key>TailArrow</key>
<string>0</string>
</dict>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{394.73969338491258, 70.74998911050038}, {19, 24}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>FitText</key>
<string>YES</string>
<key>Flow</key>
<string>Resize</string>
<key>FontInfo</key>
<dict>
<key>Color</key>
<dict>
<key>w</key>
<string>0</string>
</dict>
<key>Font</key>
<string>Helvetica</string>
<key>Size</key>
<real>12</real>
</dict>
<key>ID</key>
<integer>49</integer>
<key>Line</key>
<dict>
<key>ID</key>
<integer>48</integer>
<key>Position</key>
<real>0.46999874711036682</real>
<key>RotationType</key>
<integer>0</integer>
</dict>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>stroke</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170
\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 E}</string>
</dict>
<key>Wrap</key>
<string>NO</string>
</dict>
<dict>
<key>Class</key>
<string>LineGraphic</string>
<key>ID</key>
<integer>48</integer>
<key>Points</key>
<array>
<string>{444.03073966915389, 82.74998911050038}</string>
<string>{359.36871337890625, 82.74998911050038}</string>
</array>
<key>Style</key>
<dict>
<key>stroke</key>
<dict>
<key>HeadArrow</key>
<string>FilledArrow</string>
<key>Legacy</key>
<true/>
<key>LineType</key>
<integer>1</integer>
<key>TailArrow</key>
<string>0</string>
</dict>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{444.03075265173618, 27.964275753223664}, {54, 79.897956848144531}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>10</integer>
<key>Magnets</key>
<array>
<string>{0, 1}</string>
<string>{0, -1}</string>
<string>{1, 0}</string>
<string>{-1, 0}</string>
</array>
<key>Shape</key>
<string>Cylinder</string>
<key>Style</key>
<dict/>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170
\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
\f0\fs20 \cf0 Journal}</string>
<key>VerticalPad</key>
<integer>0</integer>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{187.09438968957969, 27.964285076097411}, {57.586738586425781, 79.897956848144531}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>13</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170
\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 Event\
Adapter}</string>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{9.9872450012231155, 51.61224533855227}, {102.19643402099609, 45.275508880615234}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>1</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170
\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 PersistentActor}</string>
</dict>
</dict>
</array>
<key>GridInfo</key>
<dict/>
<key>GuidesLocked</key>
<string>NO</string>
<key>GuidesVisible</key>
<string>YES</string>
<key>HPages</key>
<integer>1</integer>
<key>ImageCounter</key>
<integer>1</integer>
<key>KeepToScale</key>
<false/>
<key>Layers</key>
<array>
<dict>
<key>Lock</key>
<string>NO</string>
<key>Name</key>
<string>Layer 1</string>
<key>Print</key>
<string>YES</string>
<key>View</key>
<string>YES</string>
</dict>
</array>
<key>LayoutInfo</key>
<dict>
<key>Animate</key>
<string>NO</string>
<key>circoMinDist</key>
<real>18</real>
<key>circoSeparation</key>
<real>0.0</real>
<key>layoutEngine</key>
<string>dot</string>
<key>neatoSeparation</key>
<real>0.0</real>
<key>twopiSeparation</key>
<real>0.0</real>
</dict>
<key>LinksVisible</key>
<string>NO</string>
<key>MagnetsVisible</key>
<string>NO</string>
<key>MasterSheets</key>
<array/>
<key>ModificationDate</key>
<string>2015-07-24 11:04:44 +0000</string>
<key>Modifier</key>
<string>Konrad Malawski</string>
<key>NotesVisible</key>
<string>NO</string>
<key>Orientation</key>
<integer>2</integer>
<key>OriginVisible</key>
<string>NO</string>
<key>PageBreaks</key>
<string>YES</string>
<key>PrintInfo</key>
<dict>
<key>NSBottomMargin</key>
<array>
<string>float</string>
<string>41</string>
</array>
<key>NSHorizonalPagination</key>
<array>
<string>coded</string>
<string>BAtzdHJlYW10eXBlZIHoA4QBQISEhAhOU051bWJlcgCEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAFxlwCG</string>
</array>
<key>NSLeftMargin</key>
<array>
<string>float</string>
<string>18</string>
</array>
<key>NSPaperSize</key>
<array>
<string>size</string>
<string>{595.28997802734375, 841.8900146484375}</string>
</array>
<key>NSPrintReverseOrientation</key>
<array>
<string>int</string>
<string>0</string>
</array>
<key>NSRightMargin</key>
<array>
<string>float</string>
<string>18</string>
</array>
<key>NSTopMargin</key>
<array>
<string>float</string>
<string>18</string>
</array>
</dict>
<key>PrintOnePage</key>
<false/>
<key>ReadOnly</key>
<string>NO</string>
<key>RowAlign</key>
<integer>1</integer>
<key>RowSpacing</key>
<real>36</real>
<key>SheetTitle</key>
<string>Canvas 1</string>
<key>SmartAlignmentGuidesActive</key>
<string>YES</string>
<key>SmartDistanceGuidesActive</key>
<string>YES</string>
<key>UniqueID</key>
<integer>1</integer>
<key>UseEntirePage</key>
<false/>
<key>VPages</key>
<integer>1</integer>
<key>WindowInfo</key>
<dict>
<key>CurrentSheet</key>
<integer>0</integer>
<key>ExpandedCanvases</key>
<array>
<dict>
<key>name</key>
<string>Canvas 1</string>
</dict>
</array>
<key>FitInWindow</key>
<true/>
<key>Frame</key>
<string>{{271, 0}, {1920, 1417}}</string>
<key>ListView</key>
<true/>
<key>OutlineWidth</key>
<integer>142</integer>
<key>RightSidebar</key>
<false/>
<key>ShowRuler</key>
<true/>
<key>Sidebar</key>
<true/>
<key>SidebarWidth</key>
<integer>120</integer>
<key>VisibleRegion</key>
<string>{{-268, 0}, {1096.199978169217, 782.99998440658374}}</string>
<key>Zoom</key>
<real>1.6283525228500366</real>
<key>ZoomValues</key>
<array>
<array>
<string>Canvas 1</string>
<real>0.0</real>
<real>1</real>
</array>
</array>
</dict>
</dict>
</plist>

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6.9 KiB

View file

@ -0,0 +1,596 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>ActiveLayerIndex</key>
<integer>0</integer>
<key>ApplicationVersion</key>
<array>
<string>com.omnigroup.OmniGrafflePro</string>
<string>139.18.0.187838</string>
</array>
<key>AutoAdjust</key>
<true/>
<key>BackgroundGraphic</key>
<dict>
<key>Bounds</key>
<string>{{0, 0}, {559.28997802734375, 782.8900146484375}}</string>
<key>Class</key>
<string>SolidGraphic</string>
<key>ID</key>
<integer>2</integer>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>stroke</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
</dict>
<key>BaseZoom</key>
<integer>0</integer>
<key>CanvasOrigin</key>
<string>{0, 0}</string>
<key>ColumnAlign</key>
<integer>1</integer>
<key>ColumnSpacing</key>
<real>36</real>
<key>CreationDate</key>
<string>2015-07-23 08:51:08 +0000</string>
<key>Creator</key>
<string>Konrad Malawski</string>
<key>DisplayScale</key>
<string>1 0/72 in = 1.0000 in</string>
<key>ExportLineEnds</key>
<array>
<dict>
<key>Gap</key>
<real>0.5</real>
<key>LineGap</key>
<real>1</real>
<key>Name</key>
<string>NonNavigable</string>
<key>Path</key>
<dict>
<key>elements</key>
<array>
<dict>
<key>element</key>
<string>MOVETO</string>
<key>point</key>
<string>{0, 0}</string>
</dict>
<dict>
<key>element</key>
<string>LINETO</string>
<key>point</key>
<string>{14, 0}</string>
</dict>
<dict>
<key>element</key>
<string>MOVETO</string>
<key>point</key>
<string>{6, -4}</string>
</dict>
<dict>
<key>element</key>
<string>LINETO</string>
<key>point</key>
<string>{14, 4}</string>
</dict>
<dict>
<key>element</key>
<string>MOVETO</string>
<key>point</key>
<string>{14, -4}</string>
</dict>
<dict>
<key>element</key>
<string>LINETO</string>
<key>point</key>
<string>{6, 4}</string>
</dict>
</array>
</dict>
<key>ShouldExport</key>
<string>YES</string>
<key>Width</key>
<real>14</real>
</dict>
</array>
<key>GraphDocumentVersion</key>
<integer>8</integer>
<key>GraphicsList</key>
<array>
<dict>
<key>Bounds</key>
<string>{{145.63265806103379, 72.749998636153364}, {19, 24}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>FitText</key>
<string>YES</string>
<key>Flow</key>
<string>Resize</string>
<key>FontInfo</key>
<dict>
<key>Color</key>
<dict>
<key>w</key>
<string>0</string>
</dict>
<key>Font</key>
<string>Helvetica</string>
<key>Size</key>
<real>12</real>
</dict>
<key>ID</key>
<integer>55</integer>
<key>Line</key>
<dict>
<key>ID</key>
<integer>54</integer>
<key>Position</key>
<real>0.43243709206581116</real>
<key>RotationType</key>
<integer>0</integer>
</dict>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>stroke</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170
\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 E}</string>
</dict>
<key>Wrap</key>
<string>NO</string>
</dict>
<dict>
<key>Class</key>
<string>LineGraphic</string>
<key>ID</key>
<integer>54</integer>
<key>Points</key>
<array>
<string>{187.09439086914062, 84.749998636153364}</string>
<string>{113.18368016802742, 84.749998636153364}</string>
</array>
<key>Style</key>
<dict>
<key>stroke</key>
<dict>
<key>HeadArrow</key>
<string>FilledArrow</string>
<key>Legacy</key>
<true/>
<key>LineType</key>
<integer>1</integer>
<key>TailArrow</key>
<string>0</string>
</dict>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{280.05209427608111, 48.612242837540641}, {20, 24}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>FitText</key>
<string>YES</string>
<key>Flow</key>
<string>Resize</string>
<key>FontInfo</key>
<dict>
<key>Color</key>
<dict>
<key>w</key>
<string>0</string>
</dict>
<key>Font</key>
<string>Helvetica</string>
<key>Size</key>
<real>12</real>
</dict>
<key>ID</key>
<integer>51</integer>
<key>Line</key>
<dict>
<key>ID</key>
<integer>50</integer>
<key>Position</key>
<real>0.46999874711036682</real>
<key>RotationType</key>
<integer>0</integer>
</dict>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>stroke</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170
\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 O}</string>
</dict>
<key>Wrap</key>
<string>NO</string>
</dict>
<dict>
<key>Class</key>
<string>LineGraphic</string>
<key>ID</key>
<integer>50</integer>
<key>Points</key>
<array>
<string>{329.8431396484375, 60.612242837540641}</string>
<string>{245.18111529837574, 60.612242837540641}</string>
</array>
<key>Style</key>
<dict>
<key>stroke</key>
<dict>
<key>HeadArrow</key>
<string>NonNavigable</string>
<key>Legacy</key>
<true/>
<key>LineType</key>
<integer>1</integer>
<key>TailArrow</key>
<string>0</string>
</dict>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{280.55209530438208, 70.749999613371074}, {19, 24}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>FitText</key>
<string>YES</string>
<key>Flow</key>
<string>Resize</string>
<key>FontInfo</key>
<dict>
<key>Color</key>
<dict>
<key>w</key>
<string>0</string>
</dict>
<key>Font</key>
<string>Helvetica</string>
<key>Size</key>
<real>12</real>
</dict>
<key>ID</key>
<integer>49</integer>
<key>Line</key>
<dict>
<key>ID</key>
<integer>48</integer>
<key>Position</key>
<real>0.46999874711036682</real>
<key>RotationType</key>
<integer>0</integer>
</dict>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>stroke</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170
\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 E}</string>
</dict>
<key>Wrap</key>
<string>NO</string>
</dict>
<dict>
<key>Class</key>
<string>LineGraphic</string>
<key>ID</key>
<integer>48</integer>
<key>Points</key>
<array>
<string>{329.84314158862338, 82.749999613371074}</string>
<string>{245.18111529837574, 82.749999613371074}</string>
</array>
<key>Style</key>
<dict>
<key>stroke</key>
<dict>
<key>HeadArrow</key>
<string>FilledArrow</string>
<key>Legacy</key>
<true/>
<key>LineType</key>
<integer>1</integer>
<key>TailArrow</key>
<string>0</string>
</dict>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{329.84315457120567, 27.964286256094354}, {54, 79.897956848144531}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>10</integer>
<key>Magnets</key>
<array>
<string>{0, 1}</string>
<string>{0, -1}</string>
<string>{1, 0}</string>
<string>{-1, 0}</string>
</array>
<key>Shape</key>
<string>Cylinder</string>
<key>Style</key>
<dict/>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170
\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
\f0\fs20 \cf0 Journal}</string>
<key>VerticalPad</key>
<integer>0</integer>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{187.09438968957969, 27.964285076097411}, {57.586738586425781, 79.897956848144531}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>13</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170
\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 Event\
Adapter}</string>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{9.9872450012231155, 51.61224533855227}, {102.19643402099609, 45.275508880615234}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>1</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170
\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 PersistentActor}</string>
</dict>
</dict>
</array>
<key>GridInfo</key>
<dict/>
<key>GuidesLocked</key>
<string>NO</string>
<key>GuidesVisible</key>
<string>YES</string>
<key>HPages</key>
<integer>1</integer>
<key>ImageCounter</key>
<integer>1</integer>
<key>KeepToScale</key>
<false/>
<key>Layers</key>
<array>
<dict>
<key>Lock</key>
<string>NO</string>
<key>Name</key>
<string>Layer 1</string>
<key>Print</key>
<string>YES</string>
<key>View</key>
<string>YES</string>
</dict>
</array>
<key>LayoutInfo</key>
<dict>
<key>Animate</key>
<string>NO</string>
<key>circoMinDist</key>
<real>18</real>
<key>circoSeparation</key>
<real>0.0</real>
<key>layoutEngine</key>
<string>dot</string>
<key>neatoSeparation</key>
<real>0.0</real>
<key>twopiSeparation</key>
<real>0.0</real>
</dict>
<key>LinksVisible</key>
<string>NO</string>
<key>MagnetsVisible</key>
<string>NO</string>
<key>MasterSheets</key>
<array/>
<key>ModificationDate</key>
<string>2015-07-24 10:59:39 +0000</string>
<key>Modifier</key>
<string>Konrad Malawski</string>
<key>NotesVisible</key>
<string>NO</string>
<key>Orientation</key>
<integer>2</integer>
<key>OriginVisible</key>
<string>NO</string>
<key>PageBreaks</key>
<string>YES</string>
<key>PrintInfo</key>
<dict>
<key>NSBottomMargin</key>
<array>
<string>float</string>
<string>41</string>
</array>
<key>NSHorizonalPagination</key>
<array>
<string>coded</string>
<string>BAtzdHJlYW10eXBlZIHoA4QBQISEhAhOU051bWJlcgCEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAFxlwCG</string>
</array>
<key>NSLeftMargin</key>
<array>
<string>float</string>
<string>18</string>
</array>
<key>NSPaperSize</key>
<array>
<string>size</string>
<string>{595.28997802734375, 841.8900146484375}</string>
</array>
<key>NSPrintReverseOrientation</key>
<array>
<string>int</string>
<string>0</string>
</array>
<key>NSRightMargin</key>
<array>
<string>float</string>
<string>18</string>
</array>
<key>NSTopMargin</key>
<array>
<string>float</string>
<string>18</string>
</array>
</dict>
<key>PrintOnePage</key>
<false/>
<key>ReadOnly</key>
<string>NO</string>
<key>RowAlign</key>
<integer>1</integer>
<key>RowSpacing</key>
<real>36</real>
<key>SheetTitle</key>
<string>Canvas 1</string>
<key>SmartAlignmentGuidesActive</key>
<string>YES</string>
<key>SmartDistanceGuidesActive</key>
<string>YES</string>
<key>UniqueID</key>
<integer>1</integer>
<key>UseEntirePage</key>
<false/>
<key>VPages</key>
<integer>1</integer>
<key>WindowInfo</key>
<dict>
<key>CurrentSheet</key>
<integer>0</integer>
<key>ExpandedCanvases</key>
<array>
<dict>
<key>name</key>
<string>Canvas 1</string>
</dict>
</array>
<key>FitInWindow</key>
<true/>
<key>Frame</key>
<string>{{323, 0}, {1920, 1417}}</string>
<key>ListView</key>
<true/>
<key>OutlineWidth</key>
<integer>142</integer>
<key>RightSidebar</key>
<false/>
<key>ShowRuler</key>
<true/>
<key>Sidebar</key>
<true/>
<key>SidebarWidth</key>
<integer>120</integer>
<key>VisibleRegion</key>
<string>{{-268, 0}, {1096.199978169217, 782.99998440658374}}</string>
<key>Zoom</key>
<real>1.6283525228500366</real>
<key>ZoomValues</key>
<array>
<array>
<string>Canvas 1</string>
<real>0.0</real>
<real>1</real>
</array>
</array>
</dict>
</dict>
</plist>

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 5.6 KiB

View file

@ -0,0 +1,493 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>ActiveLayerIndex</key>
<integer>0</integer>
<key>ApplicationVersion</key>
<array>
<string>com.omnigroup.OmniGrafflePro</string>
<string>139.18.0.187838</string>
</array>
<key>AutoAdjust</key>
<true/>
<key>BackgroundGraphic</key>
<dict>
<key>Bounds</key>
<string>{{0, 0}, {559.28997802734375, 782.8900146484375}}</string>
<key>Class</key>
<string>SolidGraphic</string>
<key>ID</key>
<integer>2</integer>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>stroke</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
</dict>
<key>BaseZoom</key>
<integer>0</integer>
<key>CanvasOrigin</key>
<string>{0, 0}</string>
<key>ColumnAlign</key>
<integer>1</integer>
<key>ColumnSpacing</key>
<real>36</real>
<key>CreationDate</key>
<string>2015-07-23 08:51:08 +0000</string>
<key>Creator</key>
<string>Konrad Malawski</string>
<key>DisplayScale</key>
<string>1 0/72 in = 1.0000 in</string>
<key>GraphDocumentVersion</key>
<integer>8</integer>
<key>GraphicsList</key>
<array>
<dict>
<key>Bounds</key>
<string>{{329.84315457120567, 27.964286256094354}, {54, 79.897956848144531}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>10</integer>
<key>Magnets</key>
<array>
<string>{0, 1}</string>
<string>{0, -1}</string>
<string>{1, 0}</string>
<string>{-1, 0}</string>
</array>
<key>Shape</key>
<string>Cylinder</string>
<key>Style</key>
<dict/>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170
\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
\f0\fs20 \cf0 Journal}</string>
<key>VerticalPad</key>
<integer>0</integer>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{144.29847089815703, 62.227041518775934}, {17, 24}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>FitText</key>
<string>YES</string>
<key>Flow</key>
<string>Resize</string>
<key>FontInfo</key>
<dict>
<key>Color</key>
<dict>
<key>w</key>
<string>0</string>
</dict>
<key>Font</key>
<string>Helvetica</string>
<key>Size</key>
<real>12</real>
</dict>
<key>ID</key>
<integer>46</integer>
<key>Line</key>
<dict>
<key>ID</key>
<integer>43</integer>
<key>Offset</key>
<real>-3.9948978424072266</real>
<key>Position</key>
<real>0.46160221099853516</real>
<key>RotationType</key>
<integer>0</integer>
</dict>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>stroke</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170
\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 n}</string>
</dict>
<key>Wrap</key>
<string>NO</string>
</dict>
<dict>
<key>Bounds</key>
<string>{{281.55210828696437, 55.91326468016662}, {17, 24}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>FitText</key>
<string>YES</string>
<key>Flow</key>
<string>Resize</string>
<key>FontInfo</key>
<dict>
<key>Color</key>
<dict>
<key>w</key>
<string>0</string>
</dict>
<key>Font</key>
<string>Helvetica</string>
<key>Size</key>
<real>12</real>
</dict>
<key>ID</key>
<integer>45</integer>
<key>Line</key>
<dict>
<key>ID</key>
<integer>39</integer>
<key>Position</key>
<real>0.46999874711036682</real>
<key>RotationType</key>
<integer>0</integer>
</dict>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>stroke</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170
\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 1}</string>
</dict>
<key>Wrap</key>
<string>NO</string>
</dict>
<dict>
<key>Class</key>
<string>LineGraphic</string>
<key>ID</key>
<integer>44</integer>
<key>Points</key>
<array>
<string>{187.23724704207191, 79.232143676368707}</string>
<string>{113.32653634095871, 79.232143676368707}</string>
</array>
<key>Style</key>
<dict>
<key>stroke</key>
<dict>
<key>HeadArrow</key>
<string>FilledArrow</string>
<key>Legacy</key>
<true/>
<key>LineType</key>
<integer>1</integer>
<key>TailArrow</key>
<string>0</string>
</dict>
</dict>
</dict>
<dict>
<key>Class</key>
<string>LineGraphic</string>
<key>ID</key>
<integer>43</integer>
<key>Points</key>
<array>
<string>{186.91581837426398, 70.232143676368707}</string>
<string>{113.00510767315077, 70.232143676368707}</string>
</array>
<key>Style</key>
<dict>
<key>stroke</key>
<dict>
<key>HeadArrow</key>
<string>FilledArrow</string>
<key>Legacy</key>
<true/>
<key>LineType</key>
<integer>1</integer>
<key>TailArrow</key>
<string>0</string>
</dict>
</dict>
</dict>
<dict>
<key>Class</key>
<string>LineGraphic</string>
<key>Head</key>
<dict>
<key>ID</key>
<integer>13</integer>
</dict>
<key>ID</key>
<integer>39</integer>
<key>Points</key>
<array>
<string>{329.84315457120567, 67.91326468016662}</string>
<string>{245.18112828095803, 67.91326468016662}</string>
</array>
<key>Style</key>
<dict>
<key>stroke</key>
<dict>
<key>HeadArrow</key>
<string>FilledArrow</string>
<key>Legacy</key>
<true/>
<key>LineType</key>
<integer>1</integer>
<key>TailArrow</key>
<string>0</string>
</dict>
</dict>
<key>Tail</key>
<dict>
<key>ID</key>
<integer>10</integer>
<key>Info</key>
<integer>4</integer>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{187.09438968957969, 27.964285076097411}, {57.586738586425781, 79.897956848144531}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>13</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170
\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 Event\
Adapter}</string>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{9.9872450012231155, 51.61224533855227}, {102.19643402099609, 45.275508880615234}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>1</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170
\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 PersistentActor}</string>
</dict>
</dict>
</array>
<key>GridInfo</key>
<dict/>
<key>GuidesLocked</key>
<string>NO</string>
<key>GuidesVisible</key>
<string>YES</string>
<key>HPages</key>
<integer>1</integer>
<key>ImageCounter</key>
<integer>1</integer>
<key>KeepToScale</key>
<false/>
<key>Layers</key>
<array>
<dict>
<key>Lock</key>
<string>NO</string>
<key>Name</key>
<string>Layer 1</string>
<key>Print</key>
<string>YES</string>
<key>View</key>
<string>YES</string>
</dict>
</array>
<key>LayoutInfo</key>
<dict>
<key>Animate</key>
<string>NO</string>
<key>circoMinDist</key>
<real>18</real>
<key>circoSeparation</key>
<real>0.0</real>
<key>layoutEngine</key>
<string>dot</string>
<key>neatoSeparation</key>
<real>0.0</real>
<key>twopiSeparation</key>
<real>0.0</real>
</dict>
<key>LinksVisible</key>
<string>NO</string>
<key>MagnetsVisible</key>
<string>NO</string>
<key>MasterSheets</key>
<array/>
<key>ModificationDate</key>
<string>2015-07-23 12:19:58 +0000</string>
<key>Modifier</key>
<string>Konrad Malawski</string>
<key>NotesVisible</key>
<string>NO</string>
<key>Orientation</key>
<integer>2</integer>
<key>OriginVisible</key>
<string>NO</string>
<key>PageBreaks</key>
<string>YES</string>
<key>PrintInfo</key>
<dict>
<key>NSBottomMargin</key>
<array>
<string>float</string>
<string>41</string>
</array>
<key>NSHorizonalPagination</key>
<array>
<string>coded</string>
<string>BAtzdHJlYW10eXBlZIHoA4QBQISEhAhOU051bWJlcgCEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAFxlwCG</string>
</array>
<key>NSLeftMargin</key>
<array>
<string>float</string>
<string>18</string>
</array>
<key>NSPaperSize</key>
<array>
<string>size</string>
<string>{595.28997802734375, 841.8900146484375}</string>
</array>
<key>NSPrintReverseOrientation</key>
<array>
<string>int</string>
<string>0</string>
</array>
<key>NSRightMargin</key>
<array>
<string>float</string>
<string>18</string>
</array>
<key>NSTopMargin</key>
<array>
<string>float</string>
<string>18</string>
</array>
</dict>
<key>PrintOnePage</key>
<false/>
<key>ReadOnly</key>
<string>NO</string>
<key>RowAlign</key>
<integer>1</integer>
<key>RowSpacing</key>
<real>36</real>
<key>SheetTitle</key>
<string>Canvas 1</string>
<key>SmartAlignmentGuidesActive</key>
<string>YES</string>
<key>SmartDistanceGuidesActive</key>
<string>YES</string>
<key>UniqueID</key>
<integer>1</integer>
<key>UseEntirePage</key>
<false/>
<key>VPages</key>
<integer>1</integer>
<key>WindowInfo</key>
<dict>
<key>CurrentSheet</key>
<integer>0</integer>
<key>ExpandedCanvases</key>
<array>
<dict>
<key>name</key>
<string>Canvas 1</string>
</dict>
</array>
<key>FitInWindow</key>
<true/>
<key>Frame</key>
<string>{{288, 79}, {1404, 1318}}</string>
<key>ListView</key>
<true/>
<key>OutlineWidth</key>
<integer>142</integer>
<key>RightSidebar</key>
<false/>
<key>ShowRuler</key>
<true/>
<key>Sidebar</key>
<true/>
<key>SidebarWidth</key>
<integer>120</integer>
<key>VisibleRegion</key>
<string>{{-142, 0}, {844.92092710347549, 783.00000809589221}}</string>
<key>Zoom</key>
<real>1.5019156932830811</real>
<key>ZoomValues</key>
<array>
<array>
<string>Canvas 1</string>
<real>0.0</real>
<real>1</real>
</array>
</array>
</dict>
</dict>
</plist>

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 5.1 KiB

View file

@ -0,0 +1,680 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>ActiveLayerIndex</key>
<integer>0</integer>
<key>ApplicationVersion</key>
<array>
<string>com.omnigroup.OmniGraffle.MacAppStore</string>
<string>139.18</string>
</array>
<key>AutoAdjust</key>
<true/>
<key>BackgroundGraphic</key>
<dict>
<key>Bounds</key>
<string>{{0, 0}, {559.28997802734375, 782.8900146484375}}</string>
<key>Class</key>
<string>SolidGraphic</string>
<key>ID</key>
<integer>2</integer>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>stroke</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
</dict>
<key>BaseZoom</key>
<integer>0</integer>
<key>CanvasOrigin</key>
<string>{0, 0}</string>
<key>ColumnAlign</key>
<integer>1</integer>
<key>ColumnSpacing</key>
<real>36</real>
<key>CreationDate</key>
<string>2015-07-23 08:51:08 +0000</string>
<key>Creator</key>
<string>Konrad Malawski</string>
<key>DisplayScale</key>
<string>1 0/72 in = 1.0000 in</string>
<key>GraphDocumentVersion</key>
<integer>8</integer>
<key>GraphicsList</key>
<array>
<dict>
<key>Bounds</key>
<string>{{156.34123947922424, 144.36435961675622}, {30, 24}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>FitText</key>
<string>YES</string>
<key>Flow</key>
<string>Resize</string>
<key>FontInfo</key>
<dict>
<key>Color</key>
<dict>
<key>w</key>
<string>0</string>
</dict>
<key>Font</key>
<string>Helvetica</string>
<key>Size</key>
<real>12</real>
</dict>
<key>ID</key>
<integer>69</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>stroke</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170
\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 [v2]}</string>
</dict>
<key>Wrap</key>
<string>NO</string>
</dict>
<dict>
<key>Bounds</key>
<string>{{140.17231558676406, 124.47240374005878}, {57, 24}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>FitText</key>
<string>YES</string>
<key>Flow</key>
<string>Resize</string>
<key>FontInfo</key>
<dict>
<key>Color</key>
<dict>
<key>w</key>
<string>0</string>
</dict>
<key>Font</key>
<string>Helvetica</string>
<key>Size</key>
<real>12</real>
</dict>
<key>ID</key>
<integer>68</integer>
<key>Line</key>
<dict>
<key>ID</key>
<integer>67</integer>
<key>Position</key>
<real>0.43243709206581116</real>
<key>RotationType</key>
<integer>0</integer>
</dict>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>stroke</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170
\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 A.seatNr}</string>
</dict>
<key>Wrap</key>
<string>NO</string>
</dict>
<dict>
<key>Class</key>
<string>LineGraphic</string>
<key>ID</key>
<integer>67</integer>
<key>Points</key>
<array>
<string>{208.32634070768711, 136.35918075415361}</string>
<string>{116.62739570856519, 136.62100608778607}</string>
</array>
<key>Style</key>
<dict>
<key>stroke</key>
<dict>
<key>HeadArrow</key>
<string>FilledArrow</string>
<key>Legacy</key>
<true/>
<key>LineType</key>
<integer>1</integer>
<key>TailArrow</key>
<string>0</string>
</dict>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{283.60994305394411, 125.36436946675957}, {57, 38}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>FitText</key>
<string>YES</string>
<key>Flow</key>
<string>Resize</string>
<key>FontInfo</key>
<dict>
<key>Color</key>
<dict>
<key>w</key>
<string>0</string>
</dict>
<key>Font</key>
<string>Helvetica</string>
<key>Size</key>
<real>12</real>
</dict>
<key>ID</key>
<integer>66</integer>
<key>Line</key>
<dict>
<key>ID</key>
<integer>65</integer>
<key>Offset</key>
<real>2.7059365947934566e-07</real>
<key>Position</key>
<real>0.46274498105049133</real>
<key>RotationType</key>
<integer>0</integer>
</dict>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>stroke</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170
\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 A.seatNr\
[v2]}</string>
</dict>
<key>Wrap</key>
<string>NO</string>
</dict>
<dict>
<key>Class</key>
<string>LineGraphic</string>
<key>ID</key>
<integer>65</integer>
<key>Points</key>
<array>
<string>{351.286868282196, 144.36436973735323}</string>
<string>{266.6248419919483, 144.36436973735323}</string>
</array>
<key>Style</key>
<dict>
<key>stroke</key>
<dict>
<key>HeadArrow</key>
<string>FilledArrow</string>
<key>Legacy</key>
<true/>
<key>LineType</key>
<integer>1</integer>
<key>TailArrow</key>
<string>0</string>
</dict>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{139.9605523938219, 107.01448443883029}, {57, 24}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>FitText</key>
<string>YES</string>
<key>Flow</key>
<string>Resize</string>
<key>FontInfo</key>
<dict>
<key>Color</key>
<dict>
<key>w</key>
<string>0</string>
</dict>
<key>Font</key>
<string>Helvetica</string>
<key>Size</key>
<real>12</real>
</dict>
<key>ID</key>
<integer>55</integer>
<key>Line</key>
<dict>
<key>ID</key>
<integer>54</integer>
<key>Position</key>
<real>0.43243709206581116</real>
<key>RotationType</key>
<integer>0</integer>
</dict>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>stroke</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170
\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 A.seatNr}</string>
</dict>
<key>Wrap</key>
<string>NO</string>
</dict>
<dict>
<key>Class</key>
<string>LineGraphic</string>
<key>ID</key>
<integer>54</integer>
<key>Points</key>
<array>
<string>{208.11457852770752, 119.3142831598844}</string>
<string>{116.41563118613487, 118.62100608778607}</string>
</array>
<key>Style</key>
<dict>
<key>stroke</key>
<dict>
<key>HeadArrow</key>
<string>FilledArrow</string>
<key>Legacy</key>
<true/>
<key>LineType</key>
<integer>1</integer>
<key>TailArrow</key>
<string>0</string>
</dict>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{287.89817853151374, 80.152605485515707}, {48, 38}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>FitText</key>
<string>YES</string>
<key>Flow</key>
<string>Resize</string>
<key>FontInfo</key>
<dict>
<key>Color</key>
<dict>
<key>w</key>
<string>0</string>
</dict>
<key>Font</key>
<string>Helvetica</string>
<key>Size</key>
<real>12</real>
</dict>
<key>ID</key>
<integer>60</integer>
<key>Line</key>
<dict>
<key>ID</key>
<integer>59</integer>
<key>Offset</key>
<real>-2.7059365947934566e-07</real>
<key>Position</key>
<real>0.46274498105049133</real>
<key>RotationType</key>
<integer>0</integer>
</dict>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>stroke</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170
\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 A.code\
[v1]}</string>
</dict>
<key>Wrap</key>
<string>NO</string>
</dict>
<dict>
<key>Class</key>
<string>LineGraphic</string>
<key>ID</key>
<integer>59</integer>
<key>Points</key>
<array>
<string>{351.07510375976562, 99.152605214922048}</string>
<string>{266.41307746951793, 99.152605214922048}</string>
</array>
<key>Style</key>
<dict>
<key>stroke</key>
<dict>
<key>HeadArrow</key>
<string>FilledArrow</string>
<key>Legacy</key>
<true/>
<key>LineType</key>
<integer>1</integer>
<key>TailArrow</key>
<string>0</string>
</dict>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{351.07510558931313, 79.835293707727061}, {54, 79.897956848144531}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>10</integer>
<key>Magnets</key>
<array>
<string>{0, 1}</string>
<string>{0, -1}</string>
<string>{1, 0}</string>
<string>{-1, 0}</string>
</array>
<key>Shape</key>
<string>Cylinder</string>
<key>Style</key>
<dict/>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170
\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
\f0\fs20 \cf0 Journal}</string>
<key>VerticalPad</key>
<integer>0</integer>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{208.32634070768711, 79.835292527730118}, {57.586738586425781, 79.897956848144531}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>61</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170
\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs22 \cf0 Serializer}</string>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{13.219196019330578, 103.48325279018498}, {102.19643402099609, 45.275508880615234}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>1</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170
\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 PersistentActor}</string>
</dict>
</dict>
</array>
<key>GridInfo</key>
<dict/>
<key>GuidesLocked</key>
<string>NO</string>
<key>GuidesVisible</key>
<string>YES</string>
<key>HPages</key>
<integer>1</integer>
<key>ImageCounter</key>
<integer>1</integer>
<key>KeepToScale</key>
<false/>
<key>Layers</key>
<array>
<dict>
<key>Lock</key>
<string>NO</string>
<key>Name</key>
<string>Layer 1</string>
<key>Print</key>
<string>YES</string>
<key>View</key>
<string>YES</string>
</dict>
</array>
<key>LayoutInfo</key>
<dict>
<key>Animate</key>
<string>NO</string>
<key>circoMinDist</key>
<real>18</real>
<key>circoSeparation</key>
<real>0.0</real>
<key>layoutEngine</key>
<string>dot</string>
<key>neatoSeparation</key>
<real>0.0</real>
<key>twopiSeparation</key>
<real>0.0</real>
</dict>
<key>LinksVisible</key>
<string>NO</string>
<key>MagnetsVisible</key>
<string>NO</string>
<key>MasterSheets</key>
<array/>
<key>ModificationDate</key>
<string>2015-08-13 10:04:11 +0000</string>
<key>Modifier</key>
<string>Konrad Malawski</string>
<key>NotesVisible</key>
<string>NO</string>
<key>Orientation</key>
<integer>2</integer>
<key>OriginVisible</key>
<string>NO</string>
<key>PageBreaks</key>
<string>YES</string>
<key>PrintInfo</key>
<dict>
<key>NSBottomMargin</key>
<array>
<string>float</string>
<string>41</string>
</array>
<key>NSHorizonalPagination</key>
<array>
<string>coded</string>
<string>BAtzdHJlYW10eXBlZIHoA4QBQISEhAhOU051bWJlcgCEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAFxlwCG</string>
</array>
<key>NSLeftMargin</key>
<array>
<string>float</string>
<string>18</string>
</array>
<key>NSPaperSize</key>
<array>
<string>size</string>
<string>{595.28997802734375, 841.8900146484375}</string>
</array>
<key>NSPrintReverseOrientation</key>
<array>
<string>int</string>
<string>0</string>
</array>
<key>NSRightMargin</key>
<array>
<string>float</string>
<string>18</string>
</array>
<key>NSTopMargin</key>
<array>
<string>float</string>
<string>18</string>
</array>
</dict>
<key>PrintOnePage</key>
<false/>
<key>ReadOnly</key>
<string>NO</string>
<key>RowAlign</key>
<integer>1</integer>
<key>RowSpacing</key>
<real>36</real>
<key>SheetTitle</key>
<string>Canvas 1</string>
<key>SmartAlignmentGuidesActive</key>
<string>YES</string>
<key>SmartDistanceGuidesActive</key>
<string>YES</string>
<key>UniqueID</key>
<integer>1</integer>
<key>UseEntirePage</key>
<false/>
<key>VPages</key>
<integer>1</integer>
<key>WindowInfo</key>
<dict>
<key>CurrentSheet</key>
<integer>0</integer>
<key>ExpandedCanvases</key>
<array>
<dict>
<key>name</key>
<string>Canvas 1</string>
</dict>
</array>
<key>FitInWindow</key>
<true/>
<key>Frame</key>
<string>{{4, 0}, {1436, 877}}</string>
<key>ListView</key>
<true/>
<key>OutlineWidth</key>
<integer>142</integer>
<key>RightSidebar</key>
<false/>
<key>ShowRuler</key>
<true/>
<key>Sidebar</key>
<true/>
<key>SidebarWidth</key>
<integer>120</integer>
<key>VisibleRegion</key>
<string>{{-413, 0}, {1385.9632356340144, 782.9999832367414}}</string>
<key>Zoom</key>
<real>0.93869733810424805</real>
<key>ZoomValues</key>
<array>
<array>
<string>Canvas 1</string>
<real>0.0</real>
<real>1</real>
</array>
</array>
</dict>
</dict>
</plist>

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View file

@ -0,0 +1,679 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>ActiveLayerIndex</key>
<integer>0</integer>
<key>ApplicationVersion</key>
<array>
<string>com.omnigroup.OmniGraffle.MacAppStore</string>
<string>139.18</string>
</array>
<key>AutoAdjust</key>
<true/>
<key>BackgroundGraphic</key>
<dict>
<key>Bounds</key>
<string>{{0, 0}, {559.28997802734375, 782.8900146484375}}</string>
<key>Class</key>
<string>SolidGraphic</string>
<key>ID</key>
<integer>2</integer>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>stroke</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
</dict>
<key>BaseZoom</key>
<integer>0</integer>
<key>CanvasOrigin</key>
<string>{0, 0}</string>
<key>ColumnAlign</key>
<integer>1</integer>
<key>ColumnSpacing</key>
<real>36</real>
<key>CreationDate</key>
<string>2015-07-23 08:51:08 +0000</string>
<key>Creator</key>
<string>Konrad Malawski</string>
<key>DisplayScale</key>
<string>1 0/72 in = 1.0000 in</string>
<key>GraphDocumentVersion</key>
<integer>8</integer>
<key>GraphicsList</key>
<array>
<dict>
<key>Bounds</key>
<string>{{140.17231558676406, 124.47240374005878}, {57, 24}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>FitText</key>
<string>YES</string>
<key>Flow</key>
<string>Resize</string>
<key>FontInfo</key>
<dict>
<key>Color</key>
<dict>
<key>w</key>
<string>0</string>
</dict>
<key>Font</key>
<string>Helvetica</string>
<key>Size</key>
<real>12</real>
</dict>
<key>ID</key>
<integer>68</integer>
<key>Line</key>
<dict>
<key>ID</key>
<integer>67</integer>
<key>Position</key>
<real>0.43243709206581116</real>
<key>RotationType</key>
<integer>0</integer>
</dict>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>stroke</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170
\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 A.seatNr}</string>
</dict>
<key>Wrap</key>
<string>NO</string>
</dict>
<dict>
<key>Class</key>
<string>LineGraphic</string>
<key>ID</key>
<integer>67</integer>
<key>Points</key>
<array>
<string>{208.32634070768711, 136.35918075415361}</string>
<string>{116.62739570856519, 136.62100608778607}</string>
</array>
<key>Style</key>
<dict>
<key>stroke</key>
<dict>
<key>HeadArrow</key>
<string>FilledArrow</string>
<key>Legacy</key>
<true/>
<key>LineType</key>
<integer>1</integer>
<key>TailArrow</key>
<string>0</string>
</dict>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{283.60994305394411, 123.36436973735323}, {57, 24}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>FitText</key>
<string>YES</string>
<key>Flow</key>
<string>Resize</string>
<key>FontInfo</key>
<dict>
<key>Color</key>
<dict>
<key>w</key>
<string>0</string>
</dict>
<key>Font</key>
<string>Helvetica</string>
<key>Size</key>
<real>12</real>
</dict>
<key>ID</key>
<integer>66</integer>
<key>Line</key>
<dict>
<key>ID</key>
<integer>65</integer>
<key>Position</key>
<real>0.46274498105049133</real>
<key>RotationType</key>
<integer>0</integer>
</dict>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>stroke</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170
\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 A.seatNr}</string>
</dict>
<key>Wrap</key>
<string>NO</string>
</dict>
<dict>
<key>Class</key>
<string>LineGraphic</string>
<key>ID</key>
<integer>65</integer>
<key>Points</key>
<array>
<string>{351.286868282196, 135.36436973735323}</string>
<string>{266.6248419919483, 135.36436973735323}</string>
</array>
<key>Style</key>
<dict>
<key>stroke</key>
<dict>
<key>HeadArrow</key>
<string>FilledArrow</string>
<key>Legacy</key>
<true/>
<key>LineType</key>
<integer>1</integer>
<key>TailArrow</key>
<string>0</string>
</dict>
</dict>
</dict>
<dict>
<key>Class</key>
<string>LineGraphic</string>
<key>Head</key>
<dict>
<key>ID</key>
<integer>61</integer>
</dict>
<key>ID</key>
<integer>63</integer>
<key>Points</key>
<array>
<string>{237.119717968369, 50.243527827595514}</string>
<string>{237.119717968369, 79.335292523504918}</string>
</array>
<key>Style</key>
<dict>
<key>stroke</key>
<dict>
<key>HeadArrow</key>
<string>FilledArrow</string>
<key>Legacy</key>
<true/>
<key>LineType</key>
<integer>1</integer>
<key>TailArrow</key>
<string>FilledArrow</string>
</dict>
</dict>
<key>Tail</key>
<dict>
<key>ID</key>
<integer>56</integer>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{183.40465009683402, 20.265881949346891}, {107.43011379637244, 29.477645874023438}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>56</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170
\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 Protocol\
IDL}</string>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{139.9605523938219, 107.01448443883029}, {57, 24}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>FitText</key>
<string>YES</string>
<key>Flow</key>
<string>Resize</string>
<key>FontInfo</key>
<dict>
<key>Color</key>
<dict>
<key>w</key>
<string>0</string>
</dict>
<key>Font</key>
<string>Helvetica</string>
<key>Size</key>
<real>12</real>
</dict>
<key>ID</key>
<integer>55</integer>
<key>Line</key>
<dict>
<key>ID</key>
<integer>54</integer>
<key>Position</key>
<real>0.43243709206581116</real>
<key>RotationType</key>
<integer>0</integer>
</dict>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>stroke</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170
\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 A.seatNr}</string>
</dict>
<key>Wrap</key>
<string>NO</string>
</dict>
<dict>
<key>Class</key>
<string>LineGraphic</string>
<key>ID</key>
<integer>54</integer>
<key>Points</key>
<array>
<string>{208.11457852770752, 119.3142831598844}</string>
<string>{116.41563118613487, 118.62100608778607}</string>
</array>
<key>Style</key>
<dict>
<key>stroke</key>
<dict>
<key>HeadArrow</key>
<string>FilledArrow</string>
<key>Legacy</key>
<true/>
<key>LineType</key>
<integer>1</integer>
<key>TailArrow</key>
<string>0</string>
</dict>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{287.89817853151374, 96.152605214922048}, {48, 24}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>FitText</key>
<string>YES</string>
<key>Flow</key>
<string>Resize</string>
<key>FontInfo</key>
<dict>
<key>Color</key>
<dict>
<key>w</key>
<string>0</string>
</dict>
<key>Font</key>
<string>Helvetica</string>
<key>Size</key>
<real>12</real>
</dict>
<key>ID</key>
<integer>60</integer>
<key>Line</key>
<dict>
<key>ID</key>
<integer>59</integer>
<key>Position</key>
<real>0.46274498105049133</real>
<key>RotationType</key>
<integer>0</integer>
</dict>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>stroke</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170
\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 A.code}</string>
</dict>
<key>Wrap</key>
<string>NO</string>
</dict>
<dict>
<key>Class</key>
<string>LineGraphic</string>
<key>ID</key>
<integer>59</integer>
<key>Points</key>
<array>
<string>{351.07510375976562, 108.15260521492205}</string>
<string>{266.41307746951793, 108.15260521492205}</string>
</array>
<key>Style</key>
<dict>
<key>stroke</key>
<dict>
<key>HeadArrow</key>
<string>FilledArrow</string>
<key>Legacy</key>
<true/>
<key>LineType</key>
<integer>1</integer>
<key>TailArrow</key>
<string>0</string>
</dict>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{351.07510558931313, 79.835293707727061}, {54, 79.897956848144531}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>10</integer>
<key>Magnets</key>
<array>
<string>{0, 1}</string>
<string>{0, -1}</string>
<string>{1, 0}</string>
<string>{-1, 0}</string>
</array>
<key>Shape</key>
<string>Cylinder</string>
<key>Style</key>
<dict/>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170
\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
\f0\fs20 \cf0 Journal}</string>
<key>VerticalPad</key>
<integer>0</integer>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{208.32634070768711, 79.835292527730118}, {57.586738586425781, 79.897956848144531}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>61</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170
\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs22 \cf0 Serializer}</string>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{13.219196019330578, 103.48325279018498}, {102.19643402099609, 45.275508880615234}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>1</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170
\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 PersistentActor}</string>
</dict>
</dict>
</array>
<key>GridInfo</key>
<dict/>
<key>GuidesLocked</key>
<string>NO</string>
<key>GuidesVisible</key>
<string>YES</string>
<key>HPages</key>
<integer>1</integer>
<key>ImageCounter</key>
<integer>1</integer>
<key>KeepToScale</key>
<false/>
<key>Layers</key>
<array>
<dict>
<key>Lock</key>
<string>NO</string>
<key>Name</key>
<string>Layer 1</string>
<key>Print</key>
<string>YES</string>
<key>View</key>
<string>YES</string>
</dict>
</array>
<key>LayoutInfo</key>
<dict>
<key>Animate</key>
<string>NO</string>
<key>circoMinDist</key>
<real>18</real>
<key>circoSeparation</key>
<real>0.0</real>
<key>layoutEngine</key>
<string>dot</string>
<key>neatoSeparation</key>
<real>0.0</real>
<key>twopiSeparation</key>
<real>0.0</real>
</dict>
<key>LinksVisible</key>
<string>NO</string>
<key>MagnetsVisible</key>
<string>NO</string>
<key>MasterSheets</key>
<array/>
<key>ModificationDate</key>
<string>2015-08-13 10:00:21 +0000</string>
<key>Modifier</key>
<string>Konrad Malawski</string>
<key>NotesVisible</key>
<string>NO</string>
<key>Orientation</key>
<integer>2</integer>
<key>OriginVisible</key>
<string>NO</string>
<key>PageBreaks</key>
<string>YES</string>
<key>PrintInfo</key>
<dict>
<key>NSBottomMargin</key>
<array>
<string>float</string>
<string>41</string>
</array>
<key>NSHorizonalPagination</key>
<array>
<string>coded</string>
<string>BAtzdHJlYW10eXBlZIHoA4QBQISEhAhOU051bWJlcgCEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAFxlwCG</string>
</array>
<key>NSLeftMargin</key>
<array>
<string>float</string>
<string>18</string>
</array>
<key>NSPaperSize</key>
<array>
<string>size</string>
<string>{595.28997802734375, 841.8900146484375}</string>
</array>
<key>NSPrintReverseOrientation</key>
<array>
<string>int</string>
<string>0</string>
</array>
<key>NSRightMargin</key>
<array>
<string>float</string>
<string>18</string>
</array>
<key>NSTopMargin</key>
<array>
<string>float</string>
<string>18</string>
</array>
</dict>
<key>PrintOnePage</key>
<false/>
<key>ReadOnly</key>
<string>NO</string>
<key>RowAlign</key>
<integer>1</integer>
<key>RowSpacing</key>
<real>36</real>
<key>SheetTitle</key>
<string>Canvas 1</string>
<key>SmartAlignmentGuidesActive</key>
<string>YES</string>
<key>SmartDistanceGuidesActive</key>
<string>YES</string>
<key>UniqueID</key>
<integer>1</integer>
<key>UseEntirePage</key>
<false/>
<key>VPages</key>
<integer>1</integer>
<key>WindowInfo</key>
<dict>
<key>CurrentSheet</key>
<integer>0</integer>
<key>ExpandedCanvases</key>
<array>
<dict>
<key>name</key>
<string>Canvas 1</string>
</dict>
</array>
<key>FitInWindow</key>
<true/>
<key>Frame</key>
<string>{{4, 0}, {1436, 877}}</string>
<key>ListView</key>
<true/>
<key>OutlineWidth</key>
<integer>142</integer>
<key>RightSidebar</key>
<false/>
<key>ShowRuler</key>
<true/>
<key>Sidebar</key>
<true/>
<key>SidebarWidth</key>
<integer>120</integer>
<key>VisibleRegion</key>
<string>{{-413, 0}, {1385.9632356340144, 782.9999832367414}}</string>
<key>Zoom</key>
<real>0.93869733810424805</real>
<key>ZoomValues</key>
<array>
<array>
<string>Canvas 1</string>
<real>0.0</real>
<real>1</real>
</array>
</array>
</dict>
</dict>
</plist>

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 7 KiB

View file

@ -0,0 +1,542 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>ActiveLayerIndex</key>
<integer>0</integer>
<key>ApplicationVersion</key>
<array>
<string>com.omnigroup.OmniGrafflePro</string>
<string>139.18.0.187838</string>
</array>
<key>AutoAdjust</key>
<true/>
<key>BackgroundGraphic</key>
<dict>
<key>Bounds</key>
<string>{{0, 0}, {559.28997802734375, 782.8900146484375}}</string>
<key>Class</key>
<string>SolidGraphic</string>
<key>ID</key>
<integer>2</integer>
<key>Style</key>
<dict>
<key>shadow</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
<key>stroke</key>
<dict>
<key>Draws</key>
<string>NO</string>
</dict>
</dict>
</dict>
<key>BaseZoom</key>
<integer>0</integer>
<key>CanvasOrigin</key>
<string>{0, 0}</string>
<key>ColumnAlign</key>
<integer>1</integer>
<key>ColumnSpacing</key>
<real>36</real>
<key>CreationDate</key>
<string>2015-07-23 08:51:08 +0000</string>
<key>Creator</key>
<string>Konrad Malawski</string>
<key>DisplayScale</key>
<string>1 0/72 in = 1 0/72 in</string>
<key>GraphDocumentVersion</key>
<integer>8</integer>
<key>GraphicsList</key>
<array>
<dict>
<key>Bounds</key>
<string>{{42.612243483896464, 209.73214502568541}, {208.72704538616881, 16.645408630371094}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>77</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>fill</key>
<dict>
<key>Color</key>
<dict>
<key>b</key>
<string>0.211198</string>
<key>g</key>
<string>0.79545</string>
<key>r</key>
<string>1</string>
</dict>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170
\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 payload}</string>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{122.5076543485809, 187.0943887622513}, {128.83163452148438, 16.645408630371094}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>74</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>fill</key>
<dict>
<key>Color</key>
<dict>
<key>b</key>
<string>1</string>
<key>g</key>
<string>0.990725</string>
<key>r</key>
<string>0.795885</string>
</dict>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170
\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 payloadManifest}</string>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{42.612245338551958, 187.09438968957969}, {73.86474609375, 16.645408630371094}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>70</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>fill</key>
<dict>
<key>Color</key>
<dict>
<key>b</key>
<string>1</string>
<key>g</key>
<string>0.990725</string>
<key>r</key>
<string>0.795885</string>
</dict>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170
\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 serializerId}</string>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{34.880753086927484, 166.78699333426209}, {222.86349779925854, 65.582908630371094}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>76</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>fill</key>
<dict>
<key>Color</key>
<dict>
<key>b</key>
<string>1</string>
<key>g</key>
<string>0.992157</string>
<key>r</key>
<string>0.796078</string>
</dict>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Align</key>
<integer>0</integer>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170
\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
\f0\fs24 \cf0 PersistentPayload\
\
\
}</string>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{113.45474415668954, 146.81250404707274}, {144.28950500488281, 16.645408630371094}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>73</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>fill</key>
<dict>
<key>Color</key>
<dict>
<key>b</key>
<string>1</string>
<key>g</key>
<string>0.990725</string>
<key>r</key>
<string>0.795885</string>
</dict>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170
\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 ...}</string>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{34.880752054212735, 146.81250682905579}, {73.86474609375, 16.645408630371094}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>71</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>fill</key>
<dict>
<key>Color</key>
<dict>
<key>b</key>
<string>1</string>
<key>g</key>
<string>0.990725</string>
<key>r</key>
<string>0.795885</string>
</dict>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170
\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 manifest}</string>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{113.45474588130318, 126.83801404462653}, {144.28950500488281, 16.645408630371094}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>72</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>fill</key>
<dict>
<key>Color</key>
<dict>
<key>b</key>
<string>1</string>
<key>g</key>
<string>0.990725</string>
<key>r</key>
<string>0.795885</string>
</dict>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170
\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 persistenceId}</string>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{34.880753908867661, 126.83801682660956}, {73.86474609375, 16.645408630371094}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>69</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>fill</key>
<dict>
<key>Color</key>
<dict>
<key>b</key>
<string>1</string>
<key>g</key>
<string>0.992157</string>
<key>r</key>
<string>0.796078</string>
</dict>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170
\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
\f0\fs24 \cf0 seqNr}</string>
</dict>
</dict>
<dict>
<key>Bounds</key>
<string>{{27.303571669521091, 106.53061334638005}, {241.34693908691406, 131.16581726074219}}</string>
<key>Class</key>
<string>ShapedGraphic</string>
<key>ID</key>
<integer>75</integer>
<key>Shape</key>
<string>Rectangle</string>
<key>Style</key>
<dict>
<key>fill</key>
<dict>
<key>Color</key>
<dict>
<key>b</key>
<string>0.920143</string>
<key>g</key>
<string>0.851771</string>
<key>r</key>
<string>0.237451</string>
</dict>
</dict>
</dict>
<key>Text</key>
<dict>
<key>Align</key>
<integer>0</integer>
<key>Text</key>
<string>{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170
\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
\f0\fs24 \cf0 PersistentMessage\
\
\
\
\
\
\
\
}</string>
</dict>
</dict>
</array>
<key>GridInfo</key>
<dict/>
<key>GuidesLocked</key>
<string>NO</string>
<key>GuidesVisible</key>
<string>YES</string>
<key>HPages</key>
<integer>1</integer>
<key>ImageCounter</key>
<integer>1</integer>
<key>KeepToScale</key>
<false/>
<key>Layers</key>
<array>
<dict>
<key>Lock</key>
<string>NO</string>
<key>Name</key>
<string>Layer 1</string>
<key>Print</key>
<string>YES</string>
<key>View</key>
<string>YES</string>
</dict>
</array>
<key>LayoutInfo</key>
<dict>
<key>Animate</key>
<string>NO</string>
<key>circoMinDist</key>
<real>18</real>
<key>circoSeparation</key>
<real>0.0</real>
<key>layoutEngine</key>
<string>dot</string>
<key>neatoSeparation</key>
<real>0.0</real>
<key>twopiSeparation</key>
<real>0.0</real>
</dict>
<key>LinksVisible</key>
<string>NO</string>
<key>MagnetsVisible</key>
<string>NO</string>
<key>MasterSheets</key>
<array/>
<key>ModificationDate</key>
<string>2015-07-23 12:16:09 +0000</string>
<key>Modifier</key>
<string>Konrad Malawski</string>
<key>NotesVisible</key>
<string>NO</string>
<key>Orientation</key>
<integer>2</integer>
<key>OriginVisible</key>
<string>NO</string>
<key>PageBreaks</key>
<string>YES</string>
<key>PrintInfo</key>
<dict>
<key>NSBottomMargin</key>
<array>
<string>float</string>
<string>41</string>
</array>
<key>NSHorizonalPagination</key>
<array>
<string>coded</string>
<string>BAtzdHJlYW10eXBlZIHoA4QBQISEhAhOU051bWJlcgCEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAFxlwCG</string>
</array>
<key>NSLeftMargin</key>
<array>
<string>float</string>
<string>18</string>
</array>
<key>NSPaperSize</key>
<array>
<string>size</string>
<string>{595.28997802734375, 841.8900146484375}</string>
</array>
<key>NSPrintReverseOrientation</key>
<array>
<string>int</string>
<string>0</string>
</array>
<key>NSRightMargin</key>
<array>
<string>float</string>
<string>18</string>
</array>
<key>NSTopMargin</key>
<array>
<string>float</string>
<string>18</string>
</array>
</dict>
<key>PrintOnePage</key>
<false/>
<key>ReadOnly</key>
<string>NO</string>
<key>RowAlign</key>
<integer>1</integer>
<key>RowSpacing</key>
<real>36</real>
<key>SheetTitle</key>
<string>Canvas 1</string>
<key>SmartAlignmentGuidesActive</key>
<string>YES</string>
<key>SmartDistanceGuidesActive</key>
<string>YES</string>
<key>UniqueID</key>
<integer>1</integer>
<key>UseEntirePage</key>
<false/>
<key>VPages</key>
<integer>1</integer>
<key>WindowInfo</key>
<dict>
<key>CurrentSheet</key>
<integer>0</integer>
<key>ExpandedCanvases</key>
<array>
<dict>
<key>name</key>
<string>Canvas 1</string>
</dict>
</array>
<key>FitInWindow</key>
<true/>
<key>Frame</key>
<string>{{268, 99}, {1776, 1318}}</string>
<key>ListView</key>
<true/>
<key>OutlineWidth</key>
<integer>142</integer>
<key>RightSidebar</key>
<false/>
<key>ShowRuler</key>
<true/>
<key>Sidebar</key>
<true/>
<key>SidebarWidth</key>
<integer>120</integer>
<key>VisibleRegion</key>
<string>{{-266, 0}, {1092.6046031338085, 783.0000080958921}}</string>
<key>Zoom</key>
<real>1.5019156932830811</real>
<key>ZoomValues</key>
<array>
<array>
<string>Canvas 1</string>
<real>0.0</real>
<real>1</real>
</array>
</array>
</dict>
</dict>
</plist>

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 5.7 KiB

View file

@ -8,6 +8,8 @@ import akka.japi.Procedure;
import akka.japi.pf.ReceiveBuilder; import akka.japi.pf.ReceiveBuilder;
import akka.pattern.BackoffSupervisor; import akka.pattern.BackoffSupervisor;
import akka.persistence.*; import akka.persistence.*;
import akka.persistence.journal.EventAdapter;
import akka.persistence.journal.EventSeq;
import scala.Option; import scala.Option;
import scala.concurrent.duration.Duration; import scala.concurrent.duration.Duration;
import scala.PartialFunction; import scala.PartialFunction;

View file

@ -586,6 +586,46 @@ not accept more messages and it will throw ``AtLeastOnceDelivery.MaxUnconfirmedM
The default value can be configured with the ``akka.persistence.at-least-once-delivery.max-unconfirmed-messages`` The default value can be configured with the ``akka.persistence.at-least-once-delivery.max-unconfirmed-messages``
configuration key. The method can be overridden by implementation classes to return non-default values. configuration key. The method can be overridden by implementation classes to return non-default values.
.. _event-adapters-lambda:
Event Adapters
==============
In long running projects using event sourcing sometimes the need arises to detach the data model from the domain model
completely.
Event Adapters help in situations where:
- **Version Migrations** existing events stored in *Version 1* should be "upcasted" to a new *Version 2* representation,
and the process of doing so involves actual code, not just changes on the serialization layer. For these scenarios
the ``toJournal`` function is usually an identity function, however the ``fromJournal`` is implemented as
``v1.Event=>v2.Event``, performing the neccessary mapping inside the fromJournal method.
This technique is sometimes refered to as "upcasting" in other CQRS libraries.
- **Separating Domain and Data models** thanks to EventAdapters it is possible to completely separate the domain model
from the model used to persist data in the Journals. For example one may want to use case classes in the
domain model, however persist their protocol-buffer (or any other binary serialization format) counter-parts to the Journal.
A simple ``toJournal:MyModel=>MyDataModel`` and ``fromJournal:MyDataModel=>MyModel`` adapter can be used to implement this feature.
- **Journal Specialized Data Types** exposing data types understood by the underlying Journal, for example for data stores which
understand JSON it is possible to write an EventAdapter ``toJournal:Any=>JSON`` such that the Journal can *directly* store the
json instead of serializing the object to its binary representation.
Implementing an EventAdapter is rather stright forward:
.. includecode:: code/docs/persistence/PersistenceEventAdapterDocTest.java#identity-event-adapter
Then in order for it to be used on events coming to and from the journal you must bind it using the below configuration syntax:
.. includecode:: ../scala/code/docs/persistence/PersistenceEventAdapterDocSpec.scala#event-adapters-config
It is possible to bind multiple adapters to one class *for recovery*, in which case the ``fromJournal`` methods of all
bound adapters will be applied to a given matching event (in order of definition in the configuration). Since each adapter may
return from ``0`` to ``n`` adapted events (called as ``EventSeq``), each adapter can investigate the event and if it should
indeed adapt it return the adapted event(s) for it, other adapters which do not have anything to contribute during this
adaptation simply return ``EventSeq.empty``. The adapted events are then delivered in-order to the ``PersistentActor`` during replay.
.. note::
For more advanced schema evolution techniques refer to the :ref:`persistence-schema-evolution-scala` documentation.
.. _persistent-fsm-java-lambda: .. _persistent-fsm-java-lambda:
Persistent FSM Persistent FSM
@ -794,6 +834,8 @@ it must add
to the application configuration. If not specified, a default serializer is used. to the application configuration. If not specified, a default serializer is used.
For more advanced schema evolution techniques refer to the :ref:`persistence-schema-evolution-scala` documentation.
Testing Testing
======= =======

View file

@ -601,10 +601,6 @@ configuration key. The method can be overridden by implementation classes to ret
Event Adapters Event Adapters
============== ==============
.. note::
Complete documentation featuring use-cases and implementation examples for this feature will follow shortly.
In long running projects using event sourcing sometimes the need arises to detach the data model from the domain model In long running projects using event sourcing sometimes the need arises to detach the data model from the domain model
completely. completely.
@ -638,11 +634,7 @@ indeed adapt it return the adapted event(s) for it, other adapters which do not
adaptation simply return ``EventSeq.empty``. The adapted events are then delivered in-order to the ``PersistentActor`` during replay. adaptation simply return ``EventSeq.empty``. The adapted events are then delivered in-order to the ``PersistentActor`` during replay.
.. note:: .. note::
More advanced techniques utilising advanced binary serialization formats such as protocol buffers or kryo / thrift / avro For more advanced schema evolution techniques refer to the :ref:`persistence-schema-evolution-scala` documentation.
will be documented very soon. These schema evolutions often may need to reach into the serialization layer, however
are much more powerful in terms of flexibly removing unused/deprecated classes from your classpath etc.
Storage plugins Storage plugins
=============== ===============
@ -833,6 +825,8 @@ it must add
to the application configuration. If not specified, a default serializer is used. to the application configuration. If not specified, a default serializer is used.
For more advanced schema evolution techniques refer to the :ref:`persistence-schema-evolution-scala` documentation.
Testing Testing
======= =======

View file

@ -111,11 +111,13 @@ bytes to different objects.
Then you only need to fill in the blanks, bind it to a name in your :ref:`configuration` and then Then you only need to fill in the blanks, bind it to a name in your :ref:`configuration` and then
list which classes that should be serialized using it. list which classes that should be serialized using it.
.. _string-manifest-serializer-java:
Serializer with String Manifest Serializer with String Manifest
------------------------------- -------------------------------
The ``Serializer`` illustrated above supports a class based manifest (type hint). The ``Serializer`` illustrated above supports a class based manifest (type hint).
For serialization of data that need to evolve over time the `SerializerWithStringManifest` For serialization of data that need to evolve over time the ``SerializerWithStringManifest``
is recommended instead of ``Serializer`` because the manifest (type hint) is a ``String`` is recommended instead of ``Serializer`` because the manifest (type hint) is a ``String``
instead of a ``Class``. That means that the class can be moved/removed and the serializer instead of a ``Class``. That means that the class can be moved/removed and the serializer
can still deserialize old data by matching on the ``String``. This is especially useful can still deserialize old data by matching on the ``String``. This is especially useful

View file

@ -0,0 +1,407 @@
/*
* Copyright (C) 2009-2015 Typesafe Inc. <http://www.typesafe.com>
*/
package docs.persistence
import scala.language.reflectiveCalls
import java.nio.charset.Charset
import akka.actor.ActorSystem
import akka.persistence.journal.{ EventAdapter, EventSeq }
import akka.serialization.{ SerializationExtension, SerializerWithStringManifest }
import akka.testkit.TestKit
import com.typesafe.config._
import org.scalatest.WordSpec
import spray.json.JsObject
import scala.concurrent.duration._
class PersistenceSchemaEvolutionDocSpec extends WordSpec {
val customSerializerConfig =
"""
//#custom-serializer-config
akka.actor {
serializers {
my-payload = "docs.persistence.MyPayloadSerializer"
my-snapshot = "docs.persistence.MySnapshotSerializer"
}
serialization-bindings {
"docs.persistence.MyPayload" = my-payload
"docs.persistence.MySnapshot" = my-snapshot
}
}
//#custom-serializer-config
"""
val system = ActorSystem("PersistenceSchemaEvolutionDocSpec", ConfigFactory.parseString(customSerializerConfig))
try {
SerializationExtension(system)
} finally {
TestKit.shutdownActorSystem(system, 10.seconds, false)
}
}
class ProtobufReadOptional {
object proto {
class SeatReserved {
def hasSeatType = false
def getLetter = ""
def getRow = 1
def getSeatType = ""
}
object SeatReserved {
def newBuilder = new {
def setCode(any: Any): this.type = this
def setRow(any: Any): this.type = this
def setSeatType(any: Any): this.type = this
def build() = new {
def toByteArray: Array[Byte] = Array()
}
}
def parseFrom(any: Any) = new SeatReserved
}
}
//#protobuf-read-optional-model
sealed abstract class SeatType { def code: String }
object SeatType {
def fromString(s: String) = s match {
case Window.code => Window
case Aisle.code => Aisle
case Other.code => Other
case _ => Unknown
}
case object Window extends SeatType { override val code = "W" }
case object Aisle extends SeatType { override val code = "A" }
case object Other extends SeatType { override val code = "O" }
case object Unknown extends SeatType { override val code = "" }
}
case class SeatReserved(letter: String, row: Int, seatType: SeatType)
//#protobuf-read-optional-model
val protoIDL = """
//#protobuf-read-optional-proto
// FlightAppModels.proto
option java_package = "docs.persistence.proto";
option optimize_for = SPEED;
message SeatReserved {
required string letter = 1;
required string row = 2;
optional string seatType = 3; // the new field
}
//#protobuf-read-optional-proto
"""
//#protobuf-read-optional
/**
* Example serializer impl which uses protocol buffers generated classes (proto.*)
* to perform the to/from binary marshalling.
*/
class AddedFieldsSerializerWithProtobuf extends SerializerWithStringManifest {
override def identifier = 67876
final val SeatReservedManifest = classOf[SeatReserved].getName
override def manifest(o: AnyRef): String = o.getClass.getName
override def fromBinary(bytes: Array[Byte], manifest: String): AnyRef =
manifest match {
case SeatReservedManifest =>
seatReserved(proto.SeatReserved.parseFrom(bytes)) // use generated protobuf serializer
case _ =>
throw new IllegalArgumentException("Unable to handle manifest: " + manifest)
}
override def toBinary(o: AnyRef): Array[Byte] = o match {
case s: SeatReserved =>
proto.SeatReserved.newBuilder
.setCode(s.letter)
.setSeatType(s.seatType)
.build().toByteArray
}
// -- fromBinary helpers --
private def seatReserved(p: proto.SeatReserved): SeatReserved =
SeatReserved(p.getLetter, p.getRow, seatType(p))
// handle missing field by assigning "Unknown" value
private def seatType(p: proto.SeatReserved): SeatType =
if (p.hasSeatType) SeatType.fromString(p.getSeatType) else SeatType.Unknown
}
//#protobuf-read-optional
}
class ProtoBufRename {
val protoIDL = """
//#protobuf-rename-proto
// protobuf message definition, BEFORE:
message SeatReserved {
required string code = 1;
}
// protobuf message definition, AFTER:
message SeatReserved {
required string seatNr = 1; // field renamed, id remains the same
}
//#protobuf-rename-proto
"""
}
class RenamePlainJson {
//#rename-plain-json
class JsonRenamedFieldAdapter extends EventAdapter {
val marshaller = new ExampleJsonMarshaller
val V1 = "v1"
val V2 = "v2"
// this could be done independently for each event type
override def manifest(event: Any): String = "v2"
override def toJournal(event: Any): JsObject =
marshaller.toJson(event)
override def fromJournal(event: Any, manifest: String): EventSeq = event match {
case json: JsObject => EventSeq(marshaller.fromJson(manifest match {
case V1 => rename(json, "code" -> "seatNr")
case V2 => json // pass-through
case unknown => throw new IllegalArgumentException(s"Unknown manifest: $unknown")
}))
case _ =>
val c = event.getClass
throw new IllegalArgumentException("Can only work with JSON, was: %s".format(c))
}
def rename(json: JsObject, fromTo: (String, String)): JsObject = {
val value = json.fields(fromTo._1)
val withoutOld = json.fields - fromTo._1
JsObject(withoutOld + (fromTo._2 -> value))
}
}
//#rename-plain-json
}
class SimplestCustomSerializer {
//#simplest-custom-serializer-model
final case class Person(name: String, surname: String)
//#simplest-custom-serializer-model
//#simplest-custom-serializer
/**
* Simplest possible serializer, uses a string representation of the Person class.
*
* Usually a serializer like this would use a library like:
* protobuf, kryo, avro, cap'n proto, flatbuffers, SBE or some other dedicated serializer backend
* to perform the actual to/from bytes marshalling.
*/
class SimplestPossiblePersonSerializer extends SerializerWithStringManifest {
val Utf8 = Charset.forName("UTF-8")
val PersonManifest = classOf[Person].getName
// unique identifier of the serializer
def identifier = 1234567
// extract manifest to be stored together with serialized object
override def manifest(o: AnyRef): String = o.getClass.getName
// serialize the object
def toBinary(obj: AnyRef): Array[Byte] = obj match {
case p: Person => s"""${p.name}|${p.surname}""".getBytes(Utf8)
case _ => throw new IllegalArgumentException(
s"Unable to serialize to bytes, clazz was: ${obj.getClass}!")
}
// deserialize the object, using the manifest to indicate which logic to apply
def fromBinary(bytes: Array[Byte], clazz: String): AnyRef = clazz match {
case PersonManifest =>
val nameAndSurname = new String(bytes, Utf8)
val Array(name, surname) = nameAndSurname.split("[|]")
Person(name, surname)
case _ => throw new IllegalArgumentException(
s"Unable to deserialize from bytes, clazz was: $clazz! Bytes length: ${bytes.length}")
}
}
//#simplest-custom-serializer
}
class PersonSerializerSettingsBox {
val PersonSerializerSettings = """
//#simplest-custom-serializer-config
# application.conf
akka {
actor {
serializers {
person = "docs.persistence.SimplestPossiblePersonSerializer"
}
serialization-bindings {
"docs.persistence.Person" = person
}
}
}
//#simplest-custom-serializer-config
"""
}
final case class SamplePayload(p: Any)
//#split-events-during-recovery
trait V1
trait V2
// V1 event:
final case class UserDetailsChanged(name: String, address: String) extends V1
// corresponding V2 events:
final case class UserNameChanged(name: String) extends V2
final case class UserAddressChanged(address: String) extends V2
// event splitting adapter:
class UserEventsAdapter extends EventAdapter {
override def manifest(event: Any): String = ""
override def fromJournal(event: Any, manifest: String): EventSeq = event match {
case UserDetailsChanged(null, address) => EventSeq(UserAddressChanged(address))
case UserDetailsChanged(name, null) => EventSeq(UserNameChanged(name))
case UserDetailsChanged(name, address) => EventSeq(UserNameChanged(name),
UserAddressChanged(address))
case event: V2 => EventSeq(event)
}
override def toJournal(event: Any): Any = event
}
//#split-events-during-recovery
final case class CustomerBlinked(customerId: Long)
//#string-serializer-skip-deleved-event-by-manifest
case object EventDeserializationSkipped
class RemovedEventsAwareSerializer extends SerializerWithStringManifest {
val Utf8 = Charset.forName("UTF-8")
override def identifier: Int = 8337
val SkipEventManifestsEvents = Set(
"docs.persistence.CustomerBlinked" // ...
)
val MyPayloadClassName = classOf[SamplePayload].getName
override def manifest(o: AnyRef): String = o.getClass.getName
override def toBinary(o: AnyRef): Array[Byte] = o match {
case _ => o.toString.getBytes(Utf8) // example serialization
}
override def fromBinary(bytes: Array[Byte], manifest: String): AnyRef = manifest match {
case m if SkipEventManifestsEvents.contains(m) =>
EventDeserializationSkipped
case other => new String(bytes)
}
}
//#string-serializer-skip-deleved-event-by-manifest
//#string-serializer-skip-deleved-event-by-manifest-adapter
class SkippedEventsAwareAdapter extends EventAdapter {
override def manifest(event: Any) = ""
override def toJournal(event: Any) = event
override def fromJournal(event: Any, manifest: String) = event match {
case EventDeserializationSkipped => EventSeq.empty
case _ => EventSeq(event)
}
}
//#string-serializer-skip-deleved-event-by-manifest-adapter
//#string-serializer-handle-rename
class RenamedEventAwareSerializer extends SerializerWithStringManifest {
val Utf8 = Charset.forName("UTF-8")
override def identifier: Int = 8337
val OldPayloadClassName = "docs.persistence.OldPayload" // class NOT available anymore
val MyPayloadClassName = classOf[SamplePayload].getName
override def manifest(o: AnyRef): String = o.getClass.getName
override def toBinary(o: AnyRef): Array[Byte] = o match {
case SamplePayload(data) => s"""$data""".getBytes(Utf8)
// previously also handled "old" events here.
}
override def fromBinary(bytes: Array[Byte], manifest: String): AnyRef = manifest match {
case OldPayloadClassName => SamplePayload(new String(bytes, Utf8))
case MyPayloadClassName => SamplePayload(new String(bytes, Utf8))
case other => throw new Exception(s"unexpected manifest [$other]")
}
}
//#string-serializer-handle-rename
//#detach-models
/** Domain model - highly optimised for domain language and maybe "fluent" usage */
object DomainModel {
final case class Customer(name: String)
final case class Seat(code: String) {
def bookFor(customer: Customer): SeatBooked = SeatBooked(code, customer)
}
final case class SeatBooked(code: String, customer: Customer)
}
/** Data model - highly optimised for schema evolution and persistence */
object DataModel {
final case class SeatBooked(code: String, customerName: String)
}
//#detach-models
//#detach-models-adapter
class DetachedModelsAdapter extends EventAdapter {
override def manifest(event: Any): String = ""
override def toJournal(event: Any): Any = event match {
case DomainModel.SeatBooked(code, customer) =>
DataModel.SeatBooked(code, customer.name)
}
override def fromJournal(event: Any, manifest: String): EventSeq = event match {
case DataModel.SeatBooked(code, customerName) =>
EventSeq(DomainModel.SeatBooked(code, DomainModel.Customer(customerName)))
}
}
//#detach-models-adapter
// act as-if JSON library
class ExampleJsonMarshaller {
def toJson(any: Any): JsObject = JsObject()
def fromJson(json: JsObject): Any = new Object
}
//#detach-models-adapter-json
class JsonDataModelAdapter extends EventAdapter {
override def manifest(event: Any): String = ""
val marshaller = new ExampleJsonMarshaller
override def toJournal(event: Any): JsObject =
marshaller.toJson(event)
override def fromJournal(event: Any, manifest: String): EventSeq = event match {
case json: JsObject =>
EventSeq(marshaller.fromJson(json))
case _ =>
throw new IllegalArgumentException(
"Unable to fromJournal a non-JSON object! Was: " + event.getClass)
}
}
//#detach-models-adapter-json

View file

@ -12,6 +12,7 @@ Actors
routing routing
fsm fsm
persistence persistence
persistence-schema-evolution
persistence-query persistence-query
testing testing
actordsl actordsl

View file

@ -0,0 +1,476 @@
.. _persistence-schema-evolution-scala:
##############################
Persistence - Schema Evolution
##############################
When working on long running projects using :ref:`persistence-scala`, or any kind of `Event Sourcing`_ architectures,
schema evolution becomes one of the more important technical aspects of developing your application.
The requirements as well as our own understanding of the business domain may (and will) change in time.
In fact, if a project matures to the point where you need to evolve its schema to adapt to changing business
requirements you can view this as first signs of its success if you wouldn't need to adapt anything over an apps
lifecycle that could mean that no-one is really using it actively.
In this chapter we will investigate various schema evolution strategies and techniques from which you can pick and
choose the ones that match your domain and challenge at hand.
.. note::
This page proposes a number of possible solutions to the schema evolution problem and explains how some of the
utilities Akka provides can be used to achieve this, it is by no means a complete (closed) set of solutions.
Sometimes, based on the capabilities of your serialization formats, you may be able to evolve your schema in
different ways than outlined in the sections below. If you discover useful patterns or techniques for schema
evolution feel free to submit Pull Requests to this page to extend it.
Schema evolution in event-sourced systems
=========================================
In recent years we have observed a tremendous move towards immutable append-only datastores, with event-sourcing being
the prime technique successfully being used in these settings. For an excellent overview why and how immutable data makes scalability
and systems design much simpler you may want to read Pat Helland's excellent `Immutability Changes Everything`_ whitepaper.
Since with `Event Sourcing`_ the **events are immutable** and usually never deleted the way schema evolution is handled
differs from how one would go about it in a mutable database setting (e.g. in typical CRUD database applications).
The system needs to be able to continue to work in the presence of "old" events which were stored under the "old" schema.
We also want to limit complexity in the business logic layer, exposing a consistent view over all of the events of a given
type to :class:`PersistentActor` s and :ref:`persistence queries <persistence-query-scala>`. This allows the business logic layer to focus on solving business problems
instead of having to explicitly deal with different schemas.
The system needs to be able to continue to work in the presence of "old" events which were stored under the "old" schema,
and we want to limit the complexity to the data layer, exposing a consistent view over all of the events of a given type
to :class:`PersistentActor` s and persistence queries, which allows these layers to focus on the business problems instead
handling the different schemas explicitly in the business logic layers.
In summary, schema evolution in event sourced systems exposes the following characteristics:
- Allow the system to continue operating without large scale migrations to be applied,
- Allow the system to read "old" events from the underlying storage, however present them in a "new" view to the application logic,
- Transparently promote events to the latest versions during recovery (or queries) such that the business logic need not consider multiple versions of events
.. _Immutability Changes Everything: http://www.cidrdb.org/cidr2015/Papers/CIDR15_Paper16.pdf
.. _Event Sourcing: http://martinfowler.com/eaaDev/EventSourcing.html
Types of schema evolution
-------------------------
Before we explain the various techniques that can be used to safely evolve the schema of your persistent events
over time, we first need to define what the actual problem is, and what the typical styles of changes are.
Since events are never deleted, we need to have a way to be able to replay (read) old events, in such way
that does not force the ``PersistentActor`` to be aware of all possible versions of an event that it may have
persisted in the past. Instead, we want the Actors to work on some form of "latest" version of the event and provide some
means of either converting old "versions" of stored events into this "latest" event type, or constantly evolve the event
definition - in a backwards compatible way - such that the new deserialization code can still read old events.
The most common schema changes you will likely are:
- :ref:`adding a field to an event type <add-field-scala>`,
- :ref:`remove or rename field in event type <rename-field-scala>`,
- :ref:`remove event type <remove-event-class-scala>`,
- :ref:`split event into multiple smaller events <split-large-event-into-smaller-scala>`.
The following sections will explain some patterns which can be used to safely evolve your schema when facing those changes.
Picking the right serialization format
======================================
Picking the serialization format is a very important decision you will have to make while building your application.
It affects which kind of evolutions are simple (or hard) to do, how much work is required to add a new datatype, and,
last but not least, serialization performanceion.
If you find yourself realising you have picked "the wrong" serialization format, it is always possible to change
the format used for storing new events, however you would have to keep the old deserialization code in order to
be able to replay events that were persisted using the old serialization scheme. It is possible to "rebuild"
an event-log from one serialization format to another one, however it may be a more involved process if you need
to perform this on a live system.
Binary serialization formats that we have seen work well for long-lived applications include the very flexible IDL based:
`Google Protobuf`_, `Apache Thrift`_ or `Apache Avro`_. Avro schema evolution is more "entire schema" based, instead of
single fields focused like in protobuf or thrift, and usually requires using some kind of schema registry.
Users who want their data to be human-readable directly in the write-side
datastore may opt to use plain-old `JSON`_ as the storage format, though that comes at a cost of lacking support for schema
evolution and relatively large marshalling latency.
There are plenty excellent blog posts explaining the various trade-offs between popular serialization formats,
one post we would like to highlight is the very well illustrated `Schema evolution in Avro, Protocol Buffers and Thrift`_
by Martin Kleppmann.
.. _Google Protobuf: https://developers.google.com/protocol-buffers
.. _Apache Avro: https://avro.apache.org
.. _JSON: http://json.org
.. _Schema evolution in Avro, Protocol Buffers and Thrift: http://martin.kleppmann.com/2012/12/05/schema-evolution-in-avro-protocol-buffers-thrift.html
Provided default serializers
----------------------------
Akka Persistence provides `Google Protocol Buffers`_ based serializers (using :ref:`Akka Serialization <serialization-scala>`)
for it's own message types such as ``PersistentRepr``, ``AtomicWrite`` and snapshots. Journal plugin implementations
*may* choose to use those provided serializers, or pick a serializer which suits the underlying database better.
.. note::
Serialization is **NOT** handled automatically by Akka Persistence itself. Instead, it only provides the above described
serializers, and in case a ``AsyncWriteJournal`` plugin implementation chooses to use them directly, the above serialization
scheme will be used.
Please refer to your write journal's documentation to learn more about how it handles serialization!
For example, some journals may choose to not use Akka Serialization *at all* and instead store the data in a format
that is more "native" for the underlying datastore, e.g. using JSON or some other kind of format that the target
datastore understands directly.
The below figure explains how the default serialization scheme works, and how it fits together with serializing the
user provided message itself, which we will from here on refer to as the ``payload`` (highlighted in yellow):
.. figure:: ../images/persistent-message-envelope.png
:align: center
Akka Persistence provided serializers wrap the user payload in an envelope containing all persistence-relevant information.
**If the Journal uses provided Protobuf serializers for the wrapper types (e.g. PersistentRepr), then the payload will
be serialized using the user configured serializer, and if none is provided explicitly, Java serialization will be used for it.**
The blue colored regions of the ``PersistentMessage`` indicate what is serialized using the generated protocol buffers
serializers, and the yellow payload indicates the user provided event (by calling ``persist(payload)(...)``).
As you can see, the ``PersistentMessage`` acts as an envelope around the payload, adding various fields related to the
origin of the event (``persistenceId``, ``sequenceNr`` and more).
More advanced techniques (e.g. :ref:`remove-event-class-scala`) will dive into using the manifests for increasing the
flexibility of the persisted vs. exposed types even more. Hhowever for now we will focus on the simpler evolution techniques,
concerning simply configuring the payload serializers.
By default the ``payload`` will be serialized using Java Serialization. This is fine for testing and initial phases
of your development (while you're still figuring out things and the data will not need to stay persisted forever).
However, once you move to production you should really *pick a different serializer for your payloads*.
.. warning::
Do not rely on Java serialization (which will be picked by Akka by default if you don't specify any serializers)
for *serious* application development! It does not lean itself well to evolving schemas over long periods of time,
and its performance is also not very high (it never was designed for high-throughput scenarios).
.. _Google Protocol Buffers: https://developers.google.com/protocol-buffers/
.. _Apache Thrift: https://thrift.apache.org/
Configuring payload serializers
-------------------------------
This section aims to highlight the complete basics on how to define custom serializers using :ref:`Akka Serialization <serialization-scala>`.
Many journal plugin implementations use Akka Serialization, thus it is tremendously important to understand how to configure
it to work with your event classes.
.. note::
Read the :ref:`Akka Serialization <serialization-scala>` docs to learn more about defining custom serializers,
to improve performance and maintainability of your system. Do not depend on Java serialization for production deployments.
The below snippet explains in the minimal amount of lines how a custom serializer can be registered.
For more in-depth explanations on how serialization picks the serializer to use etc, please refer to its documentation.
First we start by defining our domain model class, here representing a person:
.. includecode:: code/docs/persistence/PersistenceSchemaEvolutionDocSpec.scala#simplest-custom-serializer-model
Next we implement a serializer (or extend an existing one to be able to handle the new ``Person`` class):
.. includecode:: code/docs/persistence/PersistenceSchemaEvolutionDocSpec.scala#simplest-custom-serializer
And finally we register the serializer and bind it to handle the ``docs.persistence.Person`` class:
.. includecode:: code/docs/persistence/PersistenceSchemaEvolutionDocSpec.scala#simplest-custom-serializer-config
Deserialization will be performed by the same serializer which serialized the message initially
because of the ``identifier`` being stored together with the message.
Please refer to the :ref:`Akka Serialization <serialization-scala>` documentation for more advanced use of serializers,
especially the :ref:`string-manifest-serializer-scala` section since it is very useful for Persistence based applications
dealing with schema evolutions, as we will see in some of the examples below.
Schema evolution in action
==========================
In this section we will discuss various schema evolution techniques using concrete examples and explaining
some of the various options one might go about handling the described situation. The list below is by no means
a complete guide, so feel free to adapt these techniques depending on your serializer's capabilities
and/or other domain specific limitations.
.. _add-field-scala:
Add fields
----------
**Situation:**
You need to add a field to an existing message type. For example, a ``SeatReservation(letter:String, row:Int)`` now
needs to have an associated code which indicates if it is a window or aisle seat.
**Solution:**
Adding fields is the most common change you'll need to apply to your messages so make sure the serialization format
you picked for your payloads can handle it apropriately, i.e. such changes should be *binary compatible*.
This is easily achieved using the right serializer toolkit we recommend something like `Google Protocol Buffers`_ or
`Apache Thrift`_ however other tools may fit your needs just as well picking a serializer backend is something
you should research before picking one to run with. In the following examples we will be using protobuf, mostly because
we are familiar with it, it does its job well and Akka is using it internally as well.
While being able to read messages with missing fields is half of the solution, you also need to deal with the missing
values somehow. This is usually modeled as some kind of default value, or by representing the field as an ``Option[T]``
See below for an example how reading an optional field from from a serialized protocol buffers message might look like.
.. includecode:: code/docs/persistence/PersistenceSchemaEvolutionDocSpec.scala#protobuf-read-optional-model
Next we prepare an protocol definition using the protobuf Interface Description Language, which we'll use to generate
the serializer code to be used on the Akka Serialization layer (notice that the schema aproach allows us to easily rename
fields, as long as the numeric identifiers of the fields do not change):
.. includecode:: code/docs/persistence/PersistenceSchemaEvolutionDocSpec.scala#protobuf-read-optional-proto
The serializer implementation uses the protobuf generated classes to marshall the payloads.
Optional fields can be handled explicitly or missing values by calling the ``has...`` methods on the protobuf object,
which we do for ``seatType`` in order to use a ``Unknown`` type in case the event was stored before we had introduced
the field to this event type:
.. includecode:: code/docs/persistence/PersistenceSchemaEvolutionDocSpec.scala#protobuf-read-optional
.. _rename-field-scala:
Rename fields
-------------
**Situation:**
When first designing the system the ``SeatReverved`` event featured an ``code`` field.
After some time you discover that what what was originally called ``code`` actually means ``seatNr``, thus the model
should be changed to reflect this concept more accurately.
**Solution 1 - using IDL based serializers:**
First, we will discuss the most efficient way of dealing with such kinds of schema changes IDL based serializers.
IDL stands for Interface Description Language, and means that the schema of the messages that will be stored is based
on this description. Most IDL based serializers also generate the serializer / deserializer code so that using them
is not too hard. Examples of such serializers are protobuf or thrift.
Using these libraries rename operations are "free", because the field name is never actually stored in the binary
representation of the message. This is one of the advantages of schema based serializers, even though that they
add the overhead of having to maintain the schema. When using serializers like this, no additional code change
(except renaming the field and method used during serialization) is needed to perform such evolution:
.. figure:: ../images/persistence-serializer-rename.png
:align: center
This is how such a rename would look in protobuf:
.. includecode:: code/docs/persistence/PersistenceSchemaEvolutionDocSpec.scala#protobuf-rename-proto
It is important to learn about the strengths and limitations of your serializers, in order to be able to move
swiftly and refactor your models fearlessly as you go on with the project.
.. note::
Learn in-depth about the serialization engine you're using as it will impact how you can aproach schema evolution.
Some operations are "free" in certain serialization formats (more often than not: removing/adding optional fields,
sometimes renaming fields etc.), while some other operations are strictly not possible.
**Solution 2 - by manually handling the event versions:**
Another solution, in case your serialization format does not support renames as easily as the above mentioned formats,
is versioning your schema. For example, you could have made your events events carry an additional field called ``_version``
which was set to ``1`` (because it was the initial schema), and once you change the schema you bump this number to ``2``,
and write an adapter which can perform the rename.
This approach is popular when your serialization format is something like JSON, where renames can not be performed
automatically by the serializer. You can do these kinds of "promotions" either manually (as shown in the example below)
or using a library like `Stamina`_ which helps to create those ``V1->V2->V3->...->Vn`` promotion chains without much boilerplate.
.. figure:: ../images/persistence-manual-rename.png
:align: center
The following snippet showcases how one could apply renames if working with plain JSON (using ``spray.json.JsObject``):
.. includecode:: code/docs/persistence/PersistenceSchemaEvolutionDocSpec.scala#rename-plain-json
As you can see, manually handling renames induces some boilerplate onto the EventAdapter, however much of it
you will find is common infrastructure code that can be either provided by an external library (for promotion management)
or put together in a simple helper trait.
.. note::
The technique of versioning events and then promoting them to the latest version using JSON transformations
can of course be applied to more than just field renames it also applies to adding fields and all kinds of
changes in the message format.
.. _Stamina: https://github.com/scalapenos/stamina
.. _remove-event-class-scala:
Remove event class and ignore events
------------------------------------
**Situation:**
While investigating app performance you notice that insane amounts of ``CustomerBlinked`` events are being stored
for every customer each time he/she blinks. Upon investigation you decide that the event does not add any value
and should be deleted. You still have to be able to replay from a journal which contains those old CustomerBlinked events though.
**Naive solution - drop events in EventAdapter:**
The problem of removing an event type from the domain model is not as much its removal, as the implications
for the recovery mechanisms that this entails. For example, a naive way of filtering out certain kinds of events from
being delivered to a recovering ``PersistentActor`` is pretty simple, as one can simply filter them out in an :ref:`EventAdapter <event-adapters-scala>`:
.. figure:: ../images/persistence-drop-event.png
:align: center
The ``EventAdapter`` can drop old events (**O**) by emitting an empty :class:`EventSeq`.
Other events can simply be passed through (**E**).
This however does not address the underlying cost of having to deserialize all the events during recovery,
even those which will be filtered out by the adapter. In the next section we will improve the above explained mechanism
to avoid deserializing events which would be filtered out by the adapter anyway, thus allowing to save precious time
during a recovery containing lots of such events (without actually having to delete them).
**Improved solution - deserialize into tombstone:**
In the just described technique we have saved the PersistentActor from receiving un-wanted events by filtering them
out in the ``EventAdapter``, however the event itself still was deserialized and loaded into memory.
This has two notable *downsides*:
- first, that the deserialization was actually performed, so we spent some of out time budget on the
deserialization, even though the event does not contribute anything to the persistent actors state.
- second, that we are *unable to remove the event class* from the system since the serializer still needs to create
the actuall instance of it, as it does not know it will not be used.
The solution to these problems is to use a serializer that is aware of that event being no longer needed, and can notice
this before starting to deserialize the object.
This aproach allows us to *remove the original class from our classpath*, which makes for less "old" classes lying around in the project.
This can for example be implemented by using an ``SerializerWithStringManifest``
(documented in depth in :ref:`string-manifest-serializer-scala`). By looking at the string manifest, the serializer can notice
that the type is no longer needed, and skip the deserialization all-together:
.. figure:: ../images/persistence-drop-event-serializer.png
:align: center
The serializer is aware of the old event types that need to be skipped (**O**), and can skip deserializing them alltogether
by simply returning a "tombstone" (**T**), which the EventAdapter converts into an empty EventSeq.
Other events (**E**) can simply be passed through.
The serializer detects that the string manifest points to a removed event type and skips attempting to deserialize it:
.. includecode:: code/docs/persistence/PersistenceSchemaEvolutionDocSpec.scala#string-serializer-skip-deleved-event-by-manifest
The EventAdapter we implemented is aware of ``EventDeserializationSkipped`` events (our "Tombstones"),
and emits and empty ``EventSeq`` whenever such object is encoutered:
.. includecode:: code/docs/persistence/PersistenceSchemaEvolutionDocSpec.scala#string-serializer-skip-deleved-event-by-manifest-adapter
.. _detach-domain-from-data-model-scala:
Detach domain model from data model
-----------------------------------
**Situation:**
You want to separate the application model (often called the "*domain model*") completely from the models used to
persist the corresponding events (the "*data model*"). For example because the data representation may change
independently of the domain model.
Another situation where this technique may be useful is when your serialization tool of choice requires generated
classes to be used for serialization and deserialization of objects, like for example `Google Protocol Buffers`_ do,
yet you do not want to leak this implementation detail into the domain model itself, which you'd like to model as
plain Scala case classes.
**Solution:**
In order to detach the domain model, which is often represented using pure scala (case) classes, from the data model
classes which very often may be less user-friendly yet highly optimised for throughput and schema evolution
(like the classes generated by protobuf for example), it is possible to use a simple EventAdapter which maps between
these types in a 1:1 style as illustrated below:
.. figure:: ../images/persistence-detach-models.png
:align: center
Domain events (**A**) are adapted to the data model events (**D**) by the ``EventAdapter``.
The data model can be a format natively understood by the journal, such that it can store it more efficiently or
include additional data for the event (e.g. tags), for ease of later querying.
We will use the following domain and data models to showcase how the separation can be implemented by the adapter:
.. includecode:: code/docs/persistence/PersistenceSchemaEvolutionDocSpec.scala#detach-models
The :class:`EventAdapter` takes care of converting from one model to the other one (in both directions),
alowing the models to be completely detached from each other, such that they can be optimised independently
as long as the mapping logic is able to convert between them:
.. includecode:: code/docs/persistence/PersistenceSchemaEvolutionDocSpec.scala#detach-models-adapter
The same technique could also be used directly in the Serializer if the end result of marshalling is bytes.
Then the serializer can simply convert the bytes do the domain object by using the generated protobuf builders.
.. _store-human-readable-scala:
Store events as human-readable data model
-----------------------------------------
**Situation:**
You want to keep your persisted events in a human-readable format, for example JSON.
**Solution:**
This is a special case of the :ref:`detach-domain-from-data-model-scala` pattern, and thus requires some co-operation
from the Journal implementation to achieve this.
An example of a Journal which may implement this pattern is MongoDB, however other databases such as PostgreSQL
and Cassandra could also do it because of their built-in JSON capabilities.
In this aproach, the :class:`EventAdapter` is used as the marshalling layer: it serializes the events to/from JSON.
The journal plugin notices that the incoming event type is JSON (for example by performing a ``match`` on the incoming
event) and stores the incoming object directly.
.. includecode:: code/docs/persistence/PersistenceSchemaEvolutionDocSpec.scala#detach-models-adapter-json
.. note::
This technique only applies if the Akka Persistence plugin you are using provides this capability.
Check the documentation of your favourite plugin to see if it supports this style of persistence.
If it doesn't, you may want to skim the `list of existing journal plugins`_, just in case some other plugin
for your favourite datastore *does* provide this capability.
**Alternative solution:**
In fact, an AsyncWriteJournal implementation could natively decide to not use binary serialization at all,
and *always* serialize the incoming messages as JSON - in which case the ``toJournal`` implementation of the
:class:`EventAdapter` would be an identity function, and the ``fromJournal`` would need to de-serialize messages
from JSON.
.. note::
If in need of human-readable events on the *write-side* of your application reconsider whether preparing materialized views
using :ref:`persistence-query-scala` would not be an efficient way to go about this, without compromising the
write-side's throughput characteristics.
If indeed you want to use a human-readable representation on the write-side, pick a Persistence plugin
that provides that functionality, or implement one yourself.
.. _list of existing journal plugins: http://akka.io/community/#journal-plugins
.. _split-large-event-into-smaller-scala:
Split large event into fine-grained events
------------------------------------------
**Situation:**
While refactoring your domain events, you find that one of the events has become too large (coarse-grained)
and needs to be split up into multiple fine-grained events.
**Solution:**
Let us consider a situation where an event represents "user details changed". After some time we discover that this
event is too coarse, and needs to be split into "user name changed" and "user address changed", because somehow
users keep changing their usernames a lot and we'd like to keep this as a separate event.
The write side change is very simple, we simply persist ``UserNameChanged`` or ``UserAddressChanged`` depending
on what the user actually intended to change (instead of the composite ``UserDetailsChanged`` that we had in version 1
of our model).
.. figure:: ../images/persistence-event-adapter-1-n.png
:align: center
The ``EventAdapter`` splits the incoming event into smaller more fine grained events during recovery.
During recovery however, we now need to convert the old ``V1`` model into the ``V2`` representation of the change.
Depending if the old event contains a name change, we either emit the ``UserNameChanged`` or we don't,
and the address change is handled similarily:
.. includecode:: code/docs/persistence/PersistenceSchemaEvolutionDocSpec.scala#split-events-during-recovery
By returning an :class:`EventSeq` from the event adapter, the recovered event can be converted to multiple events before
being delivered to the persistent actor.

View file

@ -597,10 +597,6 @@ configuration key. The method can be overridden by implementation classes to ret
Event Adapters Event Adapters
============== ==============
.. note::
Complete documentation featuring use-cases and implementation examples for this feature will follow shortly.
In long running projects using event sourcing sometimes the need arises to detach the data model from the domain model In long running projects using event sourcing sometimes the need arises to detach the data model from the domain model
completely. completely.
@ -634,10 +630,7 @@ indeed adapt it return the adapted event(s) for it, other adapters which do not
adaptation simply return ``EventSeq.empty``. The adapted events are then delivered in-order to the ``PersistentActor`` during replay. adaptation simply return ``EventSeq.empty``. The adapted events are then delivered in-order to the ``PersistentActor`` during replay.
.. note:: .. note::
More advanced techniques utilising advanced binary serialization formats such as protocol buffers or kryo / thrift / avro For more advanced schema evolution techniques refer to the :ref:`persistence-schema-evolution-scala` documentation.
will be documented very soon. These schema evolutions often may need to reach into the serialization layer, however
are much more powerful in terms of flexibly removing unused/deprecated classes from your classpath etc.
.. _persistent-fsm: .. _persistent-fsm:
@ -885,6 +878,8 @@ it must add
to the application configuration. If not specified, a default serializer is used. to the application configuration. If not specified, a default serializer is used.
For more advanced schema evolution techniques refer to the :ref:`persistence-schema-evolution-scala` documentation.
Testing Testing
======= =======

View file

@ -103,11 +103,13 @@ bytes to different objects.
Then you only need to fill in the blanks, bind it to a name in your :ref:`configuration` and then Then you only need to fill in the blanks, bind it to a name in your :ref:`configuration` and then
list which classes that should be serialized using it. list which classes that should be serialized using it.
.. _string-manifest-serializer-scala:
Serializer with String Manifest Serializer with String Manifest
------------------------------- -------------------------------
The ``Serializer`` illustrated above supports a class based manifest (type hint). The ``Serializer`` illustrated above supports a class based manifest (type hint).
For serialization of data that need to evolve over time the `SerializerWithStringManifest` For serialization of data that need to evolve over time the ``SerializerWithStringManifest``
is recommended instead of ``Serializer`` because the manifest (type hint) is a ``String`` is recommended instead of ``Serializer`` because the manifest (type hint) is a ``String``
instead of a ``Class``. That means that the class can be moved/removed and the serializer instead of a ``Class``. That means that the class can be moved/removed and the serializer
can still deserialize old data by matching on the ``String``. This is especially useful can still deserialize old data by matching on the ``String``. This is especially useful