View this PageEdit this PageAttachments to this PageHistory of this PageHomeRecent ChangesSearch the SwikiHelp Guide
Hotspots: Admin Pages | Turn-in Site |
Current Links: Cases Final Project Summer 2007

Object Serialization

Reflection can provide the programmar with powerful and generic way to interact with their program data.

Acquiring All Variable Names of Class.


vars := (self makeClass: className) allInstVarNames asArray.

allInstVarNames asArray - provides a list of all instance variables a object can hold.


Detecting Private/Public Variables


a respondsTo: ((v,':') asSymbol)

respondsTo allows the object to be tested to see if it can receive a message. In this application, it allows you to deterime "public" instance variables.

Accessing data


a perform: (var asSymbol)

If you have a variable name var, and need to access its data. If the data has a get method, then you can use the above snipet to send the get message.

Putting it together


Now that these tools have been described, we can put them to use in generic object serialization.

Saving Data


The algorithm for saving data is as following.
StoreObject( obj )
   For each instance variable
      If String or Number
         WriteOut( varName, varValue )
      If Collection
         Foreach object in Collection
            StoreObject( object )
      If Object
         WriteOut( hash(object) )


Loading Data


The loading of data is a little more complicated if there are relationships between objects.

The class of each object is stored in the tag so we know how to make
a new object. But how do we make a new object if we only know the
name. Smalltalk is a global dictionary of classes.

Smalltalk at: (className asSymbol) new.

One small road bump. You can't make a new SmallInteger. You'll have to do a special case for this.

Second problem. We can't just make an new object everytime we encouter one. Imagine that a two portfolios contained the same instance of an account. We need to make sure that the new account is the same for each portfolio.

This means we have to do two things. Make two passes in our LoadObject, and model the relations of objects.

For the first pass, we need to load all the primative objects and fill in the hash codes of the objects.

For the second pass, we need to create all objects of a certain type
and place them in a collection. Then we make a second pass through our objects and lookup up the hash value with the new object and substitute it.

Look at this example:

<root>
<User class="User" id="3456">
<name class="String">chris</name>
<password class="String">chris</password>
<portfolios class="OrderedCollection">
<id>3006</id></portfolios>
<cron class="Cron" id="2712">
<tasks class="OrderedCollection">
<id>2402</id>
<id>3849</id>
<id>3804</id>
<id>1739</id></tasks></cron></User>
<tables>
<accountTable>
<account class="Checking" id="527">
<value class="Decimal">5100.0000</value>
<parents class="OrderedCollection">
<id>3006</id></parents>
<log class="TransactionLog" id="3571">
<transactions class="OrderedCollection">
<id>3334</id>
<id>3924</id>
<id>853</id>
<id>2066</id>
<id>3368</id>
<id>1671</id>
<id>1992</id></transactions></log>
<name class="String">Boo</name>
<number class="String">Hoo</number></account>
<account class="Stock" id="3164">
<value class="Decimal">5828.4000</value>
<parents class="OrderedCollection">
<id>3006</id></parents>
<log class="TransactionLog" id="3030">
<transactions class="OrderedCollection">
<id>165</id>
<id>3979</id>
<id>3012</id>
<id>3251</id>
<id>946</id>
<id>3787</id>
<id>3561</id></transactions></log>
<name class="String">LU</name>
<number class="String">LU</number>
<costBasis class="Decimal">1.53</costBasis>
<quantity class="SmallInteger">400</quantity>
<ticker class="String">LU</ticker>
<dividendAmount class="SmallInteger">0</dividendAmount>
<dividendPeriod class="String">0</dividendPeriod>
<tradeAccount class="UndefinedObject" id="3840"/> </account></accountTable>
<portfolioTable>
<portfolio class="Portfolio" id="1806">
<value class="Decimal">0.00</value>
<parents class="OrderedCollection">
<id>3006</id></parents>
<log class="TransactionLog" id="342">
<transactions class="OrderedCollection"/> </log>
<name class="String">Bank</name>
<assets class="OrderedCollection"/> </portfolio>
<portfolio class="Portfolio" id="3006">
<value class="Decimal">10928.40</value>
<parents class="OrderedCollection"/> 
<log class="TransactionLog" id="2054">
<transactions class="OrderedCollection">
<id>241</id>
<id>1155</id>
<id>2627</id>
<id>861</id>
<id>1327</id>
<id>2691</id></transactions></log>
<name class="String">Bank</name>
<assets class="OrderedCollection">
<id>527</id>
<id>3164</id>
<id>1806</id></assets></portfolio></portfolioTable></tables></root>


The structure of the xml document is as follows. There is a User Node, and then a table node. In the table node, every account, and every portfolio is stored.

Each account would be created first without resolving the transactions and parents objects. These objects are associated with the old hash value they used when they were created.

Each portfolio would be created as well without resolving accounts.

Once everything was created, the hashes can be resolved. We go through each object again, and then look up the object id and replace the id with the real object.

When complete, we have restored the original data and relationships.


by YoMammaTeam (dorky name, yes we know)

Link to this Page