1 57 58 package org.enhydra.apache.xerces.validators.schema.identity; 59 60 import org.enhydra.apache.xerces.framework.XMLAttrList; 61 import org.enhydra.apache.xerces.utils.IntStack; 62 import org.enhydra.apache.xerces.utils.NamespacesScope; 63 import org.enhydra.apache.xerces.utils.QName; 64 import org.enhydra.apache.xerces.utils.StringPool; 65 import org.enhydra.apache.xerces.validators.common.XMLAttributeDecl; 66 import org.enhydra.apache.xerces.validators.common.XMLElementDecl; 67 import org.enhydra.apache.xerces.validators.datatype.DatatypeValidator; 68 import org.enhydra.apache.xerces.validators.schema.SchemaGrammar; 69 import org.enhydra.apache.xerces.validators.schema.SchemaSymbols; 70 import org.xml.sax.SAXException ; 71 72 77 78 85 public class XPathMatcher { 86 87 91 93 94 protected static final boolean DEBUG_ALL = false; 95 96 97 protected static final boolean DEBUG_METHODS = false || DEBUG_ALL; 98 99 100 protected static final boolean DEBUG_METHODS2 = false || DEBUG_METHODS || DEBUG_ALL; 101 102 103 protected static final boolean DEBUG_METHODS3 = false || DEBUG_METHODS || DEBUG_ALL; 104 105 106 protected static final boolean DEBUG_MATCH = false || DEBUG_ALL; 107 108 109 protected static final boolean DEBUG_STACK = false || DEBUG_ALL; 110 111 112 protected static final boolean DEBUG_ANY = DEBUG_METHODS || 113 DEBUG_METHODS2 || 114 DEBUG_METHODS3 || 115 DEBUG_MATCH || 116 DEBUG_STACK; 117 118 122 123 private XPath.LocationPath[] fLocationPaths; 124 125 126 private boolean fShouldBufferContent; 127 128 129 private boolean fBufferContent; 130 131 132 private StringBuffer fMatchedBuffer = new StringBuffer (); 133 134 135 private boolean[] fMatched; 136 137 138 private String fMatchedString; 139 140 141 private IntStack[] fStepIndexes; 142 143 144 private int[] fCurrentStep; 145 146 150 private int [] fNoMatchDepth; 151 152 154 155 protected StringPool fStringPool; 156 157 158 protected NamespacesScope fNamespacesScope; 159 160 protected IdentityConstraint fIDConstraint; 163 164 168 174 public XPathMatcher(XPath xpath) { 175 this(xpath, false, null); 176 } 178 188 public XPathMatcher(XPath xpath, boolean shouldBufferContent, IdentityConstraint idConstraint) { 189 fLocationPaths = xpath.getLocationPaths(); 190 fShouldBufferContent = shouldBufferContent; 191 fIDConstraint = idConstraint; 192 fStepIndexes = new IntStack[fLocationPaths.length]; 193 for(int i=0; i<fStepIndexes.length; i++) fStepIndexes[i] = new IntStack(); 194 fCurrentStep = new int[fLocationPaths.length]; 195 fNoMatchDepth = new int[fLocationPaths.length]; 196 fMatched = new boolean[fLocationPaths.length]; 197 if (DEBUG_METHODS) { 198 System.out.println(toString()+"#<init>()"); 199 } 200 } 202 206 207 public boolean isMatched() { 208 for (int i=0; i < fLocationPaths.length; i++) 210 if (fMatched[i]) return true; 211 return false; 212 } 214 public boolean getIsSelector() { 216 return (fIDConstraint == null); 217 } 219 public IdentityConstraint getIDConstraint() { 221 return fIDConstraint; 222 } 224 225 public String getMatchedString() { 226 return fMatchedString; 227 } 229 233 238 protected void matched(String content, DatatypeValidator val, boolean isNil) throws Exception { 239 if (DEBUG_METHODS3) { 240 System.out.println(toString()+"#matched(\""+normalize(content)+"\")"); 241 } 242 } 244 248 257 public void startDocumentFragment(StringPool stringPool) 258 throws Exception { 259 if (DEBUG_METHODS) { 260 System.out.println(toString()+"#startDocumentFragment("+ 261 "stringPool="+stringPool+','+ 262 ")"); 263 } 264 265 clear(); 267 for(int i = 0; i < fLocationPaths.length; i++) { 268 fStepIndexes[i].clear(); 269 fCurrentStep[i] = 0; 270 fNoMatchDepth[i] = 0; 271 fMatched[i]=false; 272 } 273 274 fStringPool = stringPool; 276 277 } 279 291 public void startElement(QName element, XMLAttrList attributes, int handle, 292 int eIndex, SchemaGrammar grammar) 293 throws Exception { 294 if (DEBUG_METHODS2) { 295 System.out.println(toString()+"#startElement("+ 296 "element={"+ 297 "prefix="+fStringPool.toString(element.prefix)+','+ 298 "localpart="+fStringPool.toString(element.localpart)+','+ 299 "rawname="+fStringPool.toString(element.rawname)+','+ 300 "uri="+fStringPool.toString(element.uri)+ 301 "},"+ 302 "attributes=..."+ ")"); 304 } 305 306 for(int i = 0; i < fLocationPaths.length; i++) { 307 int startStep = fCurrentStep[i]; 309 fStepIndexes[i].push(startStep); 310 311 if (fMatched[i] || fNoMatchDepth[i] > 0) { 313 fNoMatchDepth[i]++; 314 continue; 315 } 316 317 if (DEBUG_STACK) { 318 System.out.println(toString()+": "+fStepIndexes[i]); 319 } 320 321 XPath.Step[] steps = fLocationPaths[i].steps; 323 while (fCurrentStep[i] < steps.length && 324 steps[fCurrentStep[i]].axis.type == XPath.Axis.SELF) { 325 if (DEBUG_MATCH) { 326 XPath.Step step = steps[fCurrentStep[i]]; 327 System.out.println(toString()+" [SELF] MATCHED!"); 328 } 329 fCurrentStep[i]++; 330 } 331 if (fCurrentStep[i] == steps.length) { 332 if (DEBUG_MATCH) { 333 System.out.println(toString()+" XPath MATCHED!"); 334 } 335 fMatched[i] = true; 336 int j=0; 337 for(; j<i && !fMatched[j]; j++); 338 if(j==i) 339 fBufferContent = fShouldBufferContent; 340 continue; 341 } 342 343 int descendantStep = fCurrentStep[i]; 348 while(fCurrentStep[i] < steps.length && steps[fCurrentStep[i]].axis.type == XPath.Axis.DESCENDANT) { 349 if (DEBUG_MATCH) { 350 XPath.Step step = steps[fCurrentStep[i]]; 351 System.out.println(toString()+" [DESCENDANT] MATCHED!"); 352 } 353 fCurrentStep[i]++; 354 } 355 if (fCurrentStep[i] == steps.length) { 356 if (DEBUG_MATCH) { 357 System.out.println(toString()+" XPath DIDN'T MATCH!"); 358 } 359 fNoMatchDepth[i]++; 360 if (DEBUG_MATCH) { 361 System.out.println(toString()+" [CHILD] after NO MATCH"); 362 } 363 continue; 364 } 365 366 if ((fCurrentStep[i] == startStep || fCurrentStep[i] > descendantStep) && 368 steps[fCurrentStep[i]].axis.type == XPath.Axis.CHILD) { 369 XPath.Step step = steps[fCurrentStep[i]]; 370 XPath.NodeTest nodeTest = step.nodeTest; 371 if (DEBUG_MATCH) { 372 System.out.println(toString()+" [CHILD] before"); 373 } 374 if (nodeTest.type == XPath.NodeTest.QNAME) { 375 if (!nodeTest.name.equals(element)) { 376 if(fCurrentStep[i] > descendantStep) { 377 fCurrentStep[i] = descendantStep; 378 continue; 379 } 380 fNoMatchDepth[i]++; 381 if (DEBUG_MATCH) { 382 System.out.println(toString()+" [CHILD] after NO MATCH"); 383 } 384 continue; 385 } 386 } 387 fCurrentStep[i]++; 388 if (DEBUG_MATCH) { 389 System.out.println(toString()+" [CHILD] after MATCHED!"); 390 } 391 } 392 if (fCurrentStep[i] == steps.length) { 393 fMatched[i] = true; 394 int j=0; 395 for(; j<i && !fMatched[j]; j++); 396 if(j==i) 397 fBufferContent = fShouldBufferContent; 398 continue; 399 } 400 401 if (fCurrentStep[i] < steps.length && 403 steps[fCurrentStep[i]].axis.type == XPath.Axis.ATTRIBUTE) { 404 if (DEBUG_MATCH) { 405 System.out.println(toString()+" [ATTRIBUTE] before"); 406 } 407 int aindex = attributes.getFirstAttr(handle); 408 if (aindex != -1) { 409 XPath.NodeTest nodeTest = steps[fCurrentStep[i]].nodeTest; 410 QName aname = new QName(); while (aindex != -1) { 412 int aprefix = attributes.getAttrPrefix(aindex); 413 int alocalpart = attributes.getAttrLocalpart(aindex); 414 int arawname = attributes.getAttrName(aindex); 415 int auri = attributes.getAttrURI(aindex); 416 aname.setValues(aprefix, alocalpart, arawname, auri); 417 if (nodeTest.type != XPath.NodeTest.QNAME || 418 nodeTest.name.equals(aname)) { 419 fCurrentStep[i]++; 420 if (fCurrentStep[i] == steps.length) { 421 fMatched[i] = true; 422 int j=0; 423 for(; j<i && !fMatched[j]; j++); 424 if(j==i) { 425 int avalue = attributes.getAttValue(aindex); 426 fMatchedString = fStringPool.toString(avalue); 427 int attIndex = grammar.getAttributeDeclIndex(eIndex, aname); 430 XMLAttributeDecl tempAttDecl = new XMLAttributeDecl(); 431 grammar.getAttributeDecl(attIndex, tempAttDecl); 432 DatatypeValidator aValidator = tempAttDecl.datatypeValidator; 433 matched(fMatchedString, aValidator, false); 434 } 435 } 436 break; 437 } 438 aindex = attributes.getNextAttr(aindex); 439 } 440 } 441 if (!fMatched[i]) { 442 if(fCurrentStep[i] > descendantStep) { 443 fCurrentStep[i] = descendantStep; 444 continue; 445 } 446 fNoMatchDepth[i]++; 447 if (DEBUG_MATCH) { 448 System.out.println(toString()+" [ATTRIBUTE] after"); 449 } 450 continue; 451 } 452 if (DEBUG_MATCH) { 453 System.out.println(toString()+" [ATTRIBUTE] after MATCHED!"); 454 } 455 } 456 } 457 458 } 460 461 public void characters(char[] ch, int offset, int length) 462 throws Exception { 463 if (DEBUG_METHODS) { 464 System.out.println(toString()+"#characters("+ 465 "text="+normalize(new String (ch, offset, length))+ 466 ")"); 467 } 468 469 for(int i=0; i<fLocationPaths.length; i++) 472 if (fBufferContent && fNoMatchDepth[i] == 0) { 473 if (!DEBUG_METHODS && DEBUG_METHODS2) { 474 System.out.println(toString()+"#characters("+ 475 "text="+normalize(new String (ch, offset, length))+ 476 ")"); 477 } 478 fMatchedBuffer.append(ch, offset, length); 479 break; 480 } 481 482 } 484 493 public void endElement(QName element, int eIndex, SchemaGrammar grammar) throws Exception { 494 if (DEBUG_METHODS2) { 495 System.out.println(toString()+"#endElement("+ 496 "element={"+ 497 "prefix="+fStringPool.toString(element.prefix)+','+ 498 "localpart="+fStringPool.toString(element.localpart)+','+ 499 "rawname="+fStringPool.toString(element.rawname)+','+ 500 "uri="+fStringPool.toString(element.uri)+ 501 "ID constraint="+fIDConstraint+ 502 "})"); 503 } 504 505 for(int i = 0; i<fLocationPaths.length; i++) { 506 if (fNoMatchDepth[i] > 0) { 508 fNoMatchDepth[i]--; 509 } 510 511 else { 513 int j=0; 514 for(; j<i && !fMatched[j]; j++); 515 if (j<i) continue; 516 if (fBufferContent) { 517 fBufferContent = false; 518 fMatchedString = fMatchedBuffer.toString(); 519 XMLElementDecl temp = new XMLElementDecl(); 520 grammar.getElementDecl(eIndex, temp); 521 DatatypeValidator val = temp.datatypeValidator; 522 if(temp != null) { 523 matched(fMatchedString, val, (grammar.getElementDeclMiscFlags(eIndex) & SchemaSymbols.NILLABLE) != 0); 524 } else 525 matched(fMatchedString, null, false); 526 } 527 clear(); 528 } 529 530 fCurrentStep[i] = fStepIndexes[i].pop(); 532 533 if (DEBUG_STACK) { 534 System.out.println(toString()+": "+fStepIndexes[i]); 535 } 536 } 537 538 } 540 545 public void endDocumentFragment() throws Exception { 546 if (DEBUG_METHODS) { 547 System.out.println(toString()+"#endDocumentFragment()"); 548 } 549 clear(); 550 } 552 556 557 public String toString() { 558 561 StringBuffer str = new StringBuffer (); 562 String s = super.toString(); 563 int index2 = s.lastIndexOf('.'); 564 if (index2 != -1) { 565 s = s.substring(index2 + 1); 566 } 567 str.append(s); 568 for(int i =0;i<fLocationPaths.length; i++) { 569 str.append('['); 570 XPath.Step[] steps = fLocationPaths[i].steps; 571 for (int j = 0; j < steps.length; j++) { 572 if (j == fCurrentStep[i]) { 573 str.append('^'); 574 } 575 str.append(steps[i].toString()); 576 if (j < steps.length - 1) { 577 str.append('/'); 578 } 579 } 580 if (fCurrentStep[i] == steps.length) { 581 str.append('^'); 582 } 583 str.append(']'); 584 str.append(','); 585 } 586 return str.toString(); 587 } 589 593 594 private void clear() { 595 fBufferContent = false; 596 fMatchedBuffer.setLength(0); 597 fMatchedString = null; 598 for(int i = 0; i<fLocationPaths.length; i++) 599 fMatched[i] = false; 600 } 602 603 private String normalize(String s) { 604 StringBuffer str = new StringBuffer (); 605 int length = s.length(); 606 for (int i = 0; i < length; i++) { 607 char c = s.charAt(i); 608 switch (c) { 609 case '\n': { 610 str.append("\\n"); 611 break; 612 } 613 default: { 614 str.append(c); 615 } 616 } 617 } 618 return str.toString(); 619 } 621 625 633 634 670 671 } | Popular Tags |