split casing and fill onto separate levels
[potlatch2.git] / org / as3yaml / Serializer.as
1 /*
2  * Copyright (c) 2007 Derek Wischusen
3  * 
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:
10  * 
11  * The above copyright notice and this permission notice shall be included in all
12  * copies or substantial portions of the Software.
13  * 
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 
20  * SOFTWARE.
21  */
22
23 package org.as3yaml {
24         import flash.utils.Dictionary;
25         
26         import mx.utils.StringUtil;
27         
28         import org.as3yaml.events.*;
29         import org.as3yaml.nodes.*;
30         import org.idmedia.as3commons.util.*;
31         
32
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;
47
48     public function Serializer(emitter : Emitter, resolver : Resolver, opts : YAMLConfig) {
49         this.emitter = emitter;
50         this.resolver = resolver;
51         this.options = opts;
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));
60         } else {
61             version = null;
62         }
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;
69         this.closed = false;
70         this.opened = false;
71     }
72
73     public function open() : void {
74         if(!closed && !opened) {
75             this.emitter.emit(new StreamStartEvent());
76             this.opened = true;
77         } else if(closed) {
78             throw new SerializerException("serializer is closed");
79         } else {
80             throw new SerializerException("serializer is already opened");
81         }
82     }
83
84     public function close() : void  {
85         if(!opened) {
86             throw new SerializerException("serializer is not opened");
87         } else if(!closed) {
88             this.emitter.emit(new StreamEndEvent());
89             this.closed = true;
90             this.opened = false;
91         }
92     }
93
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");
99         }
100         this.emitter.emit(new DocumentStartEvent(this.useExplicitStart,this.useVersion,null));
101         anchorNode(node);
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;
107     }
108
109     private function anchorNode(node : Node) : void {
110         if(this.anchors.containsKey(node)) {
111             var anchor : String = this.anchors.get(node) as String;
112             if(null == anchor) {
113                 anchor = generateAnchor(node);
114                 this.anchors.put(node,anchor);
115             }
116         } else {
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) {
121                     anchorNode(item);
122                 }
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;
127                     anchorNode(key);
128                     anchorNode(value.get(key));
129                 }
130             }
131         }
132     }
133
134     private function generateAnchor(node : Node) : String {
135         this.lastAnchorId++;
136         return StringUtil.substitute(this.anchorTemplate, [new int(this.lastAnchorId)]);
137     }
138
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));
143         } else {
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;
153                 }
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()));
158                 var ix : int = 0;
159                 var seqNodeVal: Array =  node.getValue() as Array;
160                 for each (var item: Node in seqNodeVal) {
161                     serializeNode(item,node, ix++);
162                 }                
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);
172                 }
173                 this.emitter.emit(new MappingEndEvent());
174             }
175         }
176     }
177 }
178 }