1 28 package org.jvyamlb; 29 30 import java.util.ArrayList ; 31 import java.util.Iterator ; 32 import java.util.List ; 33 import java.util.LinkedList ; 34 import java.util.HashMap ; 35 import java.util.Map ; 36 import java.util.HashSet ; 37 import java.util.Set ; 38 39 import org.jvyamlb.nodes.MappingNode; 40 import org.jvyamlb.nodes.Node; 41 import org.jvyamlb.nodes.ScalarNode; 42 import org.jvyamlb.nodes.SequenceNode; 43 44 import org.jruby.util.ByteList; 45 46 49 public class ResolverImpl implements Resolver { 50 private final static Map yamlPathResolvers = new HashMap (); 51 52 private final static ResolverScanner SCANNER = new ResolverScanner(); 53 54 private List resolverExactPaths = new LinkedList (); 55 private List resolverPrefixPaths = new LinkedList (); 56 57 public static void addPathResolver(final String tag, final List path, final Class kind) { 58 final List newPath = new LinkedList (); 59 Object nodeCheck=null; 60 Object indexCheck=null; 61 for(final Iterator iter = path.iterator();iter.hasNext();) { 62 final Object element = iter.next(); 63 if(element instanceof List ) { 64 final List eList = (List )element; 65 if(eList.size() == 2) { 66 nodeCheck = eList.get(0); 67 indexCheck = eList.get(1); 68 } else if(eList.size() == 1) { 69 nodeCheck = eList.get(0); 70 indexCheck = Boolean.TRUE; 71 } else { 72 throw new ResolverException("Invalid path element: " + element); 73 } 74 } else { 75 nodeCheck = null; 76 indexCheck = element; 77 } 78 79 if(nodeCheck instanceof String || nodeCheck instanceof ByteList) { 80 nodeCheck = ScalarNode.class; 81 } else if(nodeCheck instanceof List ) { 82 nodeCheck = SequenceNode.class; 83 } else if(nodeCheck instanceof Map ) { 84 nodeCheck = MappingNode.class; 85 } else if(null != nodeCheck && !ScalarNode.class.equals(nodeCheck) && !SequenceNode.class.equals(nodeCheck) && !MappingNode.class.equals(nodeCheck)) { 86 throw new ResolverException("Invalid node checker: " + nodeCheck); 87 } 88 if(!(indexCheck instanceof String || nodeCheck instanceof ByteList || indexCheck instanceof Integer ) && null != indexCheck) { 89 throw new ResolverException("Invalid index checker: " + indexCheck); 90 } 91 newPath.add(new Object []{nodeCheck,indexCheck}); 92 } 93 Class newKind = null; 94 if(String .class.equals(kind) || ByteList.class.equals(kind)) { 95 newKind = ScalarNode.class; 96 } else if(List .class.equals(kind)) { 97 newKind = SequenceNode.class; 98 } else if(Map .class.equals(kind)) { 99 newKind = MappingNode.class; 100 } else if(kind != null && !ScalarNode.class.equals(kind) && !SequenceNode.class.equals(kind) && !MappingNode.class.equals(kind)) { 101 throw new ResolverException("Invalid node kind: " + kind); 102 } else { 103 newKind = kind; 104 } 105 final List x = new ArrayList (1); 106 x.add(newPath); 107 final List y = new ArrayList (2); 108 y.add(x); 109 y.add(kind); 110 yamlPathResolvers.put(y,tag); 111 } 112 113 public void descendResolver(final Node currentNode, final Object currentIndex) { 114 final Map exactPaths = new HashMap (); 115 final List prefixPaths = new LinkedList (); 116 if(null != currentNode) { 117 final int depth = resolverPrefixPaths.size(); 118 for(final Iterator iter = ((List )resolverPrefixPaths.get(0)).iterator();iter.hasNext();) { 119 final Object [] obj = (Object [])iter.next(); 120 final List path = (List )obj[0]; 121 if(checkResolverPrefix(depth,path,(Class )obj[1],currentNode,currentIndex)) { 122 if(path.size() > depth) { 123 prefixPaths.add(new Object [] {path,obj[1]}); 124 } else { 125 final List resPath = new ArrayList (2); 126 resPath.add(path); 127 resPath.add(obj[1]); 128 exactPaths.put(obj[1],yamlPathResolvers.get(resPath)); 129 } 130 } 131 } 132 } else { 133 for(final Iterator iter = yamlPathResolvers.keySet().iterator();iter.hasNext();) { 134 final List key = (List )iter.next(); 135 final List path = (List )key.get(0); 136 final Class kind = (Class )key.get(1); 137 if(null == path) { 138 exactPaths.put(kind,yamlPathResolvers.get(key)); 139 } else { 140 prefixPaths.add(key); 141 } 142 } 143 } 144 resolverExactPaths.add(0,exactPaths); 145 resolverPrefixPaths.add(0,prefixPaths); 146 } 147 148 public void ascendResolver() { 149 resolverExactPaths.remove(0); 150 resolverPrefixPaths.remove(0); 151 } 152 153 public boolean checkResolverPrefix(final int depth, final List path, final Class kind, final Node currentNode, final Object currentIndex) { 154 final Object [] check = (Object [])path.get(depth-1); 155 final Object nodeCheck = check[0]; 156 final Object indexCheck = check[1]; 157 if(nodeCheck instanceof String ) { 158 if(!currentNode.getTag().equals(nodeCheck)) { 159 return false; 160 } 161 } else if(null != nodeCheck) { 162 if(!((Class )nodeCheck).isInstance(currentNode)) { 163 return false; 164 } 165 } 166 if(indexCheck == Boolean.TRUE && currentIndex != null) { 167 return false; 168 } 169 if(indexCheck == Boolean.FALSE && currentIndex == null) { 170 return false; 171 } 172 if(indexCheck instanceof String ) { 173 if(!(currentIndex instanceof ScalarNode && indexCheck.equals(((ScalarNode)currentIndex).getValue()))) { 174 return false; 175 } 176 } else if(indexCheck instanceof ByteList) { 177 if(!(currentIndex instanceof ScalarNode && indexCheck.equals(((ScalarNode)currentIndex).getValue()))) { 178 return false; 179 } 180 } else if(indexCheck instanceof Integer ) { 181 if(!currentIndex.equals(indexCheck)) { 182 return false; 183 } 184 } 185 return true; 186 } 187 188 public String resolve(final Class kind, final ByteList value, final boolean[] implicit) { 189 List resolvers = null; 190 if(kind.equals(ScalarNode.class) && implicit[0]) { 191 String resolv = SCANNER.recognize(value); 192 if(resolv != null) { 193 return resolv; 194 } 195 } 196 final Map exactPaths = (Map )resolverExactPaths.get(0); 197 if(exactPaths.containsKey(kind)) { 198 return (String )exactPaths.get(kind); 199 } 200 if(exactPaths.containsKey(null)) { 201 return (String )exactPaths.get(null); 202 } 203 if(kind.equals(ScalarNode.class)) { 204 return YAML.DEFAULT_SCALAR_TAG; 205 } else if(kind.equals(SequenceNode.class)) { 206 return YAML.DEFAULT_SEQUENCE_TAG; 207 } else if(kind.equals(MappingNode.class)) { 208 return YAML.DEFAULT_MAPPING_TAG; 209 } 210 return null; 211 } 212 213 private static ByteList s(String se){ 214 return new ByteList(se.getBytes()); 215 } 216 217 public static void main(String [] args) { 218 ByteList[] strings = {s("yes"), s("NO"), s("booooooooooooooooooooooooooooooooooooooooooooooool"), s("false"),s(""), s("~"),s("~a"), 219 s("<<"), s("10.1"), s("10000000000003435345.2324E+13"), s(".23"), s(".nan"), s("null"), s("124233333333333333"), 220 s("0b030323"), s("+0b0111111011010101"), s("0xaafffdf"), s("2005-05-03"), s("2005-05-03a"), s(".nana"), 221 s("2005-03-05T05:23:22"), s("="), s("= "), s("=a")}; 222 boolean[] implicit = new boolean[]{true,true}; 223 Resolver res = new ResolverImpl(); 224 res.descendResolver(null,null); 225 Class s = ScalarNode.class; 226 final long before = System.currentTimeMillis(); 227 final int NUM = 100000; 228 for(int j=0;j<NUM;j++) { 229 for(int i=0;i<strings.length;i++) { 230 res.resolve(s,strings[i%(strings.length)],implicit); 231 } 232 } 233 final long after = System.currentTimeMillis(); 234 final long time = after-before; 235 final double timeS = (after-before)/1000.0; 236 System.out.println("Resolving " + NUM*strings.length + " nodes took " + time + "ms, or " + timeS + " seconds"); 237 } 238 } | Popular Tags |