1 28 package org.jvyamlb; 29 30 import java.io.FileInputStream ; 31 import java.io.InputStream ; 32 33 import java.util.HashMap ; 34 import java.util.Iterator ; 35 import java.util.List ; 36 import java.util.ArrayList ; 37 import java.util.LinkedList ; 38 import java.util.Map ; 39 import java.util.Set ; 40 41 import java.util.regex.Pattern ; 42 43 import org.jvyamlb.nodes.Node; 44 import org.jvyamlb.nodes.ScalarNode; 45 import org.jvyamlb.nodes.SequenceNode; 46 import org.jvyamlb.nodes.MappingNode; 47 48 import org.jruby.util.ByteList; 49 50 53 public class BaseConstructorImpl implements Constructor { 54 private final static Map yamlConstructors = new HashMap (); 55 private final static Map yamlMultiConstructors = new HashMap (); 56 private final static Map yamlMultiRegexps = new HashMap (); 57 public YamlConstructor getYamlConstructor(final Object key) { 58 return (YamlConstructor)yamlConstructors.get(key); 59 } 60 61 public YamlMultiConstructor getYamlMultiConstructor(final Object key) { 62 return (YamlMultiConstructor)yamlMultiConstructors.get(key); 63 } 64 65 public Pattern getYamlMultiRegexp(final Object key) { 66 return (Pattern )yamlMultiRegexps.get(key); 67 } 68 69 public Set getYamlMultiRegexps() { 70 return yamlMultiRegexps.keySet(); 71 } 72 73 public static void addConstructor(final String tag, final YamlConstructor ctor) { 74 yamlConstructors.put(tag,ctor); 75 } 76 77 public static void addMultiConstructor(final String tagPrefix, final YamlMultiConstructor ctor) { 78 yamlMultiConstructors.put(tagPrefix,ctor); 79 yamlMultiRegexps.put(tagPrefix,Pattern.compile("^"+tagPrefix)); 80 } 81 82 private Composer composer; 83 private Map constructedObjects = new HashMap (); 84 private Map recursiveObjects = new HashMap (); 85 86 public BaseConstructorImpl(final Composer composer) { 87 this.composer = composer; 88 } 89 90 public boolean checkData() { 91 return composer.checkNode(); 92 } 93 94 public Object getData() { 95 if(composer.checkNode()) { 96 Node node = composer.getNode(); 97 if(null != node) { 98 return constructDocument(node); 99 } 100 } 101 return null; 102 } 103 104 private class DocumentIterator implements Iterator { 105 public boolean hasNext() {return checkData();} 106 public Object next() {return getData();} 107 public void remove() {} 108 } 109 110 public Iterator eachDocument() { 111 return new DocumentIterator(); 112 } 113 114 public Iterator iterator() { 115 return eachDocument(); 116 } 117 118 public Object constructDocument(final Node node) { 119 final Object data = constructObject(node); 120 constructedObjects.clear(); 121 recursiveObjects.clear(); 122 return data; 123 } 124 125 public static class YamlMultiAdapter implements YamlConstructor { 126 private YamlMultiConstructor ctor; 127 private String prefix; 128 public YamlMultiAdapter(final YamlMultiConstructor ctor, final String prefix) { 129 this.ctor = ctor; 130 this.prefix = prefix; 131 } 132 133 public Object call(final Constructor self, final Node node) { 134 return ctor.call(self,this.prefix,node); 135 } 136 } 137 138 public Object constructObject(final Node node) { 139 if(constructedObjects.containsKey(node)) { 140 return constructedObjects.get(node); 141 } 142 if(recursiveObjects.containsKey(node)) { 143 throw new ConstructorException(null,"found recursive node",null); 144 } 145 recursiveObjects.put(node,null); 146 YamlConstructor ctor = getYamlConstructor(node.getTag()); 147 if(ctor == null) { 148 boolean through = true; 149 for(final Iterator iter = getYamlMultiRegexps().iterator();iter.hasNext();) { 150 final String tagPrefix = (String )iter.next(); 151 final Pattern reg = getYamlMultiRegexp(tagPrefix); 152 if(reg.matcher(node.getTag()).find()) { 153 final String tagSuffix = node.getTag().substring(tagPrefix.length()); 154 ctor = new YamlMultiAdapter(getYamlMultiConstructor(tagPrefix),tagSuffix); 155 through = false; 156 break; 157 } 158 } 159 if(through) { 160 final YamlMultiConstructor xctor = getYamlMultiConstructor(null); 161 if(null != xctor) { 162 ctor = new YamlMultiAdapter(xctor,node.getTag()); 163 } else { 164 ctor = getYamlConstructor(null); 165 if(ctor == null) { 166 ctor = CONSTRUCT_PRIMITIVE; 167 } 168 } 169 } 170 } 171 final Object data = ctor.call(this,node); 172 constructedObjects.put(node,data); 173 recursiveObjects.remove(node); 174 return data; 175 } 176 177 public Object constructPrimitive(final Node node) { 178 if(node instanceof ScalarNode) { 179 return constructScalar(node); 180 } else if(node instanceof SequenceNode) { 181 return constructSequence(node); 182 } else if(node instanceof MappingNode) { 183 return constructMapping(node); 184 } else { 185 System.err.println(node.getTag()); 186 } 187 return null; 188 } 189 190 public Object constructScalar(final Node node) { 191 if(!(node instanceof ScalarNode)) { 192 if(node instanceof MappingNode) { 193 final Map vals = ((Map )node.getValue()); 194 for(final Iterator iter = vals.keySet().iterator();iter.hasNext();) { 195 final Node key = (Node)iter.next(); 196 if("tag:yaml.org,2002:value".equals(key.getTag())) { 197 return constructScalar((Node)vals.get(key)); 198 } 199 } 200 } 201 throw new ConstructorException(null,"expected a scalar node, but found " + node.getClass().getName(),null); 202 } 203 return node.getValue(); 204 } 205 206 public Object constructPrivateType(final Node node) { 207 Object val = null; 208 if(node.getValue() instanceof Map ) { 209 val = constructMapping(node); 210 } else if(node.getValue() instanceof List ) { 211 val = constructSequence(node); 212 } else { 213 val = node.getValue().toString(); 214 } 215 return new PrivateType(node.getTag(),val); 216 } 217 218 public Object constructSequence(final Node node) { 219 if(!(node instanceof SequenceNode)) { 220 throw new ConstructorException(null,"expected a sequence node, but found " + node.getClass().getName(),null); 221 } 222 final List internal = (List )node.getValue(); 223 final List val = new ArrayList (internal.size()); 224 for(final Iterator iter = internal.iterator();iter.hasNext();) { 225 val.add(constructObject((Node)iter.next())); 226 } 227 return val; 228 } 229 230 public Object constructMapping(final Node node) { 231 if(!(node instanceof MappingNode)) { 232 throw new ConstructorException(null,"expected a mapping node, but found " + node.getClass().getName(),null); 233 } 234 Map mapping = new HashMap (); 235 List merge = null; 236 final Map val = (Map )node.getValue(); 237 for(final Iterator iter = val.keySet().iterator();iter.hasNext();) { 238 final Node key_v = (Node)iter.next(); 239 final Node value_v = (Node)val.get(key_v); 240 if(key_v.getTag().equals("tag:yaml.org,2002:merge")) { 241 if(merge != null) { 242 throw new ConstructorException("while constructing a mapping", "found duplicate merge key",null); 243 } 244 if(value_v instanceof MappingNode) { 245 merge = new LinkedList (); 246 merge.add(constructMapping(value_v)); 247 } else if(value_v instanceof SequenceNode) { 248 merge = new LinkedList (); 249 final List vals = (List )value_v.getValue(); 250 for(final Iterator sub = vals.iterator();sub.hasNext();) { 251 final Node subnode = (Node)sub.next(); 252 if(!(subnode instanceof MappingNode)) { 253 throw new ConstructorException("while constructing a mapping","expected a mapping for merging, but found " + subnode.getClass().getName(),null); 254 } 255 merge.add(0,constructMapping(subnode)); 256 } 257 } else { 258 throw new ConstructorException("while constructing a mapping","expected a mapping or list of mappings for merging, but found " + value_v.getClass().getName(),null); 259 } 260 } else if(key_v.getTag().equals("tag:yaml.org,2002:value")) { 261 if(mapping.containsKey("=")) { 262 throw new ConstructorException("while construction a mapping", "found duplicate value key", null); 263 } 264 mapping.put("=",constructObject(value_v)); 265 } else { 266 mapping.put(constructObject(key_v),constructObject(value_v)); 267 } 268 } 269 if(null != merge) { 270 merge.add(mapping); 271 mapping = new HashMap (); 272 for(final Iterator iter = merge.iterator();iter.hasNext();) { 273 mapping.putAll((Map )iter.next()); 274 } 275 } 276 return mapping; 277 } 278 279 public Object constructPairs(final Node node) { 280 if(!(node instanceof MappingNode)) { 281 throw new ConstructorException(null,"expected a mapping node, but found " + node.getClass().getName(), null); 282 } 283 final List value = new LinkedList (); 284 final Map vals = (Map )node.getValue(); 285 for(final Iterator iter = vals.keySet().iterator();iter.hasNext();) { 286 final Node key = (Node)iter.next(); 287 final Node val = (Node)vals.get(key); 288 value.add(new Object []{constructObject(key),constructObject(val)}); 289 } 290 return value; 291 } 292 293 public final static YamlConstructor CONSTRUCT_PRIMITIVE = new YamlConstructor() { 294 public Object call(final Constructor self, final Node node) { 295 return self.constructPrimitive(node); 296 }}; 297 public final static YamlConstructor CONSTRUCT_SCALAR = new YamlConstructor() { 298 public Object call(final Constructor self, final Node node) { 299 return self.constructScalar(node); 300 }}; 301 public final static YamlConstructor CONSTRUCT_PRIVATE = new YamlConstructor() { 302 public Object call(final Constructor self, final Node node) { 303 return self.constructPrivateType(node); 304 }}; 305 public final static YamlConstructor CONSTRUCT_SEQUENCE = new YamlConstructor() { 306 public Object call(final Constructor self, final Node node) { 307 return self.constructSequence(node); 308 }}; 309 public final static YamlConstructor CONSTRUCT_MAPPING = new YamlConstructor() { 310 public Object call(final Constructor self, final Node node) { 311 return self.constructMapping(node); 312 }}; 313 314 public static void main(final String [] args) throws Exception { 315 final String filename = args[0]; 316 System.out.println("Reading of file: \"" + filename + "\""); 317 318 final ByteList input = new ByteList(1024); 319 final InputStream reader = new FileInputStream (filename); 320 byte[] buff = new byte[1024]; 321 int read = 0; 322 while(true) { 323 read = reader.read(buff); 324 input.append(buff,0,read); 325 if(read < 1024) { 326 break; 327 } 328 } 329 reader.close(); 330 final long before = System.currentTimeMillis(); 331 for(int i=0;i<1;i++) { 332 final Constructor ctor = new BaseConstructorImpl(new ComposerImpl(new ParserImpl(new ScannerImpl(input)),new ResolverImpl())); 333 for(final Iterator iter = ctor.eachDocument();iter.hasNext();) { 334 iter.next(); 335 } 337 } 338 final long after = System.currentTimeMillis(); 339 final long time = after-before; 340 final double timeS = (after-before)/1000.0; 341 System.out.println("Walking through the nodes for the file: " + filename + " took " + time + "ms, or " + timeS + " seconds"); 342 } 343 } | Popular Tags |