553d801f7c25f7d0a416f3ca3dfc74861f7ca676
[potlatch2.git] / org / as3yaml / Composer.as
1 /* Copyright (c) 2007 Derek Wischusen
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining a copy of 
4  * this software and associated documentation files (the "Software"), to deal in 
5  * the Software without restriction, including without limitation the rights to 
6  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 
7  * of the Software, and to permit persons to whom the Software is furnished to do
8  * so, subject to the following conditions:
9  * 
10  * The above copyright notice and this permission notice shall be included in all
11  * copies or substantial portions of the Software.
12  * 
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
14  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
15  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
16  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
17  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
18  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
19  * SOFTWARE.
20  */
21
22 package org.as3yaml {
23
24 import flash.utils.Dictionary;
25
26 import org.as3yaml.events.*;
27 import org.as3yaml.nodes.*;
28
29 public class Composer {
30     private var parser : Parser;
31     private var resolver : Resolver;
32     private var anchors : Dictionary;
33
34     public function Composer(parser : Parser, resolver : Resolver) : void {
35         this.parser = parser;
36         this.resolver = resolver;
37         this.anchors = new Dictionary();
38     }
39
40     public function checkNode() : Boolean {
41         return !(parser.peekEvent() is StreamEndEvent);
42     }
43     
44     public function getNode() : Node {
45         return checkNode() ? composeDocument() : Node(null);
46     }
47
48     public function eachNode(composer : Composer) : NodeIterator {
49         return new NodeIterator(composer);
50     }
51
52     public function iterator() : NodeIterator {
53         return eachNode(this);
54     }
55
56     public function composeDocument() : Node {
57         if(parser.peekEvent() is StreamStartEvent) {
58             //Drop STREAM-START event
59             parser.getEvent();
60         }
61         //Drop DOCUMENT-START event
62         parser.getEvent();
63         var node : Node = composeNode(null,null);
64         //Drop DOCUMENT-END event
65         parser.getEvent();
66         this.anchors = new Dictionary();
67         return node;
68     }
69
70     private static var FALS : Array = [false];
71     private static var TRU : Array = [true];
72
73     public function composeNode(parent : Node, index : Object) : Node {
74                 var event : Event = parser.peekEvent();
75                 var anchor : String;
76         if(event is AliasEvent) {
77             var eve : AliasEvent = parser.getEvent() as AliasEvent;
78             anchor = eve.getAnchor();
79             if(!anchors[anchor]) {
80                 
81                 throw new ComposerException(null,"found undefined alias " + anchor,null);
82             }
83             return anchors[anchor] as Node;
84         }
85         anchor = null;
86         if(event is NodeEvent) {
87             anchor = NodeEvent(event).getAnchor();
88         }
89         if(null != anchor) {
90             if(anchors[anchor]) {
91                 throw new ComposerException("found duplicate anchor "+anchor+"; first occurence",null,null);
92             }
93         }
94         resolver.descendResolver(parent,index);
95         var node : Node = null;
96                 var tag : String;
97         if(event is ScalarEvent) {
98             var ev : ScalarEvent = parser.getEvent() as ScalarEvent;
99             tag = ev.getTag();
100             if(tag == null || tag == ("!")) {
101                 tag = resolver.resolve(ScalarNode,ev.getValue(),ev.getImplicit());
102             }
103             node = new ScalarNode(tag,ev.getValue(),ev.getStyle());
104             if(null != anchor) {
105                 anchors[anchor] = node;
106             }
107         } else if(event is SequenceStartEvent) {
108             var start : SequenceStartEvent = parser.getEvent() as SequenceStartEvent;
109             tag = start.getTag();
110             if(tag == null || tag == ("!")) {
111                 tag = resolver.resolve(SequenceNode,null,start.getImplicit()  ? TRU : FALS);
112             }
113             node = new SequenceNode(tag,[],start.getFlowStyle());
114             if(null != anchor) {
115                 anchors[anchor] = node;
116             }
117             var ix : int = 0;
118             var nodeVal: Array = node.getValue() as Array;
119             while(!(parser.peekEvent() is SequenceEndEvent)) {
120                 nodeVal.push(composeNode(node, ix++));
121             }
122             parser.getEvent();
123         } else if(event is MappingStartEvent) {
124             var st : MappingStartEvent = parser.getEvent() as MappingStartEvent;
125             tag = st.getTag();
126             if(tag == null || tag == ("!")) {
127                 tag = resolver.resolve(MappingNode,null, st.getImplicit() ? TRU : FALS);
128             }
129             node = new MappingNode(tag, new Dictionary(), st.getFlowStyle());
130             if(null != anchor) {
131                 anchors[anchor] = node;
132             }
133             var mapNodeVal: Dictionary = node.getValue() as Dictionary;
134             while(!(parser.peekEvent() is MappingEndEvent)) {
135                 var key : Event = parser.peekEvent();
136                 var itemKey : Node = composeNode(node,null);
137                 if(mapNodeVal[itemKey]) {
138                     composeNode(node,itemKey);
139                 } else {
140                     mapNodeVal[itemKey] = composeNode(node,itemKey);
141                 }
142             }
143             parser.getEvent();
144         }
145         resolver.ascendResolver();
146         return node;
147     }
148     
149 }
150 }
151
152 import org.as3yaml.Composer;
153 import org.as3yaml.nodes.Node;
154         
155
156 internal class NodeIterator {
157         private var composer : Composer;
158         public function NodeIterator(composer : Composer) : void { this.composer = composer; }
159     public function hasNext() : Boolean {return composer.checkNode();}
160     public function next() :  Node{return composer.getNode();}
161     public function remove() : void {}
162 }