1 16 17 package org.apache.xerces.impl.xs.identity; 18 19 import org.apache.xerces.impl.Constants; 20 import org.apache.xerces.impl.xpath.XPath; 21 import org.apache.xerces.util.IntStack; 22 import org.apache.xerces.xni.QName; 23 import org.apache.xerces.xni.XMLAttributes; 24 import org.apache.xerces.xs.AttributePSVI; 25 import org.apache.xerces.xs.ShortList; 26 import org.apache.xerces.xs.XSTypeDefinition; 27 import org.xml.sax.SAXException ; 28 29 30 39 public class XPathMatcher { 40 41 45 47 48 protected static final boolean DEBUG_ALL = false; 49 50 51 protected static final boolean DEBUG_METHODS = false || DEBUG_ALL; 52 53 54 protected static final boolean DEBUG_METHODS2 = false || DEBUG_METHODS || DEBUG_ALL; 55 56 57 protected static final boolean DEBUG_METHODS3 = false || DEBUG_METHODS || DEBUG_ALL; 58 59 60 protected static final boolean DEBUG_MATCH = false || DEBUG_ALL; 61 62 63 protected static final boolean DEBUG_STACK = false || DEBUG_ALL; 64 65 66 protected static final boolean DEBUG_ANY = DEBUG_METHODS || 67 DEBUG_METHODS2 || 68 DEBUG_METHODS3 || 69 DEBUG_MATCH || 70 DEBUG_STACK; 71 72 protected static final int MATCHED = 1; 76 protected static final int MATCHED_ATTRIBUTE = 3; 78 protected static final int MATCHED_DESCENDANT = 5; 80 protected static final int MATCHED_DESCENDANT_PREVIOUS = 13; 82 83 87 88 private XPath.LocationPath[] fLocationPaths; 89 90 91 private int[] fMatched; 92 93 94 protected Object fMatchedString; 95 96 97 private IntStack[] fStepIndexes; 98 99 100 private int[] fCurrentStep; 101 102 106 private int [] fNoMatchDepth; 107 108 final QName fQName = new QName(); 109 110 111 115 121 public XPathMatcher(XPath xpath) { 122 fLocationPaths = xpath.getLocationPaths(); 123 fStepIndexes = new IntStack[fLocationPaths.length]; 124 for(int i=0; i<fStepIndexes.length; i++) fStepIndexes[i] = new IntStack(); 125 fCurrentStep = new int[fLocationPaths.length]; 126 fNoMatchDepth = new int[fLocationPaths.length]; 127 fMatched = new int[fLocationPaths.length]; 128 } 130 134 138 public boolean isMatched() { 139 for (int i=0; i < fLocationPaths.length; i++) 141 if (((fMatched[i] & MATCHED) == MATCHED) 142 && ((fMatched[i] & MATCHED_DESCENDANT_PREVIOUS) != MATCHED_DESCENDANT_PREVIOUS) 143 && ((fNoMatchDepth[i] == 0) 144 || ((fMatched[i] & MATCHED_DESCENDANT) == MATCHED_DESCENDANT))) 145 return true; 146 147 return false; 148 } 150 154 protected void handleContent(XSTypeDefinition type, boolean nillable, Object value, short valueType, ShortList itemValueType) { 157 } 158 159 164 protected void matched(Object actualValue, short valueType, ShortList itemValueType, boolean isNil) { 165 if (DEBUG_METHODS3) { 166 System.out.println(toString()+"#matched(\""+actualValue+"\")"); 167 } 168 } 170 174 177 public void startDocumentFragment(){ 178 if (DEBUG_METHODS) { 179 System.out.println(toString()+"#startDocumentFragment("+ 180 ")"); 181 } 182 183 fMatchedString = null; 185 for(int i = 0; i < fLocationPaths.length; i++) { 186 fStepIndexes[i].clear(); 187 fCurrentStep[i] = 0; 188 fNoMatchDepth[i] = 0; 189 fMatched[i] = 0; 190 } 191 192 193 } 195 205 public void startElement(QName element, XMLAttributes attributes){ 206 if (DEBUG_METHODS2) { 207 System.out.println(toString()+"#startElement("+ 208 "element={"+element+"},"+ 209 "attributes=..."+attributes+ 210 ")"); 211 } 212 213 for(int i = 0; i < fLocationPaths.length; i++) { 214 int startStep = fCurrentStep[i]; 216 fStepIndexes[i].push(startStep); 217 218 if ((fMatched[i] & MATCHED_DESCENDANT) == MATCHED || fNoMatchDepth[i] > 0) { 220 fNoMatchDepth[i]++; 221 continue; 222 } 223 if((fMatched[i] & MATCHED_DESCENDANT) == MATCHED_DESCENDANT) { 224 fMatched[i] = MATCHED_DESCENDANT_PREVIOUS; 225 } 226 227 if (DEBUG_STACK) { 228 System.out.println(toString()+": "+fStepIndexes[i]); 229 } 230 231 XPath.Step[] steps = fLocationPaths[i].steps; 233 while (fCurrentStep[i] < steps.length && 234 steps[fCurrentStep[i]].axis.type == XPath.Axis.SELF) { 235 if (DEBUG_MATCH) { 236 XPath.Step step = steps[fCurrentStep[i]]; 237 System.out.println(toString()+" [SELF] MATCHED!"); 238 } 239 fCurrentStep[i]++; 240 } 241 if (fCurrentStep[i] == steps.length) { 242 if (DEBUG_MATCH) { 243 System.out.println(toString()+" XPath MATCHED!"); 244 } 245 fMatched[i] = MATCHED; 246 continue; 247 } 248 249 int descendantStep = fCurrentStep[i]; 254 while(fCurrentStep[i] < steps.length && steps[fCurrentStep[i]].axis.type == XPath.Axis.DESCENDANT) { 255 if (DEBUG_MATCH) { 256 XPath.Step step = steps[fCurrentStep[i]]; 257 System.out.println(toString()+" [DESCENDANT] MATCHED!"); 258 } 259 fCurrentStep[i]++; 260 } 261 boolean sawDescendant = fCurrentStep[i] > descendantStep; 262 if (fCurrentStep[i] == steps.length) { 263 if (DEBUG_MATCH) { 264 System.out.println(toString()+" XPath DIDN'T MATCH!"); 265 } 266 fNoMatchDepth[i]++; 267 if (DEBUG_MATCH) { 268 System.out.println(toString()+" [CHILD] after NO MATCH"); 269 } 270 continue; 271 } 272 273 if ((fCurrentStep[i] == startStep || fCurrentStep[i] > descendantStep) && 275 steps[fCurrentStep[i]].axis.type == XPath.Axis.CHILD) { 276 XPath.Step step = steps[fCurrentStep[i]]; 277 XPath.NodeTest nodeTest = step.nodeTest; 278 if (DEBUG_MATCH) { 279 System.out.println(toString()+" [CHILD] before"); 280 } 281 if (nodeTest.type == XPath.NodeTest.QNAME) { 282 if (!nodeTest.name.equals(element)) { 283 if(fCurrentStep[i] > descendantStep) { 284 fCurrentStep[i] = descendantStep; 285 continue; 286 } 287 fNoMatchDepth[i]++; 288 if (DEBUG_MATCH) { 289 System.out.println(toString()+" [CHILD] after NO MATCH"); 290 } 291 continue; 292 } 293 } 294 fCurrentStep[i]++; 295 if (DEBUG_MATCH) { 296 System.out.println(toString()+" [CHILD] after MATCHED!"); 297 } 298 } 299 if (fCurrentStep[i] == steps.length) { 300 if(sawDescendant) { 301 fCurrentStep[i] = descendantStep; 302 fMatched[i] = MATCHED_DESCENDANT; 303 } else { 304 fMatched[i] = MATCHED; 305 } 306 continue; 307 } 308 309 if (fCurrentStep[i] < steps.length && 311 steps[fCurrentStep[i]].axis.type == XPath.Axis.ATTRIBUTE) { 312 if (DEBUG_MATCH) { 313 System.out.println(toString()+" [ATTRIBUTE] before"); 314 } 315 int attrCount = attributes.getLength(); 316 if (attrCount > 0) { 317 XPath.NodeTest nodeTest = steps[fCurrentStep[i]].nodeTest; 318 319 for (int aIndex = 0; aIndex < attrCount; aIndex++) { 320 attributes.getName(aIndex, fQName); 321 if (nodeTest.type != XPath.NodeTest.QNAME || 322 nodeTest.name.equals(fQName)) { 323 fCurrentStep[i]++; 324 if (fCurrentStep[i] == steps.length) { 325 fMatched[i] = MATCHED_ATTRIBUTE; 326 int j=0; 327 for(; j<i && ((fMatched[j] & MATCHED) != MATCHED); j++); 328 if(j==i) { 329 AttributePSVI attrPSVI = (AttributePSVI)attributes.getAugmentations(aIndex).getItem(Constants.ATTRIBUTE_PSVI); 330 fMatchedString = attrPSVI.getActualNormalizedValue(); 331 matched(fMatchedString, attrPSVI.getActualNormalizedValueType(), attrPSVI.getItemValueTypes(), false); 332 } 333 } 334 break; 335 } 336 } 337 } 338 if ((fMatched[i] & MATCHED) != MATCHED) { 339 if(fCurrentStep[i] > descendantStep) { 340 fCurrentStep[i] = descendantStep; 341 continue; 342 } 343 fNoMatchDepth[i]++; 344 if (DEBUG_MATCH) { 345 System.out.println(toString()+" [ATTRIBUTE] after"); 346 } 347 continue; 348 } 349 if (DEBUG_MATCH) { 350 System.out.println(toString()+" [ATTRIBUTE] after MATCHED!"); 351 } 352 } 353 } 354 355 } 356 358 372 public void endElement(QName element, XSTypeDefinition type, boolean nillable, Object value, short valueType, ShortList itemValueType) { 373 if (DEBUG_METHODS2) { 374 System.out.println(toString()+"#endElement("+ 375 "element={"+element+"},"+ 376 ")"); 377 } 378 for(int i = 0; i<fLocationPaths.length; i++) { 379 fCurrentStep[i] = fStepIndexes[i].pop(); 381 382 if (fNoMatchDepth[i] > 0) { 384 fNoMatchDepth[i]--; 385 } 386 387 else { 389 int j=0; 390 for(; j<i && ((fMatched[j] & MATCHED) != MATCHED); j++); 391 if ((j<i) || (fMatched[j] == 0) || 392 ((fMatched[j] & MATCHED_ATTRIBUTE) == MATCHED_ATTRIBUTE)) { 393 continue; 394 } 395 handleContent(type, nillable, value, valueType, itemValueType); 400 fMatched[i] = 0; 401 } 402 403 if (DEBUG_STACK) { 404 System.out.println(toString()+": "+fStepIndexes[i]); 405 } 406 } 407 408 } 410 414 415 public String toString() { 416 419 StringBuffer str = new StringBuffer (); 420 String s = super.toString(); 421 int index2 = s.lastIndexOf('.'); 422 if (index2 != -1) { 423 s = s.substring(index2 + 1); 424 } 425 str.append(s); 426 for(int i =0;i<fLocationPaths.length; i++) { 427 str.append('['); 428 XPath.Step[] steps = fLocationPaths[i].steps; 429 for (int j = 0; j < steps.length; j++) { 430 if (j == fCurrentStep[i]) { 431 str.append('^'); 432 } 433 str.append(steps[j].toString()); 434 if (j < steps.length - 1) { 435 str.append('/'); 436 } 437 } 438 if (fCurrentStep[i] == steps.length) { 439 str.append('^'); 440 } 441 str.append(']'); 442 str.append(','); 443 } 444 return str.toString(); 445 } 447 451 452 private String normalize(String s) { 453 StringBuffer str = new StringBuffer (); 454 int length = s.length(); 455 for (int i = 0; i < length; i++) { 456 char c = s.charAt(i); 457 switch (c) { 458 case '\n': { 459 str.append("\\n"); 460 break; 461 } 462 default: { 463 str.append(c); 464 } 465 } 466 } 467 return str.toString(); 468 } 470 474 482 483 518 519 } | Popular Tags |