/xbird-open/main/src/java/xbird/xquery/expr/path/axis/DescendantOrSelfStep.java

http://xbird.googlecode.com/ · Java · 147 lines · 99 code · 16 blank · 32 comment · 21 complexity · 498adc09d03a2ab82bc885fc998d372e MD5 · raw file

  1. /*
  2. * @(#)$Id: DescendantOrSelfStep.java 3619 2008-03-26 07:23:03Z yui $
  3. *
  4. * Copyright 2006-2008 Makoto YUI
  5. *
  6. * Licensed under the Apache License, Version 2.0 (the "License");
  7. * you may not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. *
  18. * Contributors:
  19. * Makoto YUI - initial implementation
  20. */
  21. package xbird.xquery.expr.path.axis;
  22. import xbird.xquery.DynamicError;
  23. import xbird.xquery.XQueryException;
  24. import xbird.xquery.dm.value.*;
  25. import xbird.xquery.dm.value.sequence.*;
  26. import xbird.xquery.expr.path.NodeTest;
  27. import xbird.xquery.meta.*;
  28. import xbird.xquery.optim.RewriteInfo;
  29. /**
  30. * The descendant-or-self axis contains the context node and the descendants
  31. * of the context node.
  32. * <DIV lang="en"></DIV>
  33. * <DIV lang="ja"></DIV>
  34. *
  35. * @author Makoto YUI (yuin405+xbird@gmail.com)
  36. */
  37. public class DescendantOrSelfStep extends AxisStep {
  38. private static final long serialVersionUID = -1036349267969466494L;
  39. public DescendantOrSelfStep(NodeTest test) {
  40. this(DESC_OR_SELF, test);
  41. }
  42. public DescendantOrSelfStep(int kind, NodeTest test) {
  43. super(kind, test);
  44. }
  45. @Override
  46. public boolean isPathIndexAccessable(StaticContext statEnv, RewriteInfo info) {
  47. if(!info.hasPreviousStep()) {
  48. return false;
  49. }
  50. String nt = _nodeTest.toString();
  51. if(!"*".equals(nt) && !"node()".equals(nt)) {
  52. return false;
  53. }
  54. info.markDescendantOrSelf();
  55. return true;
  56. }
  57. public Sequence<? extends Item> eval(Sequence<? extends Item> contextSeq, DynamicContext dynEnv)
  58. throws XQueryException {
  59. if(contextSeq == null) {
  60. throw new DynamicError("err:XPDY0002", "ContextItem is not set");
  61. }
  62. final INodeSequence<XQNode> src = ProxyNodeSequence.wrap(contextSeq, dynEnv);
  63. final IFocus<XQNode> srcItor = src.iterator();
  64. if(srcItor.hasNext()) {
  65. final XQNode n = srcItor.next();
  66. if(srcItor.hasNext()) {
  67. srcItor.closeQuietly();
  68. reportError("err:XPTY0020", "Context item is expected to be a node, but was node sequence.");
  69. }
  70. srcItor.closeQuietly();
  71. // FIXME DMNode
  72. return new DescendantOrSelfEmurationSequence(n, _nodeTest, dynEnv);
  73. }
  74. srcItor.closeQuietly();
  75. return NodeSequence.<XQNode> emptySequence();
  76. }
  77. /**
  78. * Represents "/descendant-or-self::node()/"
  79. */
  80. public static final class RootDescStep extends DescendantOrSelfStep {
  81. private static final long serialVersionUID = -8533383126416496506L;
  82. public static final RootDescStep INSTANCE = new RootDescStep();
  83. public RootDescStep() {
  84. super(NodeTest.ANYNODE);
  85. }
  86. }
  87. protected static final class DescendantOrSelfEmurationSequence extends AxisEmurationSequence {
  88. private static final long serialVersionUID = 3516008834617795445L;
  89. private final NodeTest _filterNodeTest;
  90. private final XQNode _stopNode;
  91. private final long _stopNID;
  92. private final boolean _excludeSelf;
  93. public DescendantOrSelfEmurationSequence(XQNode baseNode, NodeTest nodeTest, DynamicContext dynEnv) {
  94. this(baseNode, nodeTest, dynEnv, false);
  95. }
  96. public DescendantOrSelfEmurationSequence(XQNode baseNode, NodeTest nodeTest, DynamicContext dynEnv, boolean excludeSelf) {
  97. super(baseNode, dynEnv);
  98. this._filterNodeTest = nodeTest;
  99. this._stopNode = baseNode.following(true);
  100. this._stopNID = (_stopNode == null) ? Long.MIN_VALUE : _stopNode.getPosition();
  101. this._excludeSelf = excludeSelf;
  102. }
  103. public boolean next(final IFocus<XQNode> focus) throws XQueryException {
  104. XQNode curNode = focus.getContextItem();
  105. for(int pos = focus.getContextPosition(); curNode != null; pos++) {
  106. if(pos == 0) {
  107. if(_excludeSelf) {
  108. curNode = curNode.firstChild();
  109. }
  110. } else {
  111. curNode = curNode.nextNode();
  112. if(curNode == null) {
  113. return false;
  114. }
  115. if(curNode == _stopNode) {// REVIEWME DMNode
  116. return false;
  117. }
  118. final long nid = curNode.getPosition();
  119. if(nid == _stopNID) {
  120. return false;
  121. }
  122. }
  123. if(_filterNodeTest.accepts(curNode)) {
  124. focus.setContextItem(curNode);
  125. return true;
  126. }
  127. }
  128. return false;
  129. }
  130. }
  131. }