|
| 1 | +# Features |
| 2 | + |
| 3 | +SIXX is a multi-platform XML serializer/deserializer for Smalltalk. You can exchange various Smalltalk objects among different (dialect) images. |
| 4 | + |
| 5 | +## How to use |
| 6 | + |
| 7 | +### Basic writing/reading |
| 8 | + |
| 9 | +SIXX is very easy to use. Like #storeString, You can generate a SIXX string by #sixxString. |
| 10 | + |
| 11 | +```smalltalk |
| 12 | +array := Array with: 1 with: 'Hello' with: Date today. |
| 13 | +array sixxString. |
| 14 | +``` |
| 15 | + |
| 16 | +This code generates the following SIXX string: |
| 17 | + |
| 18 | +```xml |
| 19 | +'<sixx.object sixx.id="0" sixx.type="Array"> |
| 20 | + <sixx.object sixx.id="1" sixx.type="SmallInteger">1</sixx.object> |
| 21 | + <sixx.object sixx.id="2" sixx.type="String">Hello</sixx.object> |
| 22 | + <sixx.object sixx.id="3" sixx.type="Date">16 June 2002</sixx.object> |
| 23 | +</sixx.object>' |
| 24 | +``` |
| 25 | + |
| 26 | +This string can be read by #readSixxFrom:. |
| 27 | + |
| 28 | +```smalltalk |
| 29 | +Object readSixxFrom: sixxString. "sixxString is the above string" |
| 30 | +``` |
| 31 | + |
| 32 | +### Stream writing/reading |
| 33 | + |
| 34 | +SixxWriteStream and SixxReadStream are provided so that you can write/read Smalltalk objects in a way similar to binary object stream (BOSS in VW, and the ReferenceStream in Squeak). |
| 35 | + |
| 36 | +In order to write objects to an external file, you can: |
| 37 | + |
| 38 | +```smalltalk |
| 39 | +sws := SixxWriteStream newFileNamed: 'obj.sixx'. |
| 40 | +sws nextPut: object. "an object" |
| 41 | +sws nextPutAll: objects. "collection of objects" |
| 42 | +sws close. |
| 43 | +``` |
| 44 | + |
| 45 | +And to read objects from an external file: |
| 46 | + |
| 47 | +```smalltalk |
| 48 | +srs := SixxReadStream readOnlyFileNamed: 'obj.sixx'. |
| 49 | +objects := srs contents. |
| 50 | +srs close. |
| 51 | +``` |
| 52 | + |
| 53 | +### SIXX hooks |
| 54 | + |
| 55 | +#### Customizing serialization |
| 56 | + |
| 57 | +| Hook method | Description | |
| 58 | +| --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | |
| 59 | +| Object>>sixxPrepareWrite | It is called before the instance is written in SIXX. | |
| 60 | +| Object>>sixxWriteValue | Return the object actually serialized. | |
| 61 | +| Object>>sixxIgnorableInstVarNames | Specify the instance variables that are not written in SIXX. | |
| 62 | +| Object>>sixxNonReferencableInstVarNames | Specify the instance variables that should not be referenced in SIXX. Values are always written redundantly. It is useful for small literal objects like String, Number, etc. | |
| 63 | +| Object>>sixxReferenceIdInContext: | Return unique id that can be referenced from other objects in SIXX. It is useful when objects have their own unique id. | |
| 64 | + |
| 65 | +#### Customizing deserialization |
| 66 | + |
| 67 | +| Hook method | Description | |
| 68 | +| ---------------------- | ---------------------------------------------------------------- | |
| 69 | +| Object>>sixxInitialize | It is called immediately after the instance is read from SIXX | |
| 70 | +| Object>>sixxReadValue | Return the object for the client from the deserialized instance. | |
| 71 | + |
| 72 | +### ShapeChanger |
| 73 | + |
| 74 | +SixxShapeChangeReadStream enables you to read class shape changed instances. It supports renamed, removed and newly added instance variables. |
| 75 | + |
| 76 | +```smalltalk |
| 77 | +srs := SixxShapeChangeReadStream on: oldSixx readStream. |
| 78 | +srs shapeChangers at:#SmallIntegerOLD put: SmallInteger . "simple renaming" |
| 79 | +
|
| 80 | +srs shapeChangers at: #SixxShapeChangedObject put: SixxMockShapeChanger. |
| 81 | +"You can implement ShapeChanger for more complex conversion. " |
| 82 | +``` |
| 83 | + |
| 84 | +To define a new ShapeChanger, you should subclass base ShapeChanger class and override three methods. |
| 85 | + |
| 86 | +| Hook method | Description | |
| 87 | +| ------------------------------------------------------ | ------------------------------------------------------------------------------------- | |
| 88 | +| YourShapeChanger>>shapeChangedObjectClass | Return a newly introduced class for old instances. | |
| 89 | +| YourShapeChanger>>sixxInstVarNamed: varName put: value | Override this method for setting converted values to the shape changed object. | |
| 90 | +| YourShapeChanger>>initializeShapeChangedObject | Override this method for setting newly introduced values to the shape changed object. | |
| 91 | + |
| 92 | +For example: (YourShapeChanger>>sixxInstVarNamed: varName put:) |
| 93 | + |
| 94 | +```smalltalk |
| 95 | +sixxInstVarNamed: varName put: value |
| 96 | + "#oldNamedVar1 inst var was renamed to #renamedAtt1" |
| 97 | + varName == #oldNamedVar1 ifTrue: [^self attributesMap at: #renamedAtt1 put: value]. |
| 98 | +
|
| 99 | + "#oldNamedVar2 inst var was removed." |
| 100 | + varName == #oldNamedVar2 ifTrue: [^self]. |
| 101 | +
|
| 102 | + super sixxInstVarNamed: varName put: value |
| 103 | +``` |
| 104 | + |
| 105 | +From SIXX 0.3, you can apply ShapeChanger(s) without using SixxShapeChangeReadStream. |
| 106 | + |
| 107 | +```smalltalk |
| 108 | +obj := SixxContext evaluate: [Object readSixxFrom: oldSixx] shapeChangersBy: [:shapeChangers | shapeChangers at: #SixxShapeChangedObject put: SixxSomeShapeChanger]. |
| 109 | +``` |
| 110 | + |
| 111 | +### Formatter |
| 112 | + |
| 113 | +Formatter is a new SIXX function for customizing SIXX format without subclassing. |
| 114 | + |
| 115 | +Normally, you can customize SIXX serialization format by overriding hooks such as #sixxWriteValue, #sixxIgnorableInstVarNames. However, sometimes you would like to customize serialization format more dynamically. |
| 116 | +For example, you may want to change default Array serialization format to compact one, if the array includes only primitive (literal) elements. |
| 117 | + |
| 118 | +Suppose there is an array like: |
| 119 | + |
| 120 | +```smalltalk |
| 121 | +array := #(1 2 3 4 5). |
| 122 | +``` |
| 123 | + |
| 124 | +By default, the array will be serialized if you evaluate: |
| 125 | + |
| 126 | +```smalltalk |
| 127 | +array sixxString. "print it" |
| 128 | +``` |
| 129 | + |
| 130 | +```xml |
| 131 | +'<sixx.object sixx.id="0" sixx.type="Array"> |
| 132 | + <sixx.object sixx.id="1" sixx.type="SmallInteger">1</sixx.object> |
| 133 | + <sixx.object sixx.id="2" sixx.type="SmallInteger">2</sixx.object> |
| 134 | + <sixx.object sixx.id="3" sixx.type="SmallInteger">3</sixx.object> |
| 135 | + <sixx.object sixx.id="4" sixx.type="SmallInteger">4</sixx.object> |
| 136 | + <sixx.object sixx.id="5" sixx.type="SmallInteger">5</sixx.object> |
| 137 | +</sixx.object>' |
| 138 | +``` |
| 139 | + |
| 140 | +This format is reasonable for supporting complex array, but the format could be space-consuming if the array contains only primitive (literal) elements. By setting a Formatter, you can use more compact format for Array. |
| 141 | + |
| 142 | +```smalltalk |
| 143 | +SixxContext formatters: {SixxMockLiteralArrayFormatter on: Array}. |
| 144 | +``` |
| 145 | + |
| 146 | +After that, the format will be: |
| 147 | + |
| 148 | +```xml |
| 149 | +'<sixx.object |
| 150 | + sixx.id="0" |
| 151 | + sixx.type="Array" |
| 152 | + sixx.formatter="SixxMockLiteralArrayFormatter" |
| 153 | +> |
| 154 | + <sixx.object sixx.id="1" sixx.type="String">#(1 2 3 4 5)</sixx.object> |
| 155 | +</sixx.object>' |
| 156 | +``` |
| 157 | + |
| 158 | +You can reset the formatter by: |
| 159 | + |
| 160 | +```smalltalk |
| 161 | +SixxContext resetFormatters. |
| 162 | +``` |
| 163 | + |
| 164 | +For convenience, there is a method to switch formatter temporarily. |
| 165 | + |
| 166 | +```smalltalk |
| 167 | +SixxContext applyFormatters: {SixxMockLiteralArrayFormatter on: Array} while: [ |
| 168 | +array sixxString. |
| 169 | +] |
| 170 | +``` |
| 171 | + |
| 172 | +Or, you can even use: |
| 173 | + |
| 174 | +```smalltalk |
| 175 | +SixxContext evaluate: [array sixxString] formattersBy: [:formatters | formatters add: (SixxMockLiteralArrayFormatter on: Array)]. |
| 176 | +``` |
| 177 | + |
| 178 | +In short, Formatter can be used: |
| 179 | + |
| 180 | +- For customizing SIXX format dynamically. |
| 181 | +- For overriding SIXX format of the existing classes temporarily. |
0 commit comments