split casing and fill onto separate levels
[potlatch2.git] / org / as3yaml / Resolver.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  
24 package org.as3yaml {
25
26 import flash.utils.Dictionary;
27
28 import org.as3yaml.nodes.*;
29 import org.rxr.actionscript.io.StringReader;
30
31 public class Resolver {
32     private static var yamlImplicitResolvers : Dictionary = new Dictionary();
33     private static var yamlPathResolvers : Dictionary = new Dictionary();
34
35     private var resolverExactPaths : Array = new Array();
36     private var resolverPrefixPaths : Array = new Array();
37
38     public static function addImplicitResolver(tag : String, regexp : RegExp, first : String) : void {
39         var firstVal : String = (null == first)?"":first;
40         for(var i:int=0,j:int=firstVal.length;i<j;i++) {
41             var theC : String = firstVal.charAt(i);
42             var curr : Array = yamlImplicitResolvers[theC] as Array;
43             if(curr == null) {
44                 curr = new Array();
45                 yamlImplicitResolvers[theC] = curr;
46             }
47             curr.push([tag,regexp]);
48         }
49     }
50
51 //    public static function addPathResolver(tag : String, path : List, kind : Class) : void {
52 //        var newPath : Array = new Array();
53 //        var nodeCheck : Object = null;
54 //        var indexCheck : Object = null;
55 //        for(var iter : Iterator = path.iterator();iter.hasNext();) {
56 //            var element : Object = iter.next();
57 //            if(element is List) {
58 //                var eList : List = element as List;
59 //                if(eList.size() == 2) {
60 //                    nodeCheck = eList.get(0);
61 //                    indexCheck = eList.get(1);
62 //                } else if(eList.size() == 1) {
63 //                    nodeCheck = eList.get(0);
64 //                    indexCheck = true;
65 //                } else {
66 //                    throw new ResolverException("Invalid path element: " + element);
67 //                }
68 //            } else {
69 //                nodeCheck = null;
70 //                indexCheck = element;
71 //            }
72 //
73 //            if(nodeCheck is String) {
74 //                nodeCheck = ScalarNode;
75 //            } else if(nodeCheck is List) {
76 //                nodeCheck = SequenceNode;
77 //            } else if(nodeCheck is Map) {
78 //                nodeCheck = MappingNode;
79 //            } else if(null != nodeCheck && !ScalarNode == (nodeCheck) && !SequenceNode == (nodeCheck) && !MappingNode == (nodeCheck)) {
80 //                throw new ResolverException("Invalid node checker: " + nodeCheck);
81 //            }
82 //            if(!(indexCheck is String || indexCheck is int) && null != indexCheck) {
83 //                throw new ResolverException("Invalid index checker: " + indexCheck);
84 //            }
85 //            newPath.push([nodeCheck,indexCheck]);
86 //        }
87 //        var newKind : Class = null;
88 //        if(String == kind) {
89 //            newKind = ScalarNode;
90 //        } else if(List == kind) {
91 //            newKind = SequenceNode;
92 //        } else if(Map == kind) {
93 //            newKind = MappingNode;
94 //        } else if(kind != null && !ScalarNode == kind && !SequenceNode == kind && !MappingNode == kind) {
95 //            throw new ResolverException("Invalid node kind: " + kind);
96 //        } else {
97 //            newKind = kind;
98 //        }
99 //        var x : Array = new Array();
100 //        x.push(newPath);
101 //        var y : Array = new Array();
102 //        y.push(x);
103 //        y.push(kind);
104 //        yamlPathResolvers[y] = tag;
105 //    }
106
107     public function descendResolver(currentNode : Node, currentIndex : Object) : void {
108         var exactPaths : Dictionary = new Dictionary();
109         var prefixPaths : Array = new Array();
110                 var path : Array;
111         if(null != currentNode) {
112             var depth : int = resolverPrefixPaths.length;
113             for(var xi:int=0; xi < resolverPrefixPaths[0].length; xi++) {
114                 var obj : Array = resolverPrefixPaths[0][xi] as Array;
115                 path = obj[0] as Array;
116                 if(checkResolverPrefix(depth,path, obj[1],currentNode,currentIndex)) {
117                     if(path.size() > depth) {
118                         prefixPaths.push([path,obj[1]]);
119                     } else {
120                         var resPath : Array = new Array();
121                         resPath.push(path);
122                         resPath.push(obj[1]);
123                         exactPaths[obj[1]] = yamlPathResolvers[resPath];
124                     }
125                 }
126             }
127         } else {
128             for(var keyObj : Object in yamlPathResolvers) {
129                 var key : Array = keyObj as Array;
130                 path = key[0] as Array;
131                 var kind : Class = key[1] as Class;
132                 if(null == path) {
133                     exactPaths[kind] = yamlPathResolvers[key];
134                 } else {
135                     prefixPaths.push(key);
136                 }
137             }
138         }
139         resolverExactPaths.unshift(exactPaths);
140         resolverPrefixPaths.unshift(prefixPaths);
141     }
142
143     public function ascendResolver() : void {
144         resolverExactPaths.shift();
145         resolverPrefixPaths.shift();
146     }
147
148     public function checkResolverPrefix(depth : int, path : Array, kind : Class, currentNode : Node, currentIndex : Object) : Boolean {
149         var check : Array = path[depth-1];
150         var nodeCheck : Object = check[0];
151         var indexCheck : Object = check[1];
152         if(nodeCheck is String) {
153             if(!currentNode.getTag() == (nodeCheck)) {
154                 return false;
155             }
156         } else if(null != nodeCheck) {
157             if(!(nodeCheck).isInstance(currentNode)) {
158                 return false;
159             }
160         }
161         if(indexCheck == true && currentIndex != null) {
162             return false;
163         }
164         if(indexCheck == true && currentIndex == null) {
165             return false;
166         }
167         if(indexCheck is String) {
168             if(!(currentIndex is ScalarNode && indexCheck == ((ScalarNode(currentIndex)).getValue()))) {
169                 return false;
170             }
171         } else if(indexCheck is int) {
172             if(!currentIndex == (indexCheck)) {
173                 return false;
174             }
175         }
176         return true;
177     }
178     
179     public function resolve(kind : Class, value : String, implicit : Array) : String {
180         var resolvers : Array = null;
181         if(kind == ScalarNode && implicit[0]) {
182             if("" == (value)) {
183                 resolvers = yamlImplicitResolvers[""] as Array;
184             } else {
185                 resolvers = yamlImplicitResolvers[value.charAt(0)] as Array;
186             }
187             if(resolvers == null) {
188                 resolvers = new Array();
189             }
190             if(yamlImplicitResolvers[null]) {
191                 resolvers.concat(yamlImplicitResolvers[null]);
192             }
193             for(var xi:int=0; xi < resolvers.length; xi++) {
194                 var val : Array = resolvers[xi];
195                 if((RegExp(val[1])).exec(value)) {
196                     return val[0] as String;
197                 }
198             }
199         }
200         var exactPaths : Dictionary = resolverExactPaths[0] as Dictionary;
201         if(exactPaths[kind]) {
202             return exactPaths[kind] as String;
203         }
204         if(exactPaths[null]) {
205             return exactPaths[null] as String;
206         }
207         if(kind == ScalarNode) {
208             return YAML.DEFAULT_SCALAR_TAG;
209         } else if(kind == SequenceNode) {
210             return YAML.DEFAULT_SEQUENCE_TAG;
211         } else if(kind == MappingNode) {
212             return YAML.DEFAULT_MAPPING_TAG;
213         }
214         return null;
215     } 
216
217     static: {
218         addImplicitResolver("tag:yaml.org,2002:bool",new RegExp("^(?:yes|Yes|YES|no|No|NO|true|True|TRUE|false|False|FALSE|on|On|ON|off|Off|OFF)$"),"yYnNtTfFoO");
219         addImplicitResolver("tag:yaml.org,2002:float",new RegExp("^(?:[-+]?(?:[0-9][0-9_]*)\\.[0-9_]*(?:[eE][-+][0-9]+)?|[-+]?(?:[0-9][0-9_]*)?\\.[0-9_]+(?:[eE][-+][0-9]+)?|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"),"-+0123456789.");
220         addImplicitResolver("tag:yaml.org,2002:int",new RegExp("^(?:[-+]?0b[0-1_]+|[-+]?0[0-7_]+|[-+]?(?:0|[1-9][0-9_]*)|[-+]?0x[0-9a-fA-F_]+|[-+]?[1-9][0-9_]*(?::[0-5]?[0-9])+)$"),"-+0123456789");
221         addImplicitResolver("tag:yaml.org,2002:merge",new RegExp("^(?:<<)$"),"<");
222         addImplicitResolver("tag:yaml.org,2002:null",new RegExp("^(?:~|null|Null|NULL| )$"),"~nN\x00");
223         addImplicitResolver("tag:yaml.org,2002:timestamp",new RegExp("^(?:[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]|[0-9][0-9][0-9][0-9]-[0-9][0-9]?-[0-9][0-9]?(?:[Tt]|[ \t]+)[0-9][0-9]?:[0-9][0-9]:[0-9][0-9](?:\\.[0-9]*)?(?:[ \t]*(?:Z|[-+][0-9][0-9]?(?::[0-9][0-9])?))?)$"),"0123456789");
224         addImplicitResolver("tag:yaml.org,2002:value",new RegExp("^(?:=)$"),"=");
225       // The following implicit resolver is only for documentation purposes. It cannot work
226       // because plain scalars cannot start with '!', '&', or '*'.
227         addImplicitResolver("tag:yaml.org,2002:yaml",new RegExp("^(?:!|&|\\*)$"),"!&*");
228     }
229 }
230 }