1 package net.sf.saxon.trans; 2 3 import net.sf.saxon.Configuration; 4 import net.sf.saxon.expr.XPathContext; 5 import net.sf.saxon.expr.XPathContextMajor; 6 import net.sf.saxon.om.Navigator; 7 import net.sf.saxon.om.NodeInfo; 8 import net.sf.saxon.pattern.NoNodeTest; 9 import net.sf.saxon.pattern.Pattern; 10 import net.sf.saxon.type.Type; 11 12 import java.io.Serializable ; 13 14 20 21 public class Mode implements Serializable { 22 23 public static final int DEFAULT_MODE = -1; 24 public static final int ALL_MODES = -2; 25 public static final int NAMED_MODE = -3; 26 public static final int STRIPPER_MODE = -4; 27 28 29 private Rule[] ruleDict = new Rule[101 + Type.MAX_NODE_TYPE]; 30 private int sequence = 0; private boolean isDefault; 32 private boolean isStripper; 33 34 38 39 public Mode(int usage) { 40 this.isDefault = (usage == DEFAULT_MODE); 41 this.isStripper = (usage == STRIPPER_MODE); 42 } 43 44 45 46 51 52 public Mode(Mode omniMode) { 53 isDefault = false; 54 isStripper = false; 55 if (omniMode != null) { 56 for (int i = 0; i < this.ruleDict.length; i++) { 57 if (omniMode.ruleDict[i] != null) { 58 this.ruleDict[i] = new Rule(omniMode.ruleDict[i]); 59 } 60 } 61 this.sequence = omniMode.sequence; 62 } 63 } 64 65 68 69 public boolean isDefaultMode() { 70 return isDefault; 71 } 72 73 83 84 public void addRule(Pattern p, Object obj, int precedence, double priority) { 85 86 88 90 if (p.getNodeTest() instanceof NoNodeTest) { 91 return; 92 } 93 94 99 int fingerprint = p.getFingerprint(); 100 int type = p.getNodeKind(); 101 102 int key = getList(fingerprint, type); 103 105 Rule newRule = new Rule(p, obj, precedence, priority, sequence++); 106 107 Rule rule = ruleDict[key]; 108 if (rule == null) { 109 ruleDict[key] = newRule; 110 return; 111 } 112 113 115 Rule prev = null; 116 while (rule != null) { 117 if ((rule.precedence < precedence) || 118 (rule.precedence == precedence && rule.priority <= priority)) { 119 newRule.next = rule; 120 if (prev == null) { 121 ruleDict[key] = newRule; 122 } else { 123 prev.next = newRule; 124 } 125 break; 126 } else { 127 prev = rule; 128 rule = rule.next; 129 } 130 } 131 if (rule == null) { 132 prev.next = newRule; 133 newRule.next = null; 134 } 135 } 136 137 140 141 public int getList(int fingerprint, int type) { 142 143 if (type == Type.ELEMENT) { 144 if (fingerprint == -1) { 145 return Type.NODE; } else { 147 return Type.MAX_NODE_TYPE + 148 (fingerprint % 101); 149 } 150 } else { 151 return type; 152 } 153 } 154 155 161 162 public Object getRule(NodeInfo node, XPathContext context) throws XPathException { 163 int fingerprint = node.getFingerprint(); 165 int type = node.getNodeKind(); 167 int key = getList(fingerprint, type); 168 int policy = context.getController().getRecoveryPolicy(); 169 170 176 context = perhapsMakeNewContext(context); 177 178 Rule specificRule = null; 179 Rule generalRule = null; 180 int specificPrecedence = -1; 181 double specificPriority = Double.NEGATIVE_INFINITY; 182 183 185 187 if (key != Type.NODE) { 188 Rule r = ruleDict[key]; 189 while (r != null) { 190 if (specificRule != null) { 193 if (r.precedence < specificPrecedence || 194 (r.precedence == specificPrecedence && r.priority < specificPriority)) { 195 break; 196 } 197 } 198 if (r.pattern.matches(node, context)) { 200 202 if (specificRule != null) { 204 if (r.precedence == specificPrecedence && r.priority == specificPriority) { 205 reportAmbiguity(node, specificRule, r, context); 206 } 207 break; 208 } 209 specificRule = r; 210 specificPrecedence = r.precedence; 211 specificPriority = r.priority; 212 if (policy == Configuration.RECOVER_SILENTLY) { 213 break; } 215 } 216 r = r.next; 217 } 218 } 219 220 222 Rule r2 = ruleDict[Type.NODE]; 223 while (r2 != null) { 224 if (r2.precedence < specificPrecedence || 225 (r2.precedence == specificPrecedence && r2.priority < specificPriority)) { 226 break; } 228 if (r2.pattern.matches(node, context)) { 229 if (generalRule != null) { 231 if (r2.precedence == generalRule.precedence && r2.priority == generalRule.priority) { 232 reportAmbiguity(node, r2, generalRule, context); 233 } 234 break; 235 } else { 236 generalRule = r2; 237 if (policy == Configuration.RECOVER_SILENTLY) { 238 break; } 240 } 241 } 242 r2 = r2.next; 243 } 244 245 if (specificRule != null && generalRule == null) { 246 return specificRule.object; 247 } 248 if (specificRule == null && generalRule != null) { 249 return generalRule.object; 250 } 251 if (specificRule != null && generalRule != null) { 252 if (specificRule.precedence == generalRule.precedence && 253 specificRule.priority == generalRule.priority) { 254 Object result = (specificRule.sequence > generalRule.sequence ? 259 specificRule.object : 260 generalRule.object); 261 262 if (policy != Configuration.RECOVER_SILENTLY) { 263 reportAmbiguity(node, specificRule, generalRule, context); 264 } 265 return result; 266 } 267 if (specificRule.precedence > generalRule.precedence || 268 (specificRule.precedence == generalRule.precedence && 269 specificRule.priority >= generalRule.priority)) { 270 return specificRule.object; 271 } else { 272 return generalRule.object; 273 } 274 } 275 return null; 276 } 277 278 285 286 private XPathContext perhapsMakeNewContext(XPathContext context) { 287 int patternLocals = context.getController().getExecutable().getLargestPatternStackFrame(); 288 if (patternLocals > 0) { 289 context = context.newContext(); 290 context.setOrigin(context.getController()); 291 ((XPathContextMajor)context).openStackFrame(patternLocals); 292 } 293 return context; 294 } 295 296 303 304 public Object getRule(NodeInfo node, int min, int max, XPathContext context) throws XPathException { 305 int fing = node.getFingerprint(); 306 int type = node.getNodeKind(); 307 int key = getList(fing, type); 308 309 Rule specificRule = null; 310 Rule generalRule = null; 311 312 context = perhapsMakeNewContext(context); 313 314 316 if (key != Type.NODE) { 317 Rule r = ruleDict[key]; 318 while (r != null) { 319 if (r.precedence >= min && r.precedence <= max && 320 r.pattern.matches(node, context)) { 321 specificRule = r; 322 break; } 324 r = r.next; 325 } 326 } 327 328 330 Rule r2 = ruleDict[Type.NODE]; 331 while (r2 != null) { 332 if (r2.precedence >= min && r2.precedence <= max && r2.pattern.matches(node, context)) { 333 generalRule = r2; 334 break; } 336 r2 = r2.next; 337 } 338 if (specificRule != null && generalRule == null) { 339 return specificRule.object; 340 } 341 if (specificRule == null && generalRule != null) { 342 return generalRule.object; 343 } 344 if (specificRule != null && generalRule != null) { 345 if (specificRule.precedence > generalRule.precedence || 346 (specificRule.precedence == generalRule.precedence && 347 specificRule.priority >= generalRule.priority)) { 348 return specificRule.object; 349 } else { 350 return generalRule.object; 351 } 352 } 353 return null; 354 } 355 356 363 364 public Object getNextMatchRule(NodeInfo node, Object currentHandler, XPathContext context) throws XPathException { 365 int fingerprint = node.getFingerprint(); 366 int type = node.getNodeKind(); 367 int key = getList(fingerprint, type); 368 int policy = context.getController().getRecoveryPolicy(); 369 370 int currentPrecedence = -1; 371 double currentPriority = -1.0; 372 int currentSequence = -1; 373 374 context = perhapsMakeNewContext(context); 375 376 378 Rule r = ruleDict[key]; 379 while (r != null) { 380 if (r.object == currentHandler) { 381 currentPrecedence = r.precedence; 382 currentPriority = r.priority; 383 currentSequence = r.sequence; 384 break; 385 } else { 386 r = r.next; 387 } 388 } 389 if (r == null) { 390 r = ruleDict[Type.NODE]; 391 while (r != null) { 392 if (r.object == currentHandler) { 393 currentPrecedence = r.precedence; 394 currentPriority = r.priority; 395 currentSequence = r.sequence; 396 break; 397 } else { 398 r = r.next; 399 } 400 } 401 if (r == null) { 402 DynamicError de = new DynamicError("Internal error: current template doesn't match current node"); 403 de.setXPathContext(context); 404 de.setErrorCode("SAXON:0000"); 405 throw de; 406 } 407 } 408 409 Rule specificRule = null; 410 Rule generalRule = null; 411 int specificPrecedence = -1; 412 double specificPriority = Double.NEGATIVE_INFINITY; 413 414 416 418 if (key != Type.NODE) { 419 r = ruleDict[key]; 420 while (r != null) { 421 if (r.object == currentHandler) { 424 } else 426 if ((r.precedence > currentPrecedence) || 428 (r.precedence == currentPrecedence && 429 (r.priority > currentPriority || 430 (r.priority == currentPriority && r.sequence >= currentSequence)))) { 431 } else { 433 if (specificRule != null) { 435 if (r.precedence < specificPrecedence || 436 (r.precedence == specificPrecedence && r.priority < specificPriority)) { 437 break; 438 } 439 } 440 if (r.pattern.matches(node, context)) { 442 444 if (specificRule != null) { 446 if (r.precedence == specificPrecedence && r.priority == specificPriority) { 447 reportAmbiguity(node, specificRule, r, context); 448 } 449 break; 450 } 451 specificRule = r; 452 specificPrecedence = r.precedence; 453 specificPriority = r.priority; 454 if (policy == Configuration.RECOVER_SILENTLY) { 455 break; } 457 } 458 } 459 r = r.next; 460 } 461 } 462 463 465 Rule r2 = ruleDict[Type.NODE]; 466 while (r2 != null) { 467 if (r2.object == currentHandler) { 469 } else 471 if ((r2.precedence > currentPrecedence) || 473 (r2.precedence == currentPrecedence && 474 (r2.priority > currentPriority || 475 (r2.priority == currentPriority && r2.sequence >= currentSequence)))) { 476 } else { 478 if (r2.precedence < specificPrecedence || 479 (r2.precedence == specificPrecedence && r2.priority < specificPriority)) { 480 break; } 482 if (r2.pattern.matches(node, context)) { 483 if (generalRule != null) { 485 if (r2.precedence == generalRule.precedence && r2.priority == generalRule.priority) { 486 reportAmbiguity(node, r2, generalRule, context); 487 } 488 break; 489 } else { 490 generalRule = r2; 491 if (policy == Configuration.RECOVER_SILENTLY) { 492 break; } 494 } 495 } 496 } 497 r2 = r2.next; 498 } 499 500 if (specificRule != null && generalRule == null) { 501 return specificRule.object; 502 } 503 if (specificRule == null && generalRule != null) { 504 return generalRule.object; 505 } 506 if (specificRule != null && generalRule != null) { 507 if (specificRule.precedence == generalRule.precedence && 508 specificRule.priority == generalRule.priority) { 509 Object result = (specificRule.sequence > generalRule.sequence ? 514 specificRule.object : 515 generalRule.object); 516 517 if (policy != Configuration.RECOVER_SILENTLY) { 518 reportAmbiguity(node, specificRule, generalRule, context); 519 } 520 return result; 521 } 522 if (specificRule.precedence > generalRule.precedence || 523 (specificRule.precedence == generalRule.precedence && 524 specificRule.priority >= generalRule.priority)) { 525 return specificRule.object; 526 } else { 527 return generalRule.object; 528 } 529 } 530 return null; 531 } 532 533 542 543 private void reportAmbiguity(NodeInfo node, Rule r1, Rule r2, XPathContext c) 544 throws XPathException { 545 if (r1.object == r2.object) { 548 return; 549 } 550 String path; 551 String errorCode = "XTRE0540"; 552 553 if (isStripper) { 554 if (r1.object.equals(r2.object)) { 557 return; 558 } 559 errorCode = "XTRE0270"; 560 path = "xsl:strip-space"; 561 } else { 562 path = Navigator.getPath(node); 563 } 564 565 Pattern pat1 = r1.pattern; 566 Pattern pat2 = r2.pattern; 567 568 DynamicError err = new DynamicError("Ambiguous rule match for " + path + '\n' + 569 "Matches both \"" + pat1 + "\" on line " + pat1.getLineNumber() + " of " + pat1.getSystemId() + 570 "\nand \"" + pat2 + "\" on line " + pat2.getLineNumber() + " of " + pat2.getSystemId()); 571 err.setErrorCode(errorCode); 572 err.setLocator(c.getOrigin().getInstructionInfo()); 573 c.getController().recoverableError(err); 574 } 575 576 577 580 581 public static class Rule implements Serializable { 582 public Pattern pattern; 583 public Object object; 584 public int precedence; 585 public double priority; 586 public int sequence; 587 public Rule next; 588 589 598 599 public Rule(Pattern p, Object o, int prec, double prio, int seq) { 600 pattern = p; 601 object = o; 602 precedence = prec; 603 priority = prio; 604 next = null; 605 sequence = seq; 606 } 607 608 613 614 public Rule(Rule r) { 615 this.pattern = r.pattern; 616 this.object = r.object; 617 this.precedence = r.precedence; 618 this.priority = r.priority; 619 this.sequence = r.sequence; 620 if (r.next == null) { 621 this.next = null; 622 } else { 623 this.next = new Rule(r.next); 624 } 625 } 626 627 } 628 629 } 630 631 | Popular Tags |