/* Authors: Alexander Elyasov, Arie Middelkoop Copyright 2011 Utrecht University The use of this sofware is free under the Modified BSD License. */ package UU.Serialization { import flash.utils.Dictionary; import UU.ISerialization.* ; import flash.utils.* ; // Base implementation of a serializer. It actually does not store anything // yet; only maintains some administration. // We keep track of a stack of objects currently being serialized, and a // dictionary of all objects serialized so far. // This serializer provides a default behavior where it will go after // the entire object graph (modulo those fields specified to be included). // Cycles are handled; but there is no upper bound enforced on the depth // of the object graph that will be serialized. public class SerializerBase implements Serializer { private var _stack : Array; // stack of objects being serialized. private var _dict : Dictionary; // types of the serialized objects. private var _memo : Dictionary; // objects that are serialized so far. public function SerializerBase() : void { resetBase(); } // reset the state of the serializer private function resetBase() : void { _stack = new Array(); _dict = new Dictionary(true); _memo = new Dictionary(true); } // Call 'actualBeginObject'. public function beginObject(obj : Object, objType : String) : void { _stack.push(obj); _dict[obj] = objType; _memo[obj] = actualBeginObject(obj, objType); } // Call 'actualEndObject'. public function endObject() : void { actualEndObject(); var obj : Object = _stack.pop(); } static public function isTopObjSerializable(o : Object) : Boolean { if (o is Serializable) return true ; if (Delegates.getDelegate(o) != null){ return true ; } //trace ("## " + getQualifiedClassName(o) + ", " + o.constructor + " --> " + Delegates[o.constructor]) ; return false ; } // Dispatch either 'storeFieldRec' or 'storeFieldUnSer' to actually // store the field. public function storeField(name : QName, val : Object) : void { if (isTopObjSerializable(val)) { storeFieldRec(name, val, _memo[val]); } else{ storeFieldUnSer(name, val) ; } } // Resets the state of the serializer. public function reset() : void { resetBase(); actualReset(); } // Returns the current nesting depth of serialization. // This method may also be called by the serializer to // base detail based on the serialization depth. public function get currentDepth() : int { return _stack.length; } // Returns the current object being serialized. // This method may also be called by the serializer. It // then returns the parent object if the serializer did // not start a 'beginObject' yet. public function get currentObject() : Object { return _stack[_stack.length-1]; } // Returns the type of the current object being serialized. // This method may also be called by the serializer. public function get currentObjectType() : String { return _dict[this.currentObject]; } // Returns the token associated with the current object being serialized. // This method may also be called by the serializer. public function get currentToken() : Object { return _memo[this.currentObject]; } // // The following methods should be implemented by an actual implementation // that inherits from SerializerBase. // // To serialize an arbitrary object. This implies that the object may not // implement Serializable. public function serialize(obj : Object) : void { // override this function } // This functions may associate atoken with the object, which is given // to the storeFieldRec method when the same object is encountered again. protected function actualBeginObject(obj : Object, objType : String) : Object { // override this function return null; } protected function actualEndObject() : void { // override this function } protected function actualReset() : void { // override this function } // Serialize non-Serializable value :) Note that this may include an array. protected function storeFieldUnSer(name : QName, val : Object) : void { // override this function } // Actually stores a Serializable value. // The function can return an arbitrary object (some token associated with 'val'). // If the object is serialized recursively (i.e. the object graph is cyclic), then // 'prev' contains the token returned by the previous serialization of the object. protected function storeFieldRec(name : QName, val : Object, prev : *) : void { // override this function } } }