1. /*
  2. * Copyright 1999-2004 The Apache Software Foundation.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. /*
  17. * $Id: WalkerFactory.java,v 1.28 2004/02/17 04:32:08 minchau Exp $
  18. */
  19. package com.sun.org.apache.xpath.internal.axes;
  20. import com.sun.org.apache.xalan.internal.res.XSLMessages;
  21. import com.sun.org.apache.xml.internal.dtm.Axis;
  22. import com.sun.org.apache.xml.internal.dtm.DTMFilter;
  23. import com.sun.org.apache.xml.internal.dtm.DTMIterator;
  24. import com.sun.org.apache.xpath.internal.Expression;
  25. import com.sun.org.apache.xpath.internal.compiler.Compiler;
  26. import com.sun.org.apache.xpath.internal.compiler.FunctionTable;
  27. import com.sun.org.apache.xpath.internal.compiler.OpCodes;
  28. import com.sun.org.apache.xpath.internal.objects.XNumber;
  29. import com.sun.org.apache.xpath.internal.patterns.ContextMatchStepPattern;
  30. import com.sun.org.apache.xpath.internal.patterns.FunctionPattern;
  31. import com.sun.org.apache.xpath.internal.patterns.NodeTest;
  32. import com.sun.org.apache.xpath.internal.patterns.StepPattern;
  33. import com.sun.org.apache.xpath.internal.res.XPATHErrorResources;
  34. /**
  35. * This class is both a factory for XPath location path expressions,
  36. * which are built from the opcode map output, and an analysis engine
  37. * for the location path expressions in order to provide optimization hints.
  38. */
  39. public class WalkerFactory
  40. {
  41. /**
  42. * This method is for building an array of possible levels
  43. * where the target element(s) could be found for a match.
  44. * @param xpath The xpath that is executing.
  45. * @param context The current source tree context node.
  46. *
  47. * @param lpi The owning location path iterator.
  48. * @param compiler non-null reference to compiler object that has processed
  49. * the XPath operations into an opcode map.
  50. * @param stepOpCodePos The opcode position for the step.
  51. *
  52. * @return non-null AxesWalker derivative.
  53. *
  54. * @throws javax.xml.transform.TransformerException
  55. * @xsl.usage advanced
  56. */
  57. static AxesWalker loadOneWalker(
  58. WalkingIterator lpi, Compiler compiler, int stepOpCodePos)
  59. throws javax.xml.transform.TransformerException
  60. {
  61. AxesWalker firstWalker = null;
  62. int stepType = compiler.getOp(stepOpCodePos);
  63. if (stepType != OpCodes.ENDOP)
  64. {
  65. // m_axesWalkers = new AxesWalker[1];
  66. // As we unwind from the recursion, create the iterators.
  67. firstWalker = createDefaultWalker(compiler, stepType, lpi, 0);
  68. firstWalker.init(compiler, stepOpCodePos, stepType);
  69. }
  70. return firstWalker;
  71. }
  72. /**
  73. * This method is for building an array of possible levels
  74. * where the target element(s) could be found for a match.
  75. * @param xpath The xpath that is executing.
  76. * @param context The current source tree context node.
  77. *
  78. * @param lpi The owning location path iterator object.
  79. * @param compiler non-null reference to compiler object that has processed
  80. * the XPath operations into an opcode map.
  81. * @param stepOpCodePos The opcode position for the step.
  82. * @param stepIndex The top-level step index withing the iterator.
  83. *
  84. * @return non-null AxesWalker derivative.
  85. *
  86. * @throws javax.xml.transform.TransformerException
  87. * @xsl.usage advanced
  88. */
  89. static AxesWalker loadWalkers(
  90. WalkingIterator lpi, Compiler compiler, int stepOpCodePos, int stepIndex)
  91. throws javax.xml.transform.TransformerException
  92. {
  93. int stepType;
  94. AxesWalker firstWalker = null;
  95. AxesWalker walker, prevWalker = null;
  96. int analysis = analyze(compiler, stepOpCodePos, stepIndex);
  97. while (OpCodes.ENDOP != (stepType = compiler.getOp(stepOpCodePos)))
  98. {
  99. walker = createDefaultWalker(compiler, stepOpCodePos, lpi, analysis);
  100. walker.init(compiler, stepOpCodePos, stepType);
  101. walker.exprSetParent(lpi);
  102. // walker.setAnalysis(analysis);
  103. if (null == firstWalker)
  104. {
  105. firstWalker = walker;
  106. }
  107. else
  108. {
  109. prevWalker.setNextWalker(walker);
  110. walker.setPrevWalker(prevWalker);
  111. }
  112. prevWalker = walker;
  113. stepOpCodePos = compiler.getNextStepPos(stepOpCodePos);
  114. if (stepOpCodePos < 0)
  115. break;
  116. }
  117. return firstWalker;
  118. }
  119. public static boolean isSet(int analysis, int bits)
  120. {
  121. return (0 != (analysis & bits));
  122. }
  123. public static void diagnoseIterator(String name, int analysis, Compiler compiler)
  124. {
  125. System.out.println(compiler.toString()+", "+name+", "
  126. + Integer.toBinaryString(analysis) + ", "
  127. + getAnalysisString(analysis));
  128. }
  129. /**
  130. * Create a new LocPathIterator iterator. The exact type of iterator
  131. * returned is based on an analysis of the XPath operations.
  132. *
  133. * @param compiler non-null reference to compiler object that has processed
  134. * the XPath operations into an opcode map.
  135. * @param opPos The position of the operation code for this itterator.
  136. *
  137. * @return non-null reference to a LocPathIterator or derivative.
  138. *
  139. * @throws javax.xml.transform.TransformerException
  140. */
  141. public static DTMIterator newDTMIterator(
  142. Compiler compiler, int opPos,
  143. boolean isTopLevel)
  144. throws javax.xml.transform.TransformerException
  145. {
  146. int firstStepPos = compiler.getFirstChildPos(opPos);
  147. int analysis = analyze(compiler, firstStepPos, 0);
  148. boolean isOneStep = isOneStep(analysis);
  149. DTMIterator iter;
  150. // Is the iteration a one-step attribute pattern (i.e. select="@foo")?
  151. if (isOneStep && walksSelfOnly(analysis) &&
  152. isWild(analysis) && !hasPredicate(analysis))
  153. {
  154. if (DEBUG_ITERATOR_CREATION)
  155. diagnoseIterator("SelfIteratorNoPredicate", analysis, compiler);
  156. // Then use a simple iteration of the attributes, with node test
  157. // and predicate testing.
  158. iter = new SelfIteratorNoPredicate(compiler, opPos, analysis);
  159. }
  160. // Is the iteration exactly one child step?
  161. else if (walksChildrenOnly(analysis) && isOneStep)
  162. {
  163. // Does the pattern specify *any* child with no predicate? (i.e. select="child::node()".
  164. if (isWild(analysis) && !hasPredicate(analysis))
  165. {
  166. if (DEBUG_ITERATOR_CREATION)
  167. diagnoseIterator("ChildIterator", analysis, compiler);
  168. // Use simple child iteration without any test.
  169. iter = new ChildIterator(compiler, opPos, analysis);
  170. }
  171. else
  172. {
  173. if (DEBUG_ITERATOR_CREATION)
  174. diagnoseIterator("ChildTestIterator", analysis, compiler);
  175. // Else use simple node test iteration with predicate test.
  176. iter = new ChildTestIterator(compiler, opPos, analysis);
  177. }
  178. }
  179. // Is the iteration a one-step attribute pattern (i.e. select="@foo")?
  180. else if (isOneStep && walksAttributes(analysis))
  181. {
  182. if (DEBUG_ITERATOR_CREATION)
  183. diagnoseIterator("AttributeIterator", analysis, compiler);
  184. // Then use a simple iteration of the attributes, with node test
  185. // and predicate testing.
  186. iter = new AttributeIterator(compiler, opPos, analysis);
  187. }
  188. else if(isOneStep && !walksFilteredList(analysis))
  189. {
  190. if( !walksNamespaces(analysis)
  191. && (walksInDocOrder(analysis) || isSet(analysis, BIT_PARENT)))
  192. {
  193. if (false || DEBUG_ITERATOR_CREATION)
  194. diagnoseIterator("OneStepIteratorForward", analysis, compiler);
  195. // Then use a simple iteration of the attributes, with node test
  196. // and predicate testing.
  197. iter = new OneStepIteratorForward(compiler, opPos, analysis);
  198. }
  199. else
  200. {
  201. if (false || DEBUG_ITERATOR_CREATION)
  202. diagnoseIterator("OneStepIterator", analysis, compiler);
  203. // Then use a simple iteration of the attributes, with node test
  204. // and predicate testing.
  205. iter = new OneStepIterator(compiler, opPos, analysis);
  206. }
  207. }
  208. // Analysis of "//center":
  209. // bits: 1001000000001010000000000000011
  210. // count: 3
  211. // root
  212. // child:node()
  213. // BIT_DESCENDANT_OR_SELF
  214. // It's highly possible that we should have a seperate bit set for
  215. // "//foo" patterns.
  216. // For at least the time being, we can't optimize patterns like
  217. // "//table[3]", because this has to be analyzed as
  218. // "/descendant-or-self::node()/table[3]" in order for the indexes
  219. // to work right.
  220. else if (isOptimizableForDescendantIterator(compiler, firstStepPos, 0)
  221. // && getStepCount(analysis) <= 3
  222. // && walksDescendants(analysis)
  223. // && walksSubtreeOnlyFromRootOrContext(analysis)
  224. )
  225. {
  226. if (DEBUG_ITERATOR_CREATION)
  227. diagnoseIterator("DescendantIterator", analysis, compiler);
  228. iter = new DescendantIterator(compiler, opPos, analysis);
  229. }
  230. else
  231. {
  232. if(isNaturalDocOrder(compiler, firstStepPos, 0, analysis))
  233. {
  234. if (false || DEBUG_ITERATOR_CREATION)
  235. {
  236. diagnoseIterator("WalkingIterator", analysis, compiler);
  237. }
  238. iter = new WalkingIterator(compiler, opPos, analysis, true);
  239. }
  240. else
  241. {
  242. // if (DEBUG_ITERATOR_CREATION)
  243. // diagnoseIterator("MatchPatternIterator", analysis, compiler);
  244. //
  245. // return new MatchPatternIterator(compiler, opPos, analysis);
  246. if (DEBUG_ITERATOR_CREATION)
  247. diagnoseIterator("WalkingIteratorSorted", analysis, compiler);
  248. iter = new WalkingIteratorSorted(compiler, opPos, analysis, true);
  249. }
  250. }
  251. if(iter instanceof LocPathIterator)
  252. ((LocPathIterator)iter).setIsTopLevel(isTopLevel);
  253. return iter;
  254. }
  255. /**
  256. * Special purpose function to see if we can optimize the pattern for
  257. * a DescendantIterator.
  258. *
  259. * @param compiler non-null reference to compiler object that has processed
  260. * the XPath operations into an opcode map.
  261. * @param stepOpCodePos The opcode position for the step.
  262. * @param stepIndex The top-level step index withing the iterator.
  263. *
  264. * @return 32 bits as an integer that give information about the location
  265. * path as a whole.
  266. *
  267. * @throws javax.xml.transform.TransformerException
  268. */
  269. public static int getAxisFromStep(
  270. Compiler compiler, int stepOpCodePos)
  271. throws javax.xml.transform.TransformerException
  272. {
  273. int stepType = compiler.getOp(stepOpCodePos);
  274. switch (stepType)
  275. {
  276. case OpCodes.FROM_FOLLOWING :
  277. return Axis.FOLLOWING;
  278. case OpCodes.FROM_FOLLOWING_SIBLINGS :
  279. return Axis.FOLLOWINGSIBLING;
  280. case OpCodes.FROM_PRECEDING :
  281. return Axis.PRECEDING;
  282. case OpCodes.FROM_PRECEDING_SIBLINGS :
  283. return Axis.PRECEDINGSIBLING;
  284. case OpCodes.FROM_PARENT :
  285. return Axis.PARENT;
  286. case OpCodes.FROM_NAMESPACE :
  287. return Axis.NAMESPACE;
  288. case OpCodes.FROM_ANCESTORS :
  289. return Axis.ANCESTOR;
  290. case OpCodes.FROM_ANCESTORS_OR_SELF :
  291. return Axis.ANCESTORORSELF;
  292. case OpCodes.FROM_ATTRIBUTES :
  293. return Axis.ATTRIBUTE;
  294. case OpCodes.FROM_ROOT :
  295. return Axis.ROOT;
  296. case OpCodes.FROM_CHILDREN :
  297. return Axis.CHILD;
  298. case OpCodes.FROM_DESCENDANTS_OR_SELF :
  299. return Axis.DESCENDANTORSELF;
  300. case OpCodes.FROM_DESCENDANTS :
  301. return Axis.DESCENDANT;
  302. case OpCodes.FROM_SELF :
  303. return Axis.SELF;
  304. case OpCodes.OP_EXTFUNCTION :
  305. case OpCodes.OP_FUNCTION :
  306. case OpCodes.OP_GROUP :
  307. case OpCodes.OP_VARIABLE :
  308. return Axis.FILTEREDLIST;
  309. }
  310. throw new RuntimeException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NULL_ERROR_HANDLER, new Object[]{Integer.toString(stepType)})); //"Programmer's assertion: unknown opcode: "
  311. //+ stepType);
  312. }
  313. /**
  314. * Get a corresponding BIT_XXX from an axis.
  315. * @param axis One of Axis.ANCESTOR, etc.
  316. * @return One of BIT_ANCESTOR, etc.
  317. */
  318. static public int getAnalysisBitFromAxes(int axis)
  319. {
  320. switch (axis) // Generate new traverser
  321. {
  322. case Axis.ANCESTOR :
  323. return BIT_ANCESTOR;
  324. case Axis.ANCESTORORSELF :
  325. return BIT_ANCESTOR_OR_SELF;
  326. case Axis.ATTRIBUTE :
  327. return BIT_ATTRIBUTE;
  328. case Axis.CHILD :
  329. return BIT_CHILD;
  330. case Axis.DESCENDANT :
  331. return BIT_DESCENDANT;
  332. case Axis.DESCENDANTORSELF :
  333. return BIT_DESCENDANT_OR_SELF;
  334. case Axis.FOLLOWING :
  335. return BIT_FOLLOWING;
  336. case Axis.FOLLOWINGSIBLING :
  337. return BIT_FOLLOWING_SIBLING;
  338. case Axis.NAMESPACE :
  339. case Axis.NAMESPACEDECLS :
  340. return BIT_NAMESPACE;
  341. case Axis.PARENT :
  342. return BIT_PARENT;
  343. case Axis.PRECEDING :
  344. return BIT_PRECEDING;
  345. case Axis.PRECEDINGSIBLING :
  346. return BIT_PRECEDING_SIBLING;
  347. case Axis.SELF :
  348. return BIT_SELF;
  349. case Axis.ALLFROMNODE :
  350. return BIT_DESCENDANT_OR_SELF;
  351. // case Axis.PRECEDINGANDANCESTOR :
  352. case Axis.DESCENDANTSFROMROOT :
  353. case Axis.ALL :
  354. case Axis.DESCENDANTSORSELFFROMROOT :
  355. return BIT_ANY_DESCENDANT_FROM_ROOT;
  356. case Axis.ROOT :
  357. return BIT_ROOT;
  358. case Axis.FILTEREDLIST :
  359. return BIT_FILTER;
  360. default :
  361. return BIT_FILTER;
  362. }
  363. }
  364. static boolean functionProximateOrContainsProximate(Compiler compiler,
  365. int opPos)
  366. {
  367. int endFunc = opPos + compiler.getOp(opPos + 1) - 1;
  368. opPos = compiler.getFirstChildPos(opPos);
  369. int funcID = compiler.getOp(opPos);
  370. // System.out.println("funcID: "+funcID);
  371. // System.out.println("opPos: "+opPos);
  372. // System.out.println("endFunc: "+endFunc);
  373. switch(funcID)
  374. {
  375. case FunctionTable.FUNC_LAST:
  376. case FunctionTable.FUNC_POSITION:
  377. return true;
  378. default:
  379. opPos++;
  380. int i = 0;
  381. for (int p = opPos; p < endFunc; p = compiler.getNextOpPos(p), i++)
  382. {
  383. int innerExprOpPos = p+2;
  384. int argOp = compiler.getOp(innerExprOpPos);
  385. boolean prox = isProximateInnerExpr(compiler, innerExprOpPos);
  386. if(prox)
  387. return true;
  388. }
  389. }
  390. return false;
  391. }
  392. static boolean isProximateInnerExpr(Compiler compiler, int opPos)
  393. {
  394. int op = compiler.getOp(opPos);
  395. int innerExprOpPos = opPos+2;
  396. switch(op)
  397. {
  398. case OpCodes.OP_ARGUMENT:
  399. if(isProximateInnerExpr(compiler, innerExprOpPos))
  400. return true;
  401. break;
  402. case OpCodes.OP_VARIABLE:
  403. case OpCodes.OP_NUMBERLIT:
  404. case OpCodes.OP_LITERAL:
  405. case OpCodes.OP_LOCATIONPATH:
  406. break; // OK
  407. case OpCodes.OP_FUNCTION:
  408. boolean isProx = functionProximateOrContainsProximate(compiler, opPos);
  409. if(isProx)
  410. return true;
  411. break;
  412. case OpCodes.OP_GT:
  413. case OpCodes.OP_GTE:
  414. case OpCodes.OP_LT:
  415. case OpCodes.OP_LTE:
  416. case OpCodes.OP_EQUALS:
  417. int leftPos = compiler.getFirstChildPos(op);
  418. int rightPos = compiler.getNextOpPos(leftPos);
  419. isProx = isProximateInnerExpr(compiler, leftPos);
  420. if(isProx)
  421. return true;
  422. isProx = isProximateInnerExpr(compiler, rightPos);
  423. if(isProx)
  424. return true;
  425. break;
  426. default:
  427. return true; // be conservative...
  428. }
  429. return false;
  430. }
  431. /**
  432. * Tell if the predicates need to have proximity knowledge.
  433. */
  434. public static boolean mightBeProximate(Compiler compiler, int opPos, int stepType)
  435. throws javax.xml.transform.TransformerException
  436. {
  437. boolean mightBeProximate = false;
  438. int argLen;
  439. switch (stepType)
  440. {
  441. case OpCodes.OP_VARIABLE :
  442. case OpCodes.OP_EXTFUNCTION :
  443. case OpCodes.OP_FUNCTION :
  444. case OpCodes.OP_GROUP :
  445. argLen = compiler.getArgLength(opPos);
  446. break;
  447. default :
  448. argLen = compiler.getArgLengthOfStep(opPos);
  449. }
  450. int predPos = compiler.getFirstPredicateOpPos(opPos);
  451. int count = 0;
  452. while (OpCodes.OP_PREDICATE == compiler.getOp(predPos))
  453. {
  454. count++;
  455. int innerExprOpPos = predPos+2;
  456. int predOp = compiler.getOp(innerExprOpPos);
  457. switch(predOp)
  458. {
  459. case OpCodes.OP_VARIABLE:
  460. return true; // Would need more smarts to tell if this could be a number or not!
  461. case OpCodes.OP_LOCATIONPATH:
  462. // OK.
  463. break;
  464. case OpCodes.OP_NUMBER:
  465. case OpCodes.OP_NUMBERLIT:
  466. return true; // that's all she wrote!
  467. case OpCodes.OP_FUNCTION:
  468. boolean isProx
  469. = functionProximateOrContainsProximate(compiler, innerExprOpPos);
  470. if(isProx)
  471. return true;
  472. break;
  473. case OpCodes.OP_GT:
  474. case OpCodes.OP_GTE:
  475. case OpCodes.OP_LT:
  476. case OpCodes.OP_LTE:
  477. case OpCodes.OP_EQUALS:
  478. int leftPos = compiler.getFirstChildPos(innerExprOpPos);
  479. int rightPos = compiler.getNextOpPos(leftPos);
  480. isProx = isProximateInnerExpr(compiler, leftPos);
  481. if(isProx)
  482. return true;
  483. isProx = isProximateInnerExpr(compiler, rightPos);
  484. if(isProx)
  485. return true;
  486. break;
  487. default:
  488. return true; // be conservative...
  489. }
  490. predPos = compiler.getNextOpPos(predPos);
  491. }
  492. return mightBeProximate;
  493. }
  494. /**
  495. * Special purpose function to see if we can optimize the pattern for
  496. * a DescendantIterator.
  497. *
  498. * @param compiler non-null reference to compiler object that has processed
  499. * the XPath operations into an opcode map.
  500. * @param stepOpCodePos The opcode position for the step.
  501. * @param stepIndex The top-level step index withing the iterator.
  502. *
  503. * @return 32 bits as an integer that give information about the location
  504. * path as a whole.
  505. *
  506. * @throws javax.xml.transform.TransformerException
  507. */
  508. private static boolean isOptimizableForDescendantIterator(
  509. Compiler compiler, int stepOpCodePos, int stepIndex)
  510. throws javax.xml.transform.TransformerException
  511. {
  512. int stepType;
  513. int stepCount = 0;
  514. boolean foundDorDS = false;
  515. boolean foundSelf = false;
  516. boolean foundDS = false;
  517. int nodeTestType = OpCodes.NODETYPE_NODE;
  518. while (OpCodes.ENDOP != (stepType = compiler.getOp(stepOpCodePos)))
  519. {
  520. // The DescendantIterator can only do one node test. If there's more
  521. // than one, use another iterator.
  522. if(nodeTestType != OpCodes.NODETYPE_NODE && nodeTestType != OpCodes.NODETYPE_ROOT)
  523. return false;
  524. stepCount++;
  525. if(stepCount > 3)
  526. return false;
  527. boolean mightBeProximate = mightBeProximate(compiler, stepOpCodePos, stepType);
  528. if(mightBeProximate)
  529. return false;
  530. switch (stepType)
  531. {
  532. case OpCodes.FROM_FOLLOWING :
  533. case OpCodes.FROM_FOLLOWING_SIBLINGS :
  534. case OpCodes.FROM_PRECEDING :
  535. case OpCodes.FROM_PRECEDING_SIBLINGS :
  536. case OpCodes.FROM_PARENT :
  537. case OpCodes.OP_VARIABLE :
  538. case OpCodes.OP_EXTFUNCTION :
  539. case OpCodes.OP_FUNCTION :
  540. case OpCodes.OP_GROUP :
  541. case OpCodes.FROM_NAMESPACE :
  542. case OpCodes.FROM_ANCESTORS :
  543. case OpCodes.FROM_ANCESTORS_OR_SELF :
  544. case OpCodes.FROM_ATTRIBUTES :
  545. case OpCodes.MATCH_ATTRIBUTE :
  546. case OpCodes.MATCH_ANY_ANCESTOR :
  547. case OpCodes.MATCH_IMMEDIATE_ANCESTOR :
  548. return false;
  549. case OpCodes.FROM_ROOT :
  550. if(1 != stepCount)
  551. return false;
  552. break;
  553. case OpCodes.FROM_CHILDREN :
  554. if(!foundDS && !(foundDorDS && foundSelf))
  555. return false;
  556. break;
  557. case OpCodes.FROM_DESCENDANTS_OR_SELF :
  558. foundDS = true;
  559. case OpCodes.FROM_DESCENDANTS :
  560. if(3 == stepCount)
  561. return false;
  562. foundDorDS = true;
  563. break;
  564. case OpCodes.FROM_SELF :
  565. if(1 != stepCount)
  566. return false;
  567. foundSelf = true;
  568. break;
  569. default :
  570. throw new RuntimeException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NULL_ERROR_HANDLER, new Object[]{Integer.toString(stepType)})); //"Programmer's assertion: unknown opcode: "
  571. // + stepType);
  572. }
  573. nodeTestType = compiler.getStepTestType(stepOpCodePos);
  574. int nextStepOpCodePos = compiler.getNextStepPos(stepOpCodePos);
  575. if (nextStepOpCodePos < 0)
  576. break;
  577. if(OpCodes.ENDOP != compiler.getOp(nextStepOpCodePos))
  578. {
  579. if(compiler.countPredicates(stepOpCodePos) > 0)
  580. {
  581. return false;
  582. }
  583. }
  584. stepOpCodePos = nextStepOpCodePos;
  585. }
  586. return true;
  587. }
  588. /**
  589. * Analyze the location path and return 32 bits that give information about
  590. * the location path as a whole. See the BIT_XXX constants for meaning about
  591. * each of the bits.
  592. *
  593. * @param compiler non-null reference to compiler object that has processed
  594. * the XPath operations into an opcode map.
  595. * @param stepOpCodePos The opcode position for the step.
  596. * @param stepIndex The top-level step index withing the iterator.
  597. *
  598. * @return 32 bits as an integer that give information about the location
  599. * path as a whole.
  600. *
  601. * @throws javax.xml.transform.TransformerException
  602. */
  603. private static int analyze(
  604. Compiler compiler, int stepOpCodePos, int stepIndex)
  605. throws javax.xml.transform.TransformerException
  606. {
  607. int stepType;
  608. int stepCount = 0;
  609. int analysisResult = 0x00000000; // 32 bits of analysis
  610. while (OpCodes.ENDOP != (stepType = compiler.getOp(stepOpCodePos)))
  611. {
  612. stepCount++;
  613. // String namespace = compiler.getStepNS(stepOpCodePos);
  614. // boolean isNSWild = (null != namespace)
  615. // ? namespace.equals(NodeTest.WILD) : false;
  616. // String localname = compiler.getStepLocalName(stepOpCodePos);
  617. // boolean isWild = (null != localname) ? localname.equals(NodeTest.WILD) : false;
  618. boolean predAnalysis = analyzePredicate(compiler, stepOpCodePos,
  619. stepType);
  620. if (predAnalysis)
  621. analysisResult |= BIT_PREDICATE;
  622. switch (stepType)
  623. {
  624. case OpCodes.OP_VARIABLE :
  625. case OpCodes.OP_EXTFUNCTION :
  626. case OpCodes.OP_FUNCTION :
  627. case OpCodes.OP_GROUP :
  628. analysisResult |= BIT_FILTER;
  629. break;
  630. case OpCodes.FROM_ROOT :
  631. analysisResult |= BIT_ROOT;
  632. break;
  633. case OpCodes.FROM_ANCESTORS :
  634. analysisResult |= BIT_ANCESTOR;
  635. break;
  636. case OpCodes.FROM_ANCESTORS_OR_SELF :
  637. analysisResult |= BIT_ANCESTOR_OR_SELF;
  638. break;
  639. case OpCodes.FROM_ATTRIBUTES :
  640. analysisResult |= BIT_ATTRIBUTE;
  641. break;
  642. case OpCodes.FROM_NAMESPACE :
  643. analysisResult |= BIT_NAMESPACE;
  644. break;
  645. case OpCodes.FROM_CHILDREN :
  646. analysisResult |= BIT_CHILD;
  647. break;
  648. case OpCodes.FROM_DESCENDANTS :
  649. analysisResult |= BIT_DESCENDANT;
  650. break;
  651. case OpCodes.FROM_DESCENDANTS_OR_SELF :
  652. // Use a special bit to to make sure we get the right analysis of "//foo".
  653. if (2 == stepCount && BIT_ROOT == analysisResult)
  654. {
  655. analysisResult |= BIT_ANY_DESCENDANT_FROM_ROOT;
  656. }
  657. analysisResult |= BIT_DESCENDANT_OR_SELF;
  658. break;
  659. case OpCodes.FROM_FOLLOWING :
  660. analysisResult |= BIT_FOLLOWING;
  661. break;
  662. case OpCodes.FROM_FOLLOWING_SIBLINGS :
  663. analysisResult |= BIT_FOLLOWING_SIBLING;
  664. break;
  665. case OpCodes.FROM_PRECEDING :
  666. analysisResult |= BIT_PRECEDING;
  667. break;
  668. case OpCodes.FROM_PRECEDING_SIBLINGS :
  669. analysisResult |= BIT_PRECEDING_SIBLING;
  670. break;
  671. case OpCodes.FROM_PARENT :
  672. analysisResult |= BIT_PARENT;
  673. break;
  674. case OpCodes.FROM_SELF :
  675. analysisResult |= BIT_SELF;
  676. break;
  677. case OpCodes.MATCH_ATTRIBUTE :
  678. analysisResult |= (BIT_MATCH_PATTERN | BIT_ATTRIBUTE);
  679. break;
  680. case OpCodes.MATCH_ANY_ANCESTOR :
  681. analysisResult |= (BIT_MATCH_PATTERN | BIT_ANCESTOR);
  682. break;
  683. case OpCodes.MATCH_IMMEDIATE_ANCESTOR :
  684. analysisResult |= (BIT_MATCH_PATTERN | BIT_PARENT);
  685. break;
  686. default :
  687. throw new RuntimeException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NULL_ERROR_HANDLER, new Object[]{Integer.toString(stepType)})); //"Programmer's assertion: unknown opcode: "
  688. //+ stepType);
  689. }
  690. if (OpCodes.NODETYPE_NODE == compiler.getOp(stepOpCodePos + 3)) // child::node()
  691. {
  692. analysisResult |= BIT_NODETEST_ANY;
  693. }
  694. stepOpCodePos = compiler.getNextStepPos(stepOpCodePos);
  695. if (stepOpCodePos < 0)
  696. break;
  697. }
  698. analysisResult |= (stepCount & BITS_COUNT);
  699. return analysisResult;
  700. }
  701. /**
  702. * Tell if the given axis goes downword. Bogus name, if you can think of
  703. * a better one, please do tell. This really has to do with inverting
  704. * attribute axis.
  705. * @param axis One of Axis.XXX.
  706. * @return true if the axis is not a child axis and does not go up from
  707. * the axis root.
  708. */
  709. public static boolean isDownwardAxisOfMany(int axis)
  710. {
  711. return ((Axis.DESCENDANTORSELF == axis) ||
  712. (Axis.DESCENDANT == axis)
  713. || (Axis.FOLLOWING == axis)
  714. // || (Axis.FOLLOWINGSIBLING == axis)
  715. || (Axis.PRECEDING == axis)
  716. // || (Axis.PRECEDINGSIBLING == axis)
  717. );
  718. }
  719. /**
  720. * Read a <a href="http://www.w3.org/TR/xpath#location-paths">LocationPath</a>
  721. * as a generalized match pattern. What this means is that the LocationPath
  722. * is read backwards, as a test on a given node, to see if it matches the
  723. * criteria of the selection, and ends up at the context node. Essentially,
  724. * this is a backwards query from a given node, to find the context node.
  725. * <p>So, the selection "foo/daz[2]" is, in non-abreviated expanded syntax,
  726. * "self::node()/following-sibling::foo/child::daz[position()=2]".
  727. * Taking this as a match pattern for a probable node, it works out to
  728. * "self::daz/parent::foo[child::daz[position()=2 and isPrevStepNode()]
  729. * precedingSibling::node()[isContextNodeOfLocationPath()]", adding magic
  730. * isPrevStepNode and isContextNodeOfLocationPath operations. Predicates in
  731. * the location path have to be executed by the following step,
  732. * because they have to know the context of their execution.
  733. *
  734. * @param mpi The MatchPatternIterator to which the steps will be attached.
  735. * @param compiler The compiler that holds the syntax tree/op map to
  736. * construct from.
  737. * @param stepOpCodePos The current op code position within the opmap.
  738. * @param stepIndex The top-level step index withing the iterator.
  739. *
  740. * @return A StepPattern object, which may contain relative StepPatterns.
  741. *
  742. * @throws javax.xml.transform.TransformerException
  743. */
  744. static StepPattern loadSteps(
  745. MatchPatternIterator mpi, Compiler compiler, int stepOpCodePos,
  746. int stepIndex)
  747. throws javax.xml.transform.TransformerException
  748. {
  749. if (DEBUG_PATTERN_CREATION)
  750. {
  751. System.out.println("================");
  752. System.out.println("loadSteps for: "+compiler.getPatternString());
  753. }
  754. int stepType;
  755. StepPattern step = null;
  756. StepPattern firstStep = null, prevStep = null;
  757. int analysis = analyze(compiler, stepOpCodePos, stepIndex);
  758. while (OpCodes.ENDOP != (stepType = compiler.getOp(stepOpCodePos)))
  759. {
  760. step = createDefaultStepPattern(compiler, stepOpCodePos, mpi, analysis,
  761. firstStep, prevStep);
  762. if (null == firstStep)
  763. {
  764. firstStep = step;
  765. }
  766. else
  767. {
  768. //prevStep.setNextWalker(step);
  769. step.setRelativePathPattern(prevStep);
  770. }
  771. prevStep = step;
  772. stepOpCodePos = compiler.getNextStepPos(stepOpCodePos);
  773. if (stepOpCodePos < 0)
  774. break;
  775. }
  776. int axis = Axis.SELF;
  777. int paxis = Axis.SELF;
  778. StepPattern tail = step;
  779. for (StepPattern pat = step; null != pat;
  780. pat = pat.getRelativePathPattern())
  781. {
  782. int nextAxis = pat.getAxis();
  783. //int nextPaxis = pat.getPredicateAxis();
  784. pat.setAxis(axis);
  785. // The predicate axis can't be moved!!! Test Axes103
  786. // pat.setPredicateAxis(paxis);
  787. // If we have an attribute or namespace axis that went up, then
  788. // it won't find the attribute in the inverse, since the select-to-match
  789. // axes are not invertable (an element is a parent of an attribute, but
  790. // and attribute is not a child of an element).
  791. // If we don't do the magic below, then "@*/ancestor-or-self::*" gets
  792. // inverted for match to "self::*/descendant-or-self::@*/parent::node()",
  793. // which obviously won't work.
  794. // So we will rewrite this as:
  795. // "self::*/descendant-or-self::*/attribute::*/parent::node()"
  796. // Child has to be rewritten a little differently:
  797. // select: "@*/parent::*"
  798. // inverted match: "self::*/child::@*/parent::node()"
  799. // rewrite: "self::*/attribute::*/parent::node()"
  800. // Axes that go down in the select, do not have to have special treatment
  801. // in the rewrite. The following inverted match will still not select
  802. // anything.
  803. // select: "@*/child::*"
  804. // inverted match: "self::*/parent::@*/parent::node()"
  805. // Lovely business, this.
  806. // -sb
  807. int whatToShow = pat.getWhatToShow();
  808. if(whatToShow == DTMFilter.SHOW_ATTRIBUTE ||
  809. whatToShow == DTMFilter.SHOW_NAMESPACE)
  810. {
  811. int newAxis = (whatToShow == DTMFilter.SHOW_ATTRIBUTE) ?
  812. Axis.ATTRIBUTE : Axis.NAMESPACE;
  813. if(isDownwardAxisOfMany(axis))
  814. {
  815. StepPattern attrPat = new StepPattern(whatToShow,
  816. pat.getNamespace(),
  817. pat.getLocalName(),
  818. //newAxis, pat.getPredicateAxis);
  819. newAxis, 0); // don't care about the predicate axis
  820. XNumber score = pat.getStaticScore();
  821. pat.setNamespace(null);
  822. pat.setLocalName(NodeTest.WILD);
  823. attrPat.setPredicates(pat.getPredicates());
  824. pat.setPredicates(null);
  825. pat.setWhatToShow(DTMFilter.SHOW_ELEMENT);
  826. StepPattern rel = pat.getRelativePathPattern();
  827. pat.setRelativePathPattern(attrPat);
  828. attrPat.setRelativePathPattern(rel);
  829. attrPat.setStaticScore(score);
  830. // This is needed to inverse a following pattern, because of the
  831. // wacky Xalan rules for following from an attribute. See axes108.
  832. // By these rules, following from an attribute is not strictly
  833. // inverseable.
  834. if(Axis.PRECEDING == pat.getAxis())
  835. pat.setAxis(Axis.PRECEDINGANDANCESTOR);
  836. else if(Axis.DESCENDANT == pat.getAxis())
  837. pat.setAxis(Axis.DESCENDANTORSELF);
  838. pat = attrPat;
  839. }
  840. else if(Axis.CHILD == pat.getAxis())
  841. {
  842. // In this case just change the axis.
  843. // pat.setWhatToShow(whatToShow);
  844. pat.setAxis(Axis.ATTRIBUTE);
  845. }
  846. }
  847. axis = nextAxis;
  848. //paxis = nextPaxis;
  849. tail = pat;
  850. }
  851. if(axis < Axis.ALL)
  852. {
  853. StepPattern selfPattern = new ContextMatchStepPattern(axis, paxis);
  854. // We need to keep the new nodetest from affecting the score...
  855. XNumber score = tail.getStaticScore();
  856. tail.setRelativePathPattern(selfPattern);
  857. tail.setStaticScore(score);
  858. selfPattern.setStaticScore(score);
  859. }
  860. if (DEBUG_PATTERN_CREATION)
  861. {
  862. System.out.println("Done loading steps: "+step.toString());
  863. System.out.println("");
  864. }
  865. return step; // start from last pattern?? //firstStep;
  866. }
  867. /**
  868. * Create a StepPattern that is contained within a LocationPath.
  869. *
  870. *
  871. * @param compiler The compiler that holds the syntax tree/op map to
  872. * construct from.
  873. * @param stepOpCodePos The current op code position within the opmap.
  874. * @param mpi The MatchPatternIterator to which the steps will be attached.
  875. * @param analysis 32 bits of analysis, from which the type of AxesWalker
  876. * may be influenced.
  877. * @param tail The step that is the first step analyzed, but the last
  878. * step in the relative match linked list, i.e. the tail.
  879. * May be null.
  880. * @param head The step that is the current head of the relative
  881. * match step linked list.
  882. * May be null.
  883. *
  884. * @return the head of the list.
  885. *
  886. * @throws javax.xml.transform.TransformerException
  887. */
  888. private static StepPattern createDefaultStepPattern(
  889. Compiler compiler, int opPos, MatchPatternIterator mpi,
  890. int analysis, StepPattern tail, StepPattern head)
  891. throws javax.xml.transform.TransformerException
  892. {
  893. int stepType = compiler.getOp(opPos);
  894. boolean simpleInit = false;
  895. int totalNumberWalkers = (analysis & BITS_COUNT);
  896. boolean prevIsOneStepDown = true;
  897. int firstStepPos = compiler.getFirstChildPos(opPos);
  898. int whatToShow = compiler.getWhatToShow(opPos);
  899. StepPattern ai = null;
  900. int axis, predicateAxis;
  901. switch (stepType)
  902. {
  903. case OpCodes.OP_VARIABLE :
  904. case OpCodes.OP_EXTFUNCTION :
  905. case OpCodes.OP_FUNCTION :
  906. case OpCodes.OP_GROUP :
  907. prevIsOneStepDown = false;
  908. Expression expr;
  909. switch (stepType)
  910. {
  911. case OpCodes.OP_VARIABLE :
  912. case OpCodes.OP_EXTFUNCTION :
  913. case OpCodes.OP_FUNCTION :
  914. case OpCodes.OP_GROUP :
  915. expr = compiler.compile(opPos);
  916. break;
  917. default :
  918. expr = compiler.compile(opPos + 2);
  919. }
  920. axis = Axis.FILTEREDLIST;
  921. predicateAxis = Axis.FILTEREDLIST;
  922. ai = new FunctionPattern(expr, axis, predicateAxis);
  923. simpleInit = true;
  924. break;
  925. case OpCodes.FROM_ROOT :
  926. whatToShow = DTMFilter.SHOW_DOCUMENT
  927. | DTMFilter.SHOW_DOCUMENT_FRAGMENT;
  928. axis = Axis.ROOT;
  929. predicateAxis = Axis.ROOT;
  930. ai = new StepPattern(DTMFilter.SHOW_DOCUMENT |
  931. DTMFilter.SHOW_DOCUMENT_FRAGMENT,
  932. axis, predicateAxis);
  933. break;
  934. case OpCodes.FROM_ATTRIBUTES :
  935. whatToShow = DTMFilter.SHOW_ATTRIBUTE;
  936. axis = Axis.PARENT;
  937. predicateAxis = Axis.ATTRIBUTE;
  938. // ai = new StepPattern(whatToShow, Axis.SELF, Axis.SELF);
  939. break;
  940. case OpCodes.FROM_NAMESPACE :
  941. whatToShow = DTMFilter.SHOW_NAMESPACE;
  942. axis = Axis.PARENT;
  943. predicateAxis = Axis.NAMESPACE;
  944. // ai = new StepPattern(whatToShow, axis, predicateAxis);
  945. break;
  946. case OpCodes.FROM_ANCESTORS :
  947. axis = Axis.DESCENDANT;
  948. predicateAxis = Axis.ANCESTOR;
  949. break;
  950. case OpCodes.FROM_CHILDREN :
  951. axis = Axis.PARENT;
  952. predicateAxis = Axis.CHILD;
  953. break;
  954. case OpCodes.FROM_ANCESTORS_OR_SELF :
  955. axis = Axis.DESCENDANTORSELF;
  956. predicateAxis = Axis.ANCESTORORSELF;
  957. break;
  958. case OpCodes.FROM_SELF :
  959. axis = Axis.SELF;
  960. predicateAxis = Axis.SELF;
  961. break;
  962. case OpCodes.FROM_PARENT :
  963. axis = Axis.CHILD;
  964. predicateAxis = Axis.PARENT;
  965. break;
  966. case OpCodes.FROM_PRECEDING_SIBLINGS :
  967. axis = Axis.FOLLOWINGSIBLING;
  968. predicateAxis = Axis.PRECEDINGSIBLING;
  969. break;
  970. case OpCodes.FROM_PRECEDING :
  971. axis = Axis.FOLLOWING;
  972. predicateAxis = Axis.PRECEDING;
  973. break;
  974. case OpCodes.FROM_FOLLOWING_SIBLINGS :
  975. axis = Axis.PRECEDINGSIBLING;
  976. predicateAxis = Axis.FOLLOWINGSIBLING;
  977. break;
  978. case OpCodes.FROM_FOLLOWING :
  979. axis = Axis.PRECEDING;
  980. predicateAxis = Axis.FOLLOWING;
  981. break;
  982. case OpCodes.FROM_DESCENDANTS_OR_SELF :
  983. axis = Axis.ANCESTORORSELF;
  984. predicateAxis = Axis.DESCENDANTORSELF;
  985. break;
  986. case OpCodes.FROM_DESCENDANTS :
  987. axis = Axis.ANCESTOR;
  988. predicateAxis = Axis.DESCENDANT;
  989. break;
  990. default :
  991. throw new RuntimeException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NULL_ERROR_HANDLER, new Object[]{Integer.toString(stepType)})); //"Programmer's assertion: unknown opcode: "
  992. //+ stepType);
  993. }
  994. if(null == ai)
  995. {
  996. whatToShow = compiler.getWhatToShow(opPos); // %REVIEW%
  997. ai = new StepPattern(whatToShow, compiler.getStepNS(opPos),
  998. compiler.getStepLocalName(opPos),
  999. axis, predicateAxis);
  1000. }
  1001. if (false || DEBUG_PATTERN_CREATION)
  1002. {
  1003. System.out.print("new step: "+ ai);
  1004. System.out.print(", axis: " + Axis.names[ai.getAxis()]);
  1005. System.out.print(", predAxis: " + Axis.names[ai.getAxis()]);
  1006. System.out.print(", what: ");
  1007. System.out.print(" ");
  1008. ai.debugWhatToShow(ai.getWhatToShow());
  1009. }
  1010. int argLen = compiler.getFirstPredicateOpPos(opPos);
  1011. ai.setPredicates(compiler.getCompiledPredicates(argLen));
  1012. return ai;
  1013. }
  1014. /**
  1015. * Analyze a step and give information about it's predicates. Right now this
  1016. * just returns true or false if the step has a predicate.
  1017. *
  1018. * @param compiler non-null reference to compiler object that has processed
  1019. * the XPath operations into an opcode map.
  1020. * @param opPos The opcode position for the step.
  1021. * @param stepType The type of step, one of OP_GROUP, etc.
  1022. *
  1023. * @return true if step has a predicate.
  1024. *
  1025. * @throws javax.xml.transform.TransformerException
  1026. */
  1027. static boolean analyzePredicate(Compiler compiler, int opPos, int stepType)
  1028. throws javax.xml.transform.TransformerException
  1029. {
  1030. int argLen;
  1031. switch (stepType)
  1032. {
  1033. case OpCodes.OP_VARIABLE :
  1034. case OpCodes.OP_EXTFUNCTION :
  1035. case OpCodes.OP_FUNCTION :
  1036. case OpCodes.OP_GROUP :
  1037. argLen = compiler.getArgLength(opPos);
  1038. break;
  1039. default :
  1040. argLen = compiler.getArgLengthOfStep(opPos);
  1041. }
  1042. int pos = compiler.getFirstPredicateOpPos(opPos);
  1043. int nPredicates = compiler.countPredicates(pos);
  1044. return (nPredicates > 0) ? true : false;
  1045. }
  1046. /**
  1047. * Create the proper Walker from the axes type.
  1048. *
  1049. * @param compiler non-null reference to compiler object that has processed
  1050. * the XPath operations into an opcode map.
  1051. * @param opPos The opcode position for the step.
  1052. * @param lpi The owning location path iterator.
  1053. * @param analysis 32 bits of analysis, from which the type of AxesWalker
  1054. * may be influenced.
  1055. *
  1056. * @return non-null reference to AxesWalker derivative.
  1057. * @throws RuntimeException if the input is bad.
  1058. */
  1059. private static AxesWalker createDefaultWalker(Compiler compiler, int opPos,
  1060. WalkingIterator lpi, int analysis)
  1061. {
  1062. AxesWalker ai = null;
  1063. int stepType = compiler.getOp(opPos);
  1064. /*
  1065. System.out.println("0: "+compiler.getOp(opPos));
  1066. System.out.println("1: "+compiler.getOp(opPos+1));
  1067. System.out.println("2: "+compiler.getOp(opPos+2));
  1068. System.out.println("3: "+compiler.getOp(opPos+3));
  1069. System.out.println("4: "+compiler.getOp(opPos+4));
  1070. System.out.println("5: "+compiler.getOp(opPos+5));
  1071. */
  1072. boolean simpleInit = false;
  1073. int totalNumberWalkers = (analysis & BITS_COUNT);
  1074. boolean prevIsOneStepDown = true;
  1075. switch (stepType)
  1076. {
  1077. case OpCodes.OP_VARIABLE :
  1078. case OpCodes.OP_EXTFUNCTION :
  1079. case OpCodes.OP_FUNCTION :
  1080. case OpCodes.OP_GROUP :
  1081. prevIsOneStepDown = false;
  1082. if (DEBUG_WALKER_CREATION)
  1083. System.out.println("new walker: FilterExprWalker: " + analysis
  1084. + ", " + compiler.toString());
  1085. ai = new FilterExprWalker(lpi);
  1086. simpleInit = true;
  1087. break;
  1088. case OpCodes.FROM_ROOT :
  1089. ai = new AxesWalker(lpi, Axis.ROOT);
  1090. break;
  1091. case OpCodes.FROM_ANCESTORS :
  1092. prevIsOneStepDown = false;
  1093. ai = new ReverseAxesWalker(lpi, Axis.ANCESTOR);
  1094. break;
  1095. case OpCodes.FROM_ANCESTORS_OR_SELF :
  1096. prevIsOneStepDown = false;
  1097. ai = new ReverseAxesWalker(lpi, Axis.ANCESTORORSELF);
  1098. break;
  1099. case OpCodes.FROM_ATTRIBUTES :
  1100. ai = new AxesWalker(lpi, Axis.ATTRIBUTE);
  1101. break;
  1102. case OpCodes.FROM_NAMESPACE :
  1103. ai = new AxesWalker(lpi, Axis.NAMESPACE);
  1104. break;
  1105. case OpCodes.FROM_CHILDREN :
  1106. ai = new AxesWalker(lpi, Axis.CHILD);
  1107. break;
  1108. case OpCodes.FROM_DESCENDANTS :
  1109. prevIsOneStepDown = false;
  1110. ai = new AxesWalker(lpi, Axis.DESCENDANT);
  1111. break;
  1112. case OpCodes.FROM_DESCENDANTS_OR_SELF :
  1113. prevIsOneStepDown = false;
  1114. ai = new AxesWalker(lpi, Axis.DESCENDANTORSELF);
  1115. break;
  1116. case OpCodes.FROM_FOLLOWING :
  1117. prevIsOneStepDown = false;
  1118. ai = new AxesWalker(lpi, Axis.FOLLOWING);
  1119. break;
  1120. case OpCodes.FROM_FOLLOWING_SIBLINGS :
  1121. prevIsOneStepDown = false;
  1122. ai = new AxesWalker(lpi, Axis.FOLLOWINGSIBLING);
  1123. break;
  1124. case OpCodes.FROM_PRECEDING :
  1125. prevIsOneStepDown = false;
  1126. ai = new ReverseAxesWalker(lpi, Axis.PRECEDING);
  1127. break;
  1128. case OpCodes.FROM_PRECEDING_SIBLINGS :
  1129. prevIsOneStepDown = false;
  1130. ai = new ReverseAxesWalker(lpi, Axis.PRECEDINGSIBLING);
  1131. break;
  1132. case OpCodes.FROM_PARENT :
  1133. prevIsOneStepDown = false;
  1134. ai = new ReverseAxesWalker(lpi, Axis.PARENT);
  1135. break;
  1136. case OpCodes.FROM_SELF :
  1137. ai = new AxesWalker(lpi, Axis.SELF);
  1138. break;
  1139. default :
  1140. throw new RuntimeException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NULL_ERROR_HANDLER, new Object[]{Integer.toString(stepType)})); //"Programmer's assertion: unknown opcode: "
  1141. //+ stepType);
  1142. }
  1143. if (simpleInit)
  1144. {
  1145. ai.initNodeTest(DTMFilter.SHOW_ALL);
  1146. }
  1147. else
  1148. {
  1149. int whatToShow = compiler.getWhatToShow(opPos);
  1150. /*
  1151. System.out.print("construct: ");
  1152. NodeTest.debugWhatToShow(whatToShow);
  1153. System.out.println("or stuff: "+(whatToShow & (DTMFilter.SHOW_ATTRIBUTE
  1154. | DTMFilter.SHOW_ELEMENT
  1155. | DTMFilter.SHOW_PROCESSING_INSTRUCTION)));
  1156. */
  1157. if ((0 == (whatToShow
  1158. & (DTMFilter.SHOW_ATTRIBUTE | DTMFilter.SHOW_NAMESPACE | DTMFilter.SHOW_ELEMENT
  1159. | DTMFilter.SHOW_PROCESSING_INSTRUCTION))) || (whatToShow == DTMFilter.SHOW_ALL))
  1160. ai.initNodeTest(whatToShow);
  1161. else
  1162. {
  1163. ai.initNodeTest(whatToShow, compiler.getStepNS(opPos),
  1164. compiler.getStepLocalName(opPos));
  1165. }
  1166. }
  1167. return ai;
  1168. }
  1169. public static String getAnalysisString(int analysis)
  1170. {
  1171. StringBuffer buf = new StringBuffer();
  1172. buf.append("count: "+getStepCount(analysis)+" ");
  1173. if((analysis & BIT_NODETEST_ANY) != 0)
  1174. {
  1175. buf.append("NTANY|");
  1176. }
  1177. if((analysis & BIT_PREDICATE) != 0)
  1178. {
  1179. buf.append("PRED|");
  1180. }
  1181. if((analysis & BIT_ANCESTOR) != 0)
  1182. {
  1183. buf.append("ANC|");
  1184. }
  1185. if((analysis & BIT_ANCESTOR_OR_SELF) != 0)
  1186. {
  1187. buf.append("ANCOS|");
  1188. }
  1189. if((analysis & BIT_ATTRIBUTE) != 0)
  1190. {
  1191. buf.append("ATTR|");
  1192. }
  1193. if((analysis & BIT_CHILD) != 0)
  1194. {
  1195. buf.append("CH|");
  1196. }
  1197. if((analysis & BIT_DESCENDANT) != 0)
  1198. {
  1199. buf.append("DESC|");
  1200. }
  1201. if((analysis & BIT_DESCENDANT_OR_SELF) != 0)
  1202. {
  1203. buf.append("DESCOS|");
  1204. }
  1205. if((analysis & BIT_FOLLOWING) != 0)
  1206. {
  1207. buf.append("FOL|");
  1208. }
  1209. if((analysis & BIT_FOLLOWING_SIBLING) != 0)
  1210. {
  1211. buf.append("FOLS|");
  1212. }
  1213. if((analysis & BIT_NAMESPACE) != 0)
  1214. {
  1215. buf.append("NS|");
  1216. }
  1217. if((analysis & BIT_PARENT) != 0)
  1218. {
  1219. buf.append("P|");
  1220. }
  1221. if((analysis & BIT_PRECEDING) != 0)
  1222. {
  1223. buf.append("PREC|");
  1224. }
  1225. if((analysis & BIT_PRECEDING_SIBLING) != 0)
  1226. {
  1227. buf.append("PRECS|");
  1228. }
  1229. if((analysis & BIT_SELF) != 0)
  1230. {
  1231. buf.append(".|");
  1232. }
  1233. if((analysis & BIT_FILTER) != 0)
  1234. {
  1235. buf.append("FLT|");
  1236. }
  1237. if((analysis & BIT_ROOT) != 0)
  1238. {
  1239. buf.append("R|");
  1240. }
  1241. return buf.toString();
  1242. }
  1243. /** Set to true for diagnostics about walker creation */
  1244. static final boolean DEBUG_PATTERN_CREATION = false;
  1245. /** Set to true for diagnostics about walker creation */
  1246. static final boolean DEBUG_WALKER_CREATION = false;
  1247. /** Set to true for diagnostics about iterator creation */
  1248. static final boolean DEBUG_ITERATOR_CREATION = false;
  1249. public static boolean hasPredicate(int analysis)
  1250. {
  1251. return (0 != (analysis & BIT_PREDICATE));
  1252. }
  1253. public static boolean isWild(int analysis)
  1254. {
  1255. return (0 != (analysis & BIT_NODETEST_ANY));
  1256. }
  1257. public static boolean walksAncestors(int analysis)
  1258. {
  1259. return isSet(analysis, BIT_ANCESTOR | BIT_ANCESTOR_OR_SELF);
  1260. }
  1261. public static boolean walksAttributes(int analysis)
  1262. {
  1263. return (0 != (analysis & BIT_ATTRIBUTE));
  1264. }
  1265. public static boolean walksNamespaces(int analysis)
  1266. {
  1267. return (0 != (analysis & BIT_NAMESPACE));
  1268. }
  1269. public static boolean walksChildren(int analysis)
  1270. {
  1271. return (0 != (analysis & BIT_CHILD));
  1272. }
  1273. public static boolean walksDescendants(int analysis)
  1274. {
  1275. return isSet(analysis, BIT_DESCENDANT | BIT_DESCENDANT_OR_SELF);
  1276. }
  1277. public static boolean walksSubtree(int analysis)
  1278. {
  1279. return isSet(analysis, BIT_DESCENDANT | BIT_DESCENDANT_OR_SELF | BIT_CHILD);
  1280. }
  1281. public static boolean walksSubtreeOnlyMaybeAbsolute(int analysis)
  1282. {
  1283. return walksSubtree(analysis)
  1284. && !walksExtraNodes(analysis)
  1285. && !walksUp(analysis)
  1286. && !walksSideways(analysis)
  1287. ;
  1288. }
  1289. public static boolean walksSubtreeOnly(int analysis)
  1290. {
  1291. return walksSubtreeOnlyMaybeAbsolute(analysis)
  1292. && !isAbsolute(analysis)
  1293. ;
  1294. }
  1295. public static boolean walksFilteredList(int analysis)
  1296. {
  1297. return isSet(analysis, BIT_FILTER);
  1298. }
  1299. public static boolean walksSubtreeOnlyFromRootOrContext(int analysis)
  1300. {
  1301. return walksSubtree(analysis)
  1302. && !walksExtraNodes(analysis)
  1303. && !walksUp(analysis)
  1304. && !walksSideways(analysis)
  1305. && !isSet(analysis, BIT_FILTER)
  1306. ;
  1307. }
  1308. public static boolean walksInDocOrder(int analysis)
  1309. {
  1310. return (walksSubtreeOnlyMaybeAbsolute(analysis)
  1311. || walksExtraNodesOnly(analysis)
  1312. || walksFollowingOnlyMaybeAbsolute(analysis))
  1313. && !isSet(analysis, BIT_FILTER)
  1314. ;
  1315. }
  1316. public static boolean walksFollowingOnlyMaybeAbsolute(int analysis)
  1317. {
  1318. return isSet(analysis, BIT_SELF | BIT_FOLLOWING_SIBLING | BIT_FOLLOWING)
  1319. && !walksSubtree(analysis)
  1320. && !walksUp(analysis)
  1321. && !walksSideways(analysis)
  1322. ;
  1323. }
  1324. public static boolean walksUp(int analysis)
  1325. {
  1326. return isSet(analysis, BIT_PARENT | BIT_ANCESTOR | BIT_ANCESTOR_OR_SELF);
  1327. }
  1328. public static boolean walksSideways(int analysis)
  1329. {
  1330. return isSet(analysis, BIT_FOLLOWING | BIT_FOLLOWING_SIBLING |
  1331. BIT_PRECEDING | BIT_PRECEDING_SIBLING);
  1332. }
  1333. public static boolean walksExtraNodes(int analysis)
  1334. {
  1335. return isSet(analysis, BIT_NAMESPACE | BIT_ATTRIBUTE);
  1336. }
  1337. public static boolean walksExtraNodesOnly(int analysis)
  1338. {
  1339. return walksExtraNodes(analysis)
  1340. && !isSet(analysis, BIT_SELF)
  1341. && !walksSubtree(analysis)
  1342. && !walksUp(analysis)
  1343. && !walksSideways(analysis)
  1344. && !isAbsolute(analysis)
  1345. ;
  1346. }
  1347. public static boolean isAbsolute(int analysis)
  1348. {
  1349. return isSet(analysis, BIT_ROOT | BIT_FILTER);
  1350. }
  1351. public static boolean walksChildrenOnly(int analysis)
  1352. {
  1353. return walksChildren(analysis)
  1354. && !isSet(analysis, BIT_SELF)
  1355. && !walksExtraNodes(analysis)
  1356. && !walksDescendants(analysis)
  1357. && !walksUp(analysis)
  1358. && !walksSideways(analysis)
  1359. && (!isAbsolute(analysis) || isSet(analysis, BIT_ROOT))
  1360. ;
  1361. }
  1362. public static boolean walksChildrenAndExtraAndSelfOnly(int analysis)
  1363. {
  1364. return walksChildren(analysis)
  1365. && !walksDescendants(analysis)
  1366. && !walksUp(analysis)
  1367. && !walksSideways(analysis)
  1368. && (!isAbsolute(analysis) || isSet(analysis, BIT_ROOT))
  1369. ;
  1370. }
  1371. public static boolean walksDescendantsAndExtraAndSelfOnly(int analysis)
  1372. {
  1373. return !walksChildren(analysis)
  1374. && walksDescendants(analysis)
  1375. && !walksUp(analysis)
  1376. && !walksSideways(analysis)
  1377. && (!isAbsolute(analysis) || isSet(analysis, BIT_ROOT))
  1378. ;
  1379. }
  1380. public static boolean walksSelfOnly(int analysis)
  1381. {
  1382. return isSet(analysis, BIT_SELF)
  1383. && !walksSubtree(analysis)
  1384. && !walksUp(analysis)
  1385. && !walksSideways(analysis)
  1386. && !isAbsolute(analysis)
  1387. ;
  1388. }
  1389. public static boolean walksUpOnly(int analysis)
  1390. {
  1391. return !walksSubtree(analysis)
  1392. && walksUp(analysis)
  1393. && !walksSideways(analysis)
  1394. && !isAbsolute(analysis)
  1395. ;
  1396. }
  1397. public static boolean walksDownOnly(int analysis)
  1398. {
  1399. return walksSubtree(analysis)
  1400. && !walksUp(analysis)
  1401. && !walksSideways(analysis)
  1402. && !isAbsolute(analysis)
  1403. ;
  1404. }
  1405. public static boolean walksDownExtraOnly(int analysis)
  1406. {
  1407. return walksSubtree(analysis) && walksExtraNodes(analysis)
  1408. && !walksUp(analysis)
  1409. && !walksSideways(analysis)
  1410. && !isAbsolute(analysis)
  1411. ;
  1412. }
  1413. public static boolean canSkipSubtrees(int analysis)
  1414. {
  1415. return isSet(analysis, BIT_CHILD) | walksSideways(analysis);
  1416. }
  1417. public static boolean canCrissCross(int analysis)
  1418. {
  1419. // This could be done faster. Coded for clarity.
  1420. if(walksSelfOnly(analysis))
  1421. return false;
  1422. else if(walksDownOnly(analysis) && !canSkipSubtrees(analysis))
  1423. return false;
  1424. else if(walksChildrenAndExtraAndSelfOnly(analysis))
  1425. return false;
  1426. else if(walksDescendantsAndExtraAndSelfOnly(analysis))
  1427. return false;
  1428. else if(walksUpOnly(analysis))
  1429. return false;
  1430. else if(walksExtraNodesOnly(analysis))
  1431. return false;
  1432. else if(walksSubtree(analysis)
  1433. && (walksSideways(analysis)
  1434. || walksUp(analysis)
  1435. || canSkipSubtrees(analysis)))
  1436. return true;
  1437. else
  1438. return false;
  1439. }
  1440. /**
  1441. * Tell if the pattern can be 'walked' with the iteration steps in natural
  1442. * document order, without duplicates.
  1443. *
  1444. * @param analysis The general analysis of the pattern.
  1445. *
  1446. * @return true if the walk can be done in natural order.
  1447. *
  1448. * @throws javax.xml.transform.TransformerException
  1449. */
  1450. static public boolean isNaturalDocOrder(int analysis)
  1451. {
  1452. if(canCrissCross(analysis) || isSet(analysis, BIT_NAMESPACE) ||
  1453. walksFilteredList(analysis))
  1454. return false;
  1455. if(walksInDocOrder(analysis))
  1456. return true;
  1457. return false;
  1458. }
  1459. /**
  1460. * Tell if the pattern can be 'walked' with the iteration steps in natural
  1461. * document order, without duplicates.
  1462. *
  1463. * @param compiler non-null reference to compiler object that has processed
  1464. * the XPath operations into an opcode map.
  1465. * @param stepOpCodePos The opcode position for the step.
  1466. * @param stepIndex The top-level step index withing the iterator.
  1467. * @param analysis The general analysis of the pattern.
  1468. *
  1469. * @return true if the walk can be done in natural order.
  1470. *
  1471. * @throws javax.xml.transform.TransformerException
  1472. */
  1473. private static boolean isNaturalDocOrder(
  1474. Compiler compiler, int stepOpCodePos, int stepIndex, int analysis)
  1475. throws javax.xml.transform.TransformerException
  1476. {
  1477. if(canCrissCross(analysis))
  1478. return false;
  1479. // Namespaces can present some problems, so just punt if we're looking for
  1480. // these.
  1481. if(isSet(analysis, BIT_NAMESPACE))
  1482. return false;
  1483. // The following, preceding, following-sibling, and preceding sibling can
  1484. // be found in doc order if we get to this point, but if they occur
  1485. // together, they produce
  1486. // duplicates, so it's better for us to eliminate this case so we don't
  1487. // have to check for duplicates during runtime if we're using a
  1488. // WalkingIterator.
  1489. if(isSet(analysis, BIT_FOLLOWING | BIT_FOLLOWING_SIBLING) &&
  1490. isSet(analysis, BIT_PRECEDING | BIT_PRECEDING_SIBLING))
  1491. return false;
  1492. // OK, now we have to check for select="@*/axis::*" patterns, which
  1493. // can also cause duplicates to happen. But select="axis*/@::*" patterns
  1494. // are OK, as are select="@foo/axis::*" patterns.
  1495. // Unfortunately, we can't do this just via the analysis bits.
  1496. int stepType;
  1497. int stepCount = 0;
  1498. boolean foundWildAttribute = false;
  1499. // Steps that can traverse anything other than down a
  1500. // subtree or that can produce duplicates when used in
  1501. // combonation are counted with this variable.
  1502. int potentialDuplicateMakingStepCount = 0;
  1503. while (OpCodes.ENDOP != (stepType = compiler.getOp(stepOpCodePos)))
  1504. {
  1505. stepCount++;
  1506. switch (stepType)
  1507. {
  1508. case OpCodes.FROM_ATTRIBUTES :
  1509. case OpCodes.MATCH_ATTRIBUTE :
  1510. if(foundWildAttribute) // Maybe not needed, but be safe.
  1511. return false;
  1512. // This doesn't seem to work as a test for wild card. Hmph.
  1513. // int nodeTestType = compiler.getStepTestType(stepOpCodePos);
  1514. String localName = compiler.getStepLocalName(stepOpCodePos);
  1515. // System.err.println("localName: "+localName);
  1516. if(localName.equals("*"))
  1517. {
  1518. foundWildAttribute = true;
  1519. }
  1520. break;
  1521. case OpCodes.FROM_FOLLOWING :
  1522. case OpCodes.FROM_FOLLOWING_SIBLINGS :
  1523. case OpCodes.FROM_PRECEDING :
  1524. case OpCodes.FROM_PRECEDING_SIBLINGS :
  1525. case OpCodes.FROM_PARENT :
  1526. case OpCodes.OP_VARIABLE :
  1527. case OpCodes.OP_EXTFUNCTION :
  1528. case OpCodes.OP_FUNCTION :
  1529. case OpCodes.OP_GROUP :
  1530. case OpCodes.FROM_NAMESPACE :
  1531. case OpCodes.FROM_ANCESTORS :
  1532. case OpCodes.FROM_ANCESTORS_OR_SELF :
  1533. case OpCodes.MATCH_ANY_ANCESTOR :
  1534. case OpCodes.MATCH_IMMEDIATE_ANCESTOR :
  1535. case OpCodes.FROM_DESCENDANTS_OR_SELF :
  1536. case OpCodes.FROM_DESCENDANTS :
  1537. if(potentialDuplicateMakingStepCount > 0)
  1538. return false;
  1539. potentialDuplicateMakingStepCount++;
  1540. case OpCodes.FROM_ROOT :
  1541. case OpCodes.FROM_CHILDREN :
  1542. case OpCodes.FROM_SELF :
  1543. if(foundWildAttribute)
  1544. return false;
  1545. break;
  1546. default :
  1547. throw new RuntimeException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NULL_ERROR_HANDLER, new Object[]{Integer.toString(stepType)})); //"Programmer's assertion: unknown opcode: "
  1548. // + stepType);
  1549. }
  1550. int nextStepOpCodePos = compiler.getNextStepPos(stepOpCodePos);
  1551. if (nextStepOpCodePos < 0)
  1552. break;
  1553. stepOpCodePos = nextStepOpCodePos;
  1554. }
  1555. return true;
  1556. }
  1557. public static boolean isOneStep(int analysis)
  1558. {
  1559. return (analysis & BITS_COUNT) == 0x00000001;
  1560. }
  1561. public static int getStepCount(int analysis)
  1562. {
  1563. return (analysis & BITS_COUNT);
  1564. }
  1565. /**
  1566. * First 8 bits are the number of top-level location steps. Hopefully
  1567. * there will never be more that 255 location steps!!!
  1568. */
  1569. public static final int BITS_COUNT = 0x000000FF;
  1570. /** 4 bits are reserved for future use. */
  1571. public static final int BITS_RESERVED = 0x00000F00;
  1572. /** Bit is on if the expression contains a top-level predicate. */
  1573. public static final int BIT_PREDICATE = (0x00001000);
  1574. /** Bit is on if any of the walkers contain an ancestor step. */
  1575. public static final int BIT_ANCESTOR = (0x00001000 << 1);
  1576. /** Bit is on if any of the walkers contain an ancestor-or-self step. */
  1577. public static final int BIT_ANCESTOR_OR_SELF = (0x00001000 << 2);
  1578. /** Bit is on if any of the walkers contain an attribute step. */
  1579. public static final int BIT_ATTRIBUTE = (0x00001000 << 3);
  1580. /** Bit is on if any of the walkers contain a child step. */
  1581. public static final int BIT_CHILD = (0x00001000 << 4);
  1582. /** Bit is on if any of the walkers contain a descendant step. */
  1583. public static final int BIT_DESCENDANT = (0x00001000 << 5);
  1584. /** Bit is on if any of the walkers contain a descendant-or-self step. */
  1585. public static final int BIT_DESCENDANT_OR_SELF = (0x00001000 << 6);
  1586. /** Bit is on if any of the walkers contain a following step. */
  1587. public static final int BIT_FOLLOWING = (0x00001000 << 7);
  1588. /** Bit is on if any of the walkers contain a following-sibiling step. */
  1589. public static final int BIT_FOLLOWING_SIBLING = (0x00001000 << 8);
  1590. /** Bit is on if any of the walkers contain a namespace step. */
  1591. public static final int BIT_NAMESPACE = (0x00001000 << 9);
  1592. /** Bit is on if any of the walkers contain a parent step. */
  1593. public static final int BIT_PARENT = (0x00001000 << 10);
  1594. /** Bit is on if any of the walkers contain a preceding step. */
  1595. public static final int BIT_PRECEDING = (0x00001000 << 11);
  1596. /** Bit is on if any of the walkers contain a preceding-sibling step. */
  1597. public static final int BIT_PRECEDING_SIBLING = (0x00001000 << 12);
  1598. /** Bit is on if any of the walkers contain a self step. */
  1599. public static final int BIT_SELF = (0x00001000 << 13);
  1600. /**
  1601. * Bit is on if any of the walkers contain a filter (i.e. id(), extension
  1602. * function, etc.) step.
  1603. */
  1604. public static final int BIT_FILTER = (0x00001000 << 14);
  1605. /** Bit is on if any of the walkers contain a root step. */
  1606. public static final int BIT_ROOT = (0x00001000 << 15);
  1607. /**
  1608. * If any of these bits are on, the expression may likely traverse outside
  1609. * the given subtree.
  1610. */
  1611. public static final int BITMASK_TRAVERSES_OUTSIDE_SUBTREE = (BIT_NAMESPACE // ??
  1612. | BIT_PRECEDING_SIBLING
  1613. | BIT_PRECEDING
  1614. | BIT_FOLLOWING_SIBLING
  1615. | BIT_FOLLOWING
  1616. | BIT_PARENT // except parent of attrs.
  1617. | BIT_ANCESTOR_OR_SELF
  1618. | BIT_ANCESTOR
  1619. | BIT_FILTER
  1620. | BIT_ROOT);
  1621. /**
  1622. * Bit is on if any of the walkers can go backwards in document
  1623. * order from the context node.
  1624. */
  1625. public static final int BIT_BACKWARDS_SELF = (0x00001000 << 16);
  1626. /** Found "//foo" pattern */
  1627. public static final int BIT_ANY_DESCENDANT_FROM_ROOT = (0x00001000 << 17);
  1628. /**
  1629. * Bit is on if any of the walkers contain an node() test. This is
  1630. * really only useful if the count is 1.
  1631. */
  1632. public static final int BIT_NODETEST_ANY = (0x00001000 << 18);
  1633. // can't go higher than 18!
  1634. /** Bit is on if the expression is a match pattern. */
  1635. public static final int BIT_MATCH_PATTERN = (0x00001000 << 19);
  1636. }