1 2 12 package com.versant.core.jdo.query; 13 14 import com.versant.core.common.Debug; 15 import com.versant.core.jdo.QueryDetails; 16 import com.versant.core.common.CmdBitSet; 17 import com.versant.core.metadata.ClassMetaData; 18 import com.versant.core.metadata.ModelMetaData; 19 import com.versant.core.util.classhelper.ClassHelper; 20 21 import java.io.StringReader ; 22 23 import com.versant.core.common.BindingSupportImpl; 24 25 28 public class QueryParser { 29 30 private JavaCharStream stream; 31 protected ImportNode[] imports; 32 protected ParamNode[] params; 33 protected VarNode[] vars; 34 protected OrderNode[] orders; 35 protected UnaryNode filter; 36 protected ResultNode resultNode; 37 protected GroupingNode groupingNode; 38 39 private JDOQLParser parser; 40 private JDOQLParserTokenManager tokenManager; 41 42 45 protected ClassMetaData cmd; 46 protected ModelMetaData jmd; 47 48 public QueryParser(ModelMetaData jmd) { 49 this.jmd = jmd; 50 } 51 52 public ClassMetaData getCmd() { 53 return cmd; 54 } 55 56 public ImportNode[] getImports() { 57 return imports; 58 } 59 60 public ParamNode[] getParams() { 61 return params; 62 } 63 64 public void setParams(ParamNode[] params) { 65 this.params = params; 66 } 67 68 public VarNode[] getVars() { 69 return vars; 70 } 71 72 public OrderNode[] getOrders() { 73 return orders; 74 } 75 76 public UnaryNode getFilter() { 77 return filter; 78 } 79 80 public ResultNode getResultNode() { 81 return resultNode; 82 } 83 84 public GroupingNode getGroupingNode() { 85 return groupingNode; 86 } 87 88 public void setGroupingNode(GroupingNode groupingNode) { 89 this.groupingNode = groupingNode; 90 } 91 92 public void parse(QueryDetails q) throws Exception { 93 94 parseJDOQL(q); 95 96 parseCommon(q); 97 } 98 99 public void parseJDOQL(QueryDetails q) throws Exception { 100 cmd = jmd.getClassMetaData(q.getCandidateClass()); 101 String s = q.getImports(); 102 if (s != null) { 103 initParser(s); 104 try { 105 imports = parser.declareImports(); 106 } catch (ParseException e) { 107 throw BindingSupportImpl.getInstance().invalidOperation("Invalid imports:\n" + s + "\n" + 108 e.getMessage()); 109 } 110 if (Debug.DEBUG) { 111 Debug.OUT.println("imports: "); 112 dump(imports); 113 } 114 } else { 115 imports = null; 116 } 117 118 s = q.getParameters(); 120 if (s != null) { 121 initParser(s); 122 try { 123 params = parser.declareParameters(); 124 } catch (ParseException e) { 125 throw BindingSupportImpl.getInstance().invalidOperation("Invalid parameter declarations:\n" + s + "\n" + 126 e.getMessage()); 127 } 128 for (int i = params.length - 1; i >= 0; i--) params[i].setIndex(i); 129 if (Debug.DEBUG) { 130 Debug.OUT.println("params: "); 131 dump(params); 132 } 133 } else { 134 params = null; 135 } 136 137 s = q.getVariables(); 139 if (s != null) { 140 initParser(s); 141 try { 142 vars = parser.declareVariables(); 143 } catch (ParseException e) { 144 throw BindingSupportImpl.getInstance().invalidOperation("Invalid variable declarations:\n" + s + "\n" + 145 e.getMessage()); 146 } 147 if (Debug.DEBUG) { 148 Debug.OUT.println("vars: "); 149 dump(vars); 150 } 151 } else { 152 vars = null; 153 } 154 155 s = q.getOrdering(); 157 if (s != null) { 158 initParser(s); 159 try { 160 orders = parser.setOrderings(); 161 } catch (ParseException e) { 162 throw BindingSupportImpl.getInstance().invalidOperation("Invalid ordering:\n" + s + "\n" + 163 e.getMessage()); 164 } 165 for (int i = 0; i < orders.length; i++) orders[i].normalize(); 166 if (Debug.DEBUG) { 167 Debug.OUT.println("normalized orders: "); 168 dump(orders); 169 } 170 } else { 171 orders = null; 172 } 173 174 s = q.getFilter(); 176 if (s != null) { 177 initParser(q.getFilter()); 178 try { 179 Node e = parser.filterExpression(); 180 if (e != null) { 181 filter = new UnaryNode(e); 182 } else { 183 filter = null; 184 } 185 } catch (ParseException x) { 186 throw BindingSupportImpl.getInstance().invalidOperation("Invalid filter:\n" + s + "\n" + 187 x.getMessage()); 188 } 189 } else { 190 filter = null; 191 } 192 193 s = q.getResult(); 195 if (s != null && s.trim().length() > 0) { 196 initParser(s); 197 try { 198 resultNode = parser.setResults(); 199 } catch (ParseException x) { 200 throw BindingSupportImpl.getInstance().invalidOperation("Invalid result:\n" + s + "\n" + 201 x.getMessage()); 202 } 203 } else { 204 resultNode = null; 205 } 206 207 s = q.getGrouping(); 209 if (s != null) { 210 initParser(s); 211 try { 212 groupingNode = parser.setGrouping(); 213 } catch (ParseException x) { 214 throw BindingSupportImpl.getInstance().invalidOperation("Invalid grouping:\n" + s + "\n" + 215 x.getMessage()); 216 } 217 } else { 218 groupingNode = null; 219 } 220 } 221 222 private void parseCommon(QueryDetails q) throws Exception { 223 224 if (vars != null) { 226 for (int i = vars.length - 1; i >= 0; i--) vars[i].resolve(this); 227 } 228 229 if (filter != null) { 230 if (Debug.DEBUG) { 231 Debug.OUT.println("\n* Filter: " + filter); 232 Debug.OUT.println("\n* Parsed tree:"); 233 filter.dump(""); 234 } 235 236 filter.normalize(); 238 if (Debug.DEBUG) { 239 Debug.OUT.println("\n* Normalized tree:"); 240 filter.dump(""); 241 } 242 243 filter.resolve(this, cmd, false); 245 if (Debug.DEBUG) { 246 Debug.OUT.println("\n* Resolved tree:"); 247 filter.dump(""); 248 } 249 250 filter.normalize(); 253 if (Debug.DEBUG) { 254 Debug.OUT.println("\n* Second normalized tree:"); 255 filter.dump(""); 256 } 257 258 } else { 259 if (Debug.DEBUG) { 260 Debug.OUT.println("filter is null"); 261 } 262 } 263 } 264 265 266 267 271 public OrderNode[] parseOrdering(ClassMetaData candidateClass, String s) 272 throws ParseException { 273 try { 274 if (s != null) { 275 cmd = candidateClass; 276 initParser(s); 277 return parser.setOrderings(); 278 } else { 279 return null; 280 } 281 } catch (TokenMgrError e) { 282 throw new ParseException(e.toString()); 283 } 284 } 285 286 289 public ParamNode findParam(String name) { 290 if (params == null) return null; 291 for (int i = params.length - 1; i >= 0; i--) { 292 ParamNode p = params[i]; 293 if (p.getIdentifier().equals(name)) return p; 294 } 295 return null; 296 } 297 298 301 public VarNode findVar(String name) { 302 if (vars == null) return null; 303 for (int i = vars.length - 1; i >= 0; i--) { 304 VarNode v = vars[i]; 305 if (v.getIdentifier().equals(name)) return v; 306 } 307 return null; 308 } 309 310 public ClassMetaData getCMD(Class cls) { 311 return jmd.getClassMetaData(cls); 312 } 313 314 318 public Class resolveVarType(String type) { 319 Class cls; 320 try { 321 cls = resolveType(type); 322 } catch (ClassNotFoundException e) { 323 throw BindingSupportImpl.getInstance().runtime("Variable class not found: '" + 324 type + "'", e); 325 } 326 return cls; 327 } 328 329 333 public Class resolveParamType(String type) { 334 Class cls; 335 try { 336 cls = resolveType(type); 337 } catch (ClassNotFoundException e) { 338 throw BindingSupportImpl.getInstance().runtime("Parameter class not found: '" + 339 type + "'", e); 340 } 341 return cls; 342 } 343 344 private Class resolveType(String type) throws ClassNotFoundException { 345 try { 346 return resolveTypeImp(type); 347 } catch (ClassNotFoundException e) { 348 int i = type.lastIndexOf('.'); 349 if (i >= 0) { 350 StringBuffer s = new StringBuffer (type); 351 s.setCharAt(i, '$'); 352 try { 353 return resolveTypeImp(s.toString()); 354 } catch (ClassNotFoundException e1) { 355 } 357 } 358 throw e; 359 } 360 } 361 362 private Class resolveTypeImp(String type) throws ClassNotFoundException { 363 ClassLoader loader = cmd.getClassLoader(); 364 try { 365 return ClassHelper.get().classForName(type, true, loader); 366 } catch (ClassNotFoundException e) { 367 if (imports != null) { 368 int len = imports.length; 369 for (int i = 0; i < len; i++) { 370 ImportNode im = imports[i]; 371 if (im.all) { 372 try { 373 return ClassHelper.get().classForName(im.name + type, true, loader); 374 } catch (ClassNotFoundException x) { 375 } 377 } else { 378 if (type.equals(im.getClassName())) { 379 return ClassHelper.get().classForName(im.name, true, loader); 380 } 381 } 382 } 383 } 384 try { 385 return ClassHelper.get().classForName(cmd.packageNameWithDot + 386 type, true, loader); 387 } catch (ClassNotFoundException x) { 388 return ClassHelper.get().classForName("java.lang." + type, true, loader); 389 } 390 } 391 } 392 393 399 public ClassMetaData[] resolveCastType(String type) { 400 ClassMetaData c = jmd.getClassMetaData(type); 401 if (c == null) { 402 if (imports != null) { 403 int len = imports.length; 404 for (int i = 0; i < len && c == null; i++) { 405 ImportNode im = imports[i]; 406 if (im.all) { 407 c = jmd.getClassMetaData(im.name + type); 408 } else if (type.equals(im.getClassName())) { 409 c = jmd.getClassMetaData(im.name); 410 } 411 } 412 } 413 if (c == null) { 414 c = jmd.getClassMetaData(cmd.packageNameWithDot + type); 415 } 416 } 417 if (c == null) { 418 throw BindingSupportImpl.getInstance().runtime("No persistent class found for cast expression: (" + type + 419 "): check the query imports"); 420 } 421 return new ClassMetaData[]{c}; 422 } 423 424 427 private void initParser(String s) { 428 StringReader reader = new StringReader (s); 429 if (stream == null) { 430 stream = new JavaCharStream(reader); 431 } else { 432 stream.ReInit(reader); 433 } 434 if (tokenManager == null) { 435 tokenManager = new JDOQLParserTokenManager(stream); 436 } else { 437 tokenManager.ReInit(stream); 438 } 439 if (parser == null) { 440 parser = new JDOQLParser(tokenManager); 441 } else { 442 parser.ReInit(tokenManager); 443 } 444 } 445 446 private void dump(Node[] a) { 447 for (int i = 0; i < a.length; i++) { 448 Debug.OUT.print("[" + i + "] "); 449 a[i].dump(" "); 450 } 451 } 452 453 457 public CmdBitSet getCmds() { 458 final CmdBitSet bitSet = new CmdBitSet(jmd); 459 bitSet.addPlus(cmd); 460 if (filter != null) { 461 doCmdDependency(filter, bitSet); 462 } 463 if (orders != null) { 464 for (int i = 0; i < orders.length; i++) { 465 doCmdDependency(orders[i], bitSet); 466 } 467 } 468 return bitSet; 469 } 470 471 private void doCmdDependency(Node node, CmdBitSet bitSet) { 472 if (node == null) return; 473 node.updateEvictionDependency(bitSet); 474 for (Node n = node.childList; n != null; n = n.next) { 475 doCmdDependency(n, bitSet); 476 } 477 } 478 479 } 480 | Popular Tags |