2 * Copyright (c) 2007 Derek Wischusen
4 * Permission is hereby granted, free of charge, to any person obtaining a copy of
5 * this software and associated documentation files (the "Software"), to deal in
6 * the Software without restriction, including without limitation the rights to
7 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
8 * of the Software, and to permit persons to whom the Software is furnished to do
9 * so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in all
12 * copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 import flash.utils.Dictionary;
26 import mx.utils.StringUtil;
28 import org.as3yaml.events.*;
29 import org.as3yaml.nodes.*;
30 import org.idmedia.as3commons.util.*;
33 public class Serializer {
34 private var emitter : Emitter;
35 private var resolver : Resolver;
36 private var options : YAMLConfig;
37 private var useExplicitStart : Boolean;
38 private var useExplicitEnd : Boolean;
39 private var useVersion : Array;
40 private var useTags : Boolean;
41 private var anchorTemplate : String;
42 private var serializedNodes : Set;
43 private var anchors : Map;
44 private var lastAnchorId : int;
45 private var closed : Boolean;
46 private var opened : Boolean;
48 public function Serializer(emitter : Emitter, resolver : Resolver, opts : YAMLConfig) {
49 this.emitter = emitter;
50 this.resolver = resolver;
52 this.useExplicitStart = opts.getExplicitStart();
53 this.useExplicitEnd = opts.getExplicitEnd();
54 var version : Array = new Array();
55 if(opts.getUseVersion()) {
56 var v1 : String = opts.getVersion();
57 var index : int = v1.indexOf('.');
58 version[0] = int(v1.substring(0,index));
59 version[1] = int(v1.substring(index+1));
63 this.useVersion = version;
64 this.useTags = opts.getUseHeader();
65 this.anchorTemplate = opts.getAnchorFormat() == null ? "id{0}" : opts.getAnchorFormat();
66 this.serializedNodes = new HashSet();
67 this.anchors = new HashMap();
68 this.lastAnchorId = 0;
73 public function open() : void {
74 if(!closed && !opened) {
75 this.emitter.emit(new StreamStartEvent());
78 throw new SerializerException("serializer is closed");
80 throw new SerializerException("serializer is already opened");
84 public function close() : void {
86 throw new SerializerException("serializer is not opened");
88 this.emitter.emit(new StreamEndEvent());
94 public function serialize(node : Node) : void {
95 if(!this.closed && !this.opened) {
96 throw new SerializerException("serializer is not opened");
97 } else if(this.closed) {
98 throw new SerializerException("serializer is closed");
100 this.emitter.emit(new DocumentStartEvent(this.useExplicitStart,this.useVersion,null));
102 serializeNode(node,null,null);
103 this.emitter.emit(new DocumentEndEvent(this.useExplicitEnd));
104 this.serializedNodes = new HashSet();
105 this.anchors = new HashMap();
106 this.lastAnchorId = 0;
109 private function anchorNode(node : Node) : void {
110 if(this.anchors.containsKey(node)) {
111 var anchor : String = this.anchors.get(node) as String;
113 anchor = generateAnchor(node);
114 this.anchors.put(node,anchor);
117 this.anchors.put(node,null);
118 if(node is SequenceNode) {
119 var seqNodeVal: Array = node.getValue() as Array;
120 for each (var item: Node in seqNodeVal) {
123 } else if(node is MappingNode) {
124 var value : Map = MappingNode(node).getValue() as Map;
125 for(var iter : Iterator = value.keySet().iterator();iter.hasNext();) {
126 var key : Node = iter.next() as Node;
128 anchorNode(value.get(key));
134 private function generateAnchor(node : Node) : String {
136 return StringUtil.substitute(this.anchorTemplate, [new int(this.lastAnchorId)]);
139 private function serializeNode(node : Node, parent : Node, index : Object) : void {
140 var tAlias : String = this.anchors.get(node) as String;
141 if(this.serializedNodes.contains(node)) {
142 this.emitter.emit(new AliasEvent(tAlias));
144 this.serializedNodes.add(node);
145 this.resolver.descendResolver(parent,index);
146 if(node is ScalarNode) {
147 var detectedTag : String = this.resolver.resolve(ScalarNode,String(node.getValue()),[true,false]);
148 var defaultTag : String = this.resolver.resolve(ScalarNode,String(node.getValue()),[false,true]);
149 var implicit : Array = [false,false];
150 if(!options.getExplicitTypes()) {
151 implicit[0] = node.getTag() == detectedTag;
152 implicit[1] = node.getTag() == defaultTag;
154 this.emitter.emit(new ScalarEvent(tAlias,node.getTag(),implicit,String(node.getValue()), ScalarNode(node).getStyle()));
155 } else if(node is SequenceNode) {
156 var imp : Boolean = !options.getExplicitTypes() && (node.getTag() == (this.resolver.resolve(SequenceNode,null,[true,true])));
157 this.emitter.emit(new SequenceStartEvent(tAlias,node.getTag(),imp,CollectionNode(node).getFlowStyle()));
159 var seqNodeVal: Array = node.getValue() as Array;
160 for each (var item: Node in seqNodeVal) {
161 serializeNode(item,node, ix++);
163 this.emitter.emit(new SequenceEndEvent());
164 } else if(node is MappingNode) {
165 var impl : Boolean = !options.getExplicitTypes() && (node.getTag() == (this.resolver.resolve(MappingNode,null,[true,true])));
166 this.emitter.emit(new MappingStartEvent(tAlias,node.getTag(),impl,CollectionNode(node).getFlowStyle()));
167 var value : Map = node.getValue() as Map;
168 for(var iter : Iterator = value.keySet().iterator();iter.hasNext();) {
169 var key : Node = iter.next() as Node;
170 serializeNode(key,node,null);
171 serializeNode(value.get(key),node,key);
173 this.emitter.emit(new MappingEndEvent());