diff --git a/exist-core/src/main/java/org/exist/xquery/ContextItemExpression.java b/exist-core/src/main/java/org/exist/xquery/ContextItemExpression.java index a59819efe7e..b3f4fceef90 100644 --- a/exist-core/src/main/java/org/exist/xquery/ContextItemExpression.java +++ b/exist-core/src/main/java/org/exist/xquery/ContextItemExpression.java @@ -29,8 +29,6 @@ public class ContextItemExpression extends LocationStep { - private int returnType = Type.ITEM; - public ContextItemExpression(final XQueryContext context) { // TODO: create class AnyItemTest (one private implementation found in saxon) super(context, Constants.SELF_AXIS, new AnyNodeTest()); @@ -40,7 +38,7 @@ public ContextItemExpression(final XQueryContext context) { public void analyze(AnalyzeContextInfo contextInfo) throws XPathException { contextInfo.addFlag(DOT_TEST); // set return type to static type to allow for index use in optimization step - returnType = contextInfo.getStaticType(); + staticReturnType = contextInfo.getStaticType(); super.analyze(contextInfo); } @@ -69,7 +67,8 @@ public Sequence eval(final Sequence contextSequence, final Item contextItem) thr @Override public int returnsType() { - return returnType; + // "." will have the same type as the parent expression + return staticReturnType; } @Override diff --git a/exist-core/src/main/java/org/exist/xquery/LocationStep.java b/exist-core/src/main/java/org/exist/xquery/LocationStep.java index a2c840e6cdf..8511a953f61 100644 --- a/exist-core/src/main/java/org/exist/xquery/LocationStep.java +++ b/exist-core/src/main/java/org/exist/xquery/LocationStep.java @@ -41,7 +41,7 @@ /** * Processes all location path steps (like descendant::*, ancestor::XXX). - * + *

* The results of the first evaluation of the expression are cached for the * lifetime of the object and only reloaded if the context sequence (as passed * to the {@link #eval(Sequence, Item)} method) has changed. @@ -63,7 +63,7 @@ public class LocationStep extends Step { //private int parentDeps = Dependency.UNKNOWN_DEPENDENCY; private boolean preloadedData = false; protected boolean optimized = false; -// private boolean inUpdate = false; + //private boolean inUpdate = false; private boolean useDirectChildSelect = false; private boolean applyPredicate = true; @@ -84,36 +84,36 @@ public LocationStep(final XQueryContext context, final int axis) { * Creates a new instance. * * @param context the XQuery context - * @param axis the axis of the location step - * @param test a node test on the axis + * @param axis the axis of the location step + * @param test a node test on the axis */ - public LocationStep(final XQueryContext context, final int axis, final NodeTest test) { + public LocationStep(final XQueryContext context, final int axis, final NodeTest test) { super(context, axis, test); } @Override public int getDependencies() { - int deps = Dependency.CONTEXT_SET; + int dependencies = Dependency.CONTEXT_SET; // self axis has an obvious dependency on the context item // likewise we depend on the context item if this is a single path step (outside a predicate) - if (!this.inPredicate && - (this.axis == Constants.SELF_AXIS || + if (!inPredicate && + (axis == Constants.SELF_AXIS || (parent != null && parent.getSubExpressionCount() > 0 && parent.getSubExpression(0) == this))) { - deps = deps | Dependency.CONTEXT_ITEM; + dependencies = dependencies | Dependency.CONTEXT_ITEM; } // TODO : normally, we should call this one... // int deps = super.getDependencies(); ??? - for (final Predicate pred : predicates) { - deps |= pred.getDependencies(); + for (final Predicate predicate : predicates) { + dependencies |= predicate.getDependencies(); } // TODO : should we remove the CONTEXT_ITEM dependency returned by the // predicates ? See the comment above. // consider nested predicates however... - return deps; + return dependencies; } /** @@ -147,10 +147,10 @@ private boolean hasPreloadedData() { * @param nodes a NodeSet value */ public void setPreloadedData(final DocumentSet docs, final NodeSet nodes) { - this.preloadedData = true; - this.currentDocs = docs; - this.currentSet = nodes; - this.optimized = true; + preloadedData = true; + currentDocs = docs; + currentSet = nodes; + optimized = true; } /** @@ -165,12 +165,9 @@ private Sequence applyPredicate(Sequence outerSequence, final Sequence contextSe if (contextSequence == null) { return Sequence.EMPTY_SEQUENCE; } - if (predicates.size() == 0 - || !applyPredicate - || (!(contextSequence instanceof VirtualNodeSet) && contextSequence - .isEmpty())) - // Nothing to apply - { + if (predicates.size() == 0 || !applyPredicate || ( + !(contextSequence instanceof VirtualNodeSet) && contextSequence.isEmpty())) { + // Nothing to apply return contextSequence; } Sequence result; @@ -183,9 +180,8 @@ private Sequence applyPredicate(Sequence outerSequence, final Sequence contextSe // // If the predicate is known to return a node set, no special treatment // is required. - if (abbreviatedStep - && (pred.getExecutionMode() != Predicate.ExecutionMode.NODE || !contextSequence - .isPersistentSet())) { + if (abbreviatedStep && ( + pred.getExecutionMode() != Predicate.ExecutionMode.NODE || !contextSequence.isPersistentSet())) { result = new ValueSequence(); ((ValueSequence) result).keepUnOrdered(unordered); if (contextSequence.isPersistentSet()) { @@ -222,9 +218,9 @@ private Sequence processPredicate(Sequence outerSequence, final Sequence context for (final Iterator i = predicates.iterator(); i.hasNext() && (result instanceof VirtualNodeSet || !result.isEmpty()); ) { // TODO : log and/or profile ? - final Predicate pred = i.next(); - pred.setContextDocSet(getContextDocSet()); - result = pred.evalPredicate(outerSequence, result, axis); + final Predicate predicate = i.next(); + predicate.setContextDocSet(getContextDocSet()); + result = predicate.evalPredicate(outerSequence, result, axis); // subsequent predicates operate on the result of the previous one outerSequence = null; context.setContextSequencePosition(0, null); @@ -234,7 +230,7 @@ private Sequence processPredicate(Sequence outerSequence, final Sequence context @Override public void analyze(final AnalyzeContextInfo contextInfo) throws XPathException { - this.parent = contextInfo.getParent(); + parent = contextInfo.getParent(); unordered = (contextInfo.getFlags() & UNORDERED) > 0; @@ -248,58 +244,82 @@ public void analyze(final AnalyzeContextInfo contextInfo) throws XPathException if ((contextInfo.getFlags() & USE_TREE_TRAVERSAL) > 0) { useDirectChildSelect = true; } + // Mark ".", which is expanded as self::node() by the parser // even though it may *also* be relevant with atomic sequences - if (this.axis == Constants.SELF_AXIS - && this.test.getType() == Type.NODE) { + // JL: may be unnecessary since ContextItemExpression will add the DOT_TEST flag by itself + // JL: literal self::node() might still need this + if (axis == Constants.SELF_AXIS && test.getType() == Type.NODE) { contextInfo.addFlag(DOT_TEST); } - //Change axis from descendant-or-self to descendant for '//' - if (this.axis == Constants.DESCENDANT_SELF_AXIS && isAbbreviated()) { - this.axis = Constants.DESCENDANT_AXIS; + // Change axis from descendant-or-self to descendant for '//' + if (axis == Constants.DESCENDANT_SELF_AXIS && isAbbreviated()) { + axis = Constants.DESCENDANT_AXIS; } + final Expression contextStep; + final LocationStep cStep; + final NodeTest stepTest; + final NodeTest contextStepTest; + // static analysis for empty-sequence switch (axis) { case Constants.SELF_AXIS: - if (getTest().getType() != Type.NODE) { - final Expression contextStep = contextInfo.getContextStep(); - if (contextStep instanceof LocationStep) { - final LocationStep cStep = (LocationStep) contextStep; - - // WM: the following checks will only work on simple filters like //a[self::b], so we - // have to make sure they are not applied to more complex expression types - if (parent.getSubExpressionCount() == 1 && !Type.subTypeOf(getTest().getType(), cStep.getTest().getType())) { - throw new XPathException(this, - ErrorCodes.XPST0005, "Got nothing from self::" + getTest() + ", because parent node kind " + Type.getTypeName(cStep.getTest().getType())); - } + if (getTest().getType() == Type.NODE) { + break; + } - if (parent.getSubExpressionCount() == 1 && !(cStep.getTest().isWildcardTest() || getTest().isWildcardTest()) && !cStep.getTest().equals(getTest())) { - throw new XPathException(this, - ErrorCodes.XPST0005, "Self::" + getTest() + " called on set of nodes which do not contain any nodes of this name."); - } - } + // WM: the following checks will only work on simple filters like //a[self::b], so we + // have to make sure they are not applied to more complex expression types + if (parent.getSubExpressionCount() > 1) { + break; + } + + contextStep = contextInfo.getContextStep(); + if (!(contextStep instanceof LocationStep)) { + break; + } + + cStep = (LocationStep) contextStep; + stepTest = getTest(); + contextStepTest = cStep.getTest(); + + if (!Type.subTypeOf(stepTest.getType(), contextStepTest.getType())) { + // return empty sequence + contextInfo.setStaticType(Type.EMPTY); + staticReturnType = Type.EMPTY; + break; + } + + if (!stepTest.isWildcardTest() && + !contextStepTest.isWildcardTest() && + !contextStepTest.equals(stepTest)) { + // return empty sequence + contextInfo.setStaticType(Type.EMPTY); + staticReturnType = Type.EMPTY; } break; -// case Constants.DESCENDANT_AXIS: +// case Constants.DESCENDANT_AXIS: case Constants.DESCENDANT_SELF_AXIS: - final Expression contextStep = contextInfo.getContextStep(); - if (contextStep instanceof LocationStep) { - final LocationStep cStep = (LocationStep) contextStep; - - if (( - cStep.getTest().getType() == Type.ATTRIBUTE || - cStep.getTest().getType() == Type.TEXT - ) - && cStep.getTest() != getTest()) { - throw new XPathException(this, - ErrorCodes.XPST0005, "Descendant-or-self::" + getTest() + " from an attribute gets nothing."); - } + contextStep = contextInfo.getContextStep(); + if (!(contextStep instanceof LocationStep)) { + break; + } + + cStep = (LocationStep) contextStep; + stepTest = getTest(); + contextStepTest = cStep.getTest(); + + if ((contextStepTest.getType() == Type.ATTRIBUTE || contextStepTest.getType() == Type.TEXT) && + !contextStepTest.equals(stepTest)) { + // return empty sequence + contextInfo.setStaticType(Type.EMPTY); + staticReturnType = Type.EMPTY; } break; -// case Constants.PARENT_AXIS: -// case Constants.ATTRIBUTE_AXIS: +// case Constants.PARENT_AXIS: +// case Constants.ATTRIBUTE_AXIS: default: } @@ -363,7 +383,6 @@ public Sequence eval(Sequence contextSequence, final Item contextItem) try { switch (axis) { - case Constants.DESCENDANT_AXIS: case Constants.DESCENDANT_SELF_AXIS: result = getDescendants(context, contextSequence); @@ -464,16 +483,15 @@ private boolean needsComputation() { if (nodeTestType == null) { nodeTestType = test.getType(); } - if (nodeTestType != Type.NODE - && nodeTestType != Type.ELEMENT - && nodeTestType != Type.PROCESSING_INSTRUCTION) { + if (nodeTestType != Type.NODE && + nodeTestType != Type.ELEMENT && + nodeTestType != Type.PROCESSING_INSTRUCTION) { if (context.getProfiler().isEnabled()) { context.getProfiler().message(this, Profiler.OPTIMIZATIONS, "OPTIMIZATION", "avoid useless computations"); } return false; } - } return true; } @@ -534,7 +552,7 @@ private Sequence getSelf(final XQueryContext context, final Sequence contextSequ } else { final NewArrayNodeSet results = new NewArrayNodeSet(); for (final NodeProxy p : contextSet) { - if(test.matches(p)) { + if (test.matches(p)) { results.add(p); } } @@ -579,10 +597,8 @@ protected Sequence getAttributes(final XQueryContext context, final Sequence con if (hasPreloadedData()) { final DocumentSet docs = getDocumentSet(contextSet); synchronized (context) { - if (currentSet == null - || currentDocs == null - || (!optimized && !(docs == currentDocs || docs - .equalDocs(currentDocs)))) { + if (currentSet == null || currentDocs == null || ( + !optimized && !(docs.equals(currentDocs) || docs.equalDocs(currentDocs)))) { final StructuralIndex index = context.getBroker().getStructuralIndex(); if (context.getProfiler().isEnabled()) { context.getProfiler().message( @@ -669,10 +685,8 @@ private Sequence getChildren(final XQueryContext context, final Sequence context synchronized (context) { // TODO : understand why this one is different from the other // ones - if (currentSet == null - || currentDocs == null - || (!optimized && !(docs == currentDocs || docs - .equalDocs(currentDocs)))) { + if (currentSet == null || currentDocs == null || ( + !optimized && !(docs.equals(currentDocs) || docs.equalDocs(currentDocs)))) { final StructuralIndex index = context.getBroker().getStructuralIndex(); if (context.getProfiler().isEnabled()) { context.getProfiler().message( @@ -713,15 +727,14 @@ private Sequence getChildren(final XQueryContext context, final Sequence context private Sequence getDescendants(final XQueryContext context, final Sequence contextSequence) throws XPathException { if (!contextSequence.isPersistentSet()) { final MemoryNodeSet nodes = contextSequence.toMemNodeSet(); - return nodes.getDescendants(axis == Constants.DESCENDANT_SELF_AXIS, - test); + return nodes.getDescendants(axis == Constants.DESCENDANT_SELF_AXIS, test); } final NodeSet contextSet = contextSequence.toNodeSet(); // TODO : understand this. I guess comments should be treated in a // similar way ? -pb - if ((!hasPreloadedData() && test.isWildcardTest()) - || test.getType() == Type.PROCESSING_INSTRUCTION) { + if ((!hasPreloadedData() && test.isWildcardTest()) || + test.getType() == Type.PROCESSING_INSTRUCTION) { // test is one out of *, text(), node() including // processing-instruction(targetname) final VirtualNodeSet vset = new VirtualNodeSet(context.getBroker(), axis, test, contextId, contextSet); @@ -730,12 +743,9 @@ private Sequence getDescendants(final XQueryContext context, final Sequence cont } else if (hasPreloadedData()) { final DocumentSet docs = getDocumentSet(contextSet); synchronized (context) { - // TODO : understand why this one is different from the other - // ones - if (currentSet == null - || currentDocs == null - || (!optimized && !(docs == currentDocs || docs - .equalDocs(currentDocs)))) { + // TODO : understand why this one is different from the other ones + if (currentSet == null || currentDocs == null || ( + !optimized && !(docs.equals(currentDocs) || docs.equalDocs(currentDocs)))) { final StructuralIndex index = context.getBroker().getStructuralIndex(); if (context.getProfiler().isEnabled()) { context.getProfiler().message( @@ -752,11 +762,11 @@ private Sequence getDescendants(final XQueryContext context, final Sequence cont switch (axis) { case Constants.DESCENDANT_SELF_AXIS: - return currentSet.selectAncestorDescendant(contextSet, NodeSet.DESCENDANT, true, contextId, - true); + return currentSet.selectAncestorDescendant( + contextSet, NodeSet.DESCENDANT, true, contextId, true); case Constants.DESCENDANT_AXIS: - return currentSet.selectAncestorDescendant(contextSet, NodeSet.DESCENDANT, false, contextId, - true); + return currentSet.selectAncestorDescendant( + contextSet, NodeSet.DESCENDANT, false, contextId, true); default: throw new IllegalArgumentException("Unsupported axis specified"); } @@ -810,8 +820,7 @@ protected Sequence getSiblings(final XQueryContext context, final Sequence conte } final NodeSet contextSet = contextSequence.toNodeSet(); - // TODO : understand this. I guess comments should be treated in a - // similar way ? -pb + // TODO : understand this. I guess comments should be treated in a similar way ? -pb if (test.getType() == Type.PROCESSING_INSTRUCTION) { final VirtualNodeSet vset = new VirtualNodeSet(context.getBroker(), axis, test, contextId, contextSet); @@ -888,11 +897,9 @@ protected Sequence getSiblings(final XQueryContext context, final Sequence conte /** * Get the preceding or following axis nodes * - * @param context the xquery context + * @param context the xquery context * @param contextSequence the context sequence - * * @return the nodes from the preceding or following axis - * * @throws XPathException if an error occurs */ private Sequence getPrecedingOrFollowing(final XQueryContext context, final Sequence contextSequence) @@ -1012,11 +1019,9 @@ private int computeLimit() throws XPathException { /** * Get the ancestor axis nodes * - * @param context the xquery context + * @param context the xquery context * @param contextSequence the context sequence - * * @return the ancestor nodes - * * @throws XPathException if an error occurs */ protected Sequence getAncestors(final XQueryContext context, final Sequence contextSequence) throws XPathException { @@ -1116,11 +1121,9 @@ protected Sequence getAncestors(final XQueryContext context, final Sequence cont /** * Get the parent axis nodes * - * @param context the xquery context + * @param context the xquery context * @param contextSequence the context sequence - * * @return the parent nodes - * * @throws XPathException if an error occurs */ protected Sequence getParents(final XQueryContext context, final Sequence contextSequence) throws XPathException { @@ -1142,7 +1145,8 @@ protected Sequence getParents(final XQueryContext context, final Sequence contex } else if (hasPreloadedData()) { final DocumentSet docs = getDocumentSet(contextSet); synchronized (context) { - if (currentSet == null || currentDocs == null || (!optimized && !(docs == currentDocs || docs.equalDocs(currentDocs)))) { + if (currentSet == null || currentDocs == null || ( + !optimized && !(docs.equals(currentDocs) || docs.equalDocs(currentDocs)))) { final StructuralIndex index = context.getBroker().getStructuralIndex(); if (context.getProfiler().isEnabled()) { context.getProfiler().message( @@ -1289,7 +1293,7 @@ private class FollowingSiblingFilter extends AbstractFilterBase { boolean sibling = false; FollowingSiblingFilter(final NodeTest test, final NodeProxy start, final NodeSet result, - final int contextId, final int limit) { + final int contextId, final int limit) { super(test, result, contextId, limit); this.start = start; this.level = start.getNodeId().getTreeLevel(); @@ -1341,7 +1345,7 @@ private class PrecedingSiblingFilter extends AbstractFilterBase { final NodeProxy referenceNode; PrecedingSiblingFilter(final NodeTest test, final NodeProxy start, final NodeProxy referenceNode, - final NodeSet result, final int contextId) { + final NodeSet result, final int contextId) { super(test, result, contextId, -1); this.level = start.getNodeId().getTreeLevel(); this.referenceNode = referenceNode; @@ -1389,7 +1393,7 @@ private class FollowingFilter extends AbstractFilterBase { boolean isAfter = false; FollowingFilter(final NodeTest test, final NodeProxy root, final NodeProxy referenceNode, final NodeSet result, - final int contextId, final int limit) { + final int contextId, final int limit) { super(test, result, contextId, limit); this.root = root; this.referenceNode = referenceNode; @@ -1438,7 +1442,7 @@ private class PrecedingFilter extends AbstractFilterBase { final NodeProxy referenceNode; PrecedingFilter(final NodeTest test, final NodeProxy root, final NodeProxy referenceNode, final NodeSet result, - final int contextId) { + final int contextId) { super(test, result, contextId, -1); this.root = root; this.referenceNode = referenceNode; diff --git a/exist-core/src/main/java/org/exist/xquery/Step.java b/exist-core/src/main/java/org/exist/xquery/Step.java index bafa3bbcc95..dea3fad4167 100644 --- a/exist-core/src/main/java/org/exist/xquery/Step.java +++ b/exist-core/src/main/java/org/exist/xquery/Step.java @@ -35,7 +35,7 @@ public abstract class Step extends AbstractExpression { protected final static Logger LOG = LogManager.getLogger(Step.class); - protected int axis = Constants.UNKNOWN_AXIS; + protected int axis; protected boolean abbreviatedStep = false; @@ -47,18 +47,18 @@ public abstract class Step extends AbstractExpression { protected int staticReturnType = Type.ITEM; - public Step( XQueryContext context, int axis ) { + public Step(XQueryContext context, int axis) { super(context); this.axis = axis; } - public Step( XQueryContext context, int axis, NodeTest test ) { - this( context, axis ); + public Step(XQueryContext context, int axis, NodeTest test) { + this(context, axis); this.test = test; } - public void addPredicate( Expression expr ) { - predicates.add( (Predicate) expr ); + public void addPredicate(Expression expr) { + predicates.add((Predicate) expr); } public void insertPredicate(Expression previous, Expression predicate) { @@ -78,30 +78,36 @@ public List getPredicates() { return predicates; } - /* (non-Javadoc) - * @see org.exist.xquery.Expression#analyze(org.exist.xquery.AnalyzeContextInfo) - */ + @Override public void analyze(AnalyzeContextInfo contextInfo) throws XPathException { - if (test != null && test.getName() != null && - test.getName().getPrefix() != null && - (!test.getName().getPrefix().isEmpty()) && context.getInScopePrefixes() != null && - context.getURIForPrefix(test.getName().getPrefix()) == null) - {throw new XPathException(this, ErrorCodes.XPST0081, "undeclared prefix '" - + test.getName().getPrefix() + "'");} + if ( + test != null && + test.getName() != null && + test.getName().getPrefix() != null && + !test.getName().getPrefix().isEmpty() && + context.getInScopePrefixes() != null && + context.getURIForPrefix(test.getName().getPrefix()) == null) { + throw new XPathException(this, ErrorCodes.XPST0081, + "undeclared prefix '" + test.getName().getPrefix() + "'"); + } + inPredicate = (contextInfo.getFlags() & IN_PREDICATE) > 0; this.contextId = contextInfo.getContextId(); + if (predicates.size() > 0) { final AnalyzeContextInfo newContext = new AnalyzeContextInfo(contextInfo); newContext.setStaticType(this.axis == Constants.SELF_AXIS ? contextInfo.getStaticType() : Type.NODE); newContext.setParent(this); newContext.setContextStep(this); - for (final Predicate pred : predicates) { - pred.analyze(newContext); + + for (final Predicate predicate : predicates) { + predicate.analyze(newContext); } } // if we are on the self axis, remember the static return type given in the context - if (this.axis == Constants.SELF_AXIS) - {staticReturnType = contextInfo.getStaticType();} + if (this.axis == Constants.SELF_AXIS) { + staticReturnType = contextInfo.getStaticType(); + } } /** @@ -109,37 +115,35 @@ public void analyze(AnalyzeContextInfo contextInfo) throws XPathException { * If yes, set a flag on the {@link LocationStep} * * @param inPredicate true if in a predicate, false otherwise - * * @return true if the first filter is a positional predicate */ protected boolean checkPositionalFilters(final boolean inPredicate) { - if (!inPredicate && this.hasPredicates()) { - final List preds = this.getPredicates(); - final Predicate predicate = preds.get(0); - final Expression predExpr = predicate.getFirst(); - // only apply optimization if the static return type is a single number - // and there are no dependencies on the context item - if (Type.subTypeOfUnion(predExpr.returnsType(), Type.NUMBER) && - !Dependency.dependsOn(predExpr, Dependency.CONTEXT_POSITION)) { - return true; - } + if (inPredicate || !hasPredicates()) { + return false; } - return false; + + final List predicates = this.getPredicates(); + final Predicate predicate = predicates.get(0); + final Expression predicateExpr = predicate.getFirst(); + + // only apply optimization if the static return type is a single number + // and there are no dependencies on the context item + return (Type.subTypeOfUnion(predicateExpr.returnsType(), Type.NUMBER) && + !Dependency.dependsOn(predicateExpr, Dependency.CONTEXT_POSITION)); } - public abstract Sequence eval( Sequence contextSequence, Item contextItem ) throws XPathException; + public abstract Sequence eval(Sequence contextSequence, Item contextItem) throws XPathException; public int getAxis() { return axis; } - /* (non-Javadoc) - * @see org.exist.xquery.AbstractExpression#setPrimaryAxis(int) - */ + @Override public void setPrimaryAxis(int axis) { this.axis = axis; } + @Override public int getPrimaryAxis() { return this.axis; } @@ -152,59 +156,70 @@ public void setAbbreviated(boolean abbrev) { abbreviatedStep = abbrev; } - /* (non-Javadoc) - * @see org.exist.xquery.Expression#dump(org.exist.xquery.util.ExpressionDumper) - */ + @Override public void dump(ExpressionDumper dumper) { - if (axis != Constants.UNKNOWN_AXIS) - {dumper.display( Constants.AXISSPECIFIERS[axis] );} - dumper.display( "::" ); - if ( test != null ) + if (axis != Constants.UNKNOWN_AXIS) { + dumper.display(Constants.AXISSPECIFIERS[axis]); + } + dumper.display("::"); + if (test != null) { //TODO : toString() or... dump ? - {dumper.display( test.toString() );} - else - {dumper.display( "node()" );} - if ( predicates.size() > 0 ) - for (final Predicate pred : predicates) { - pred.dump(dumper); + dumper.display(test.toString()); + } else { + dumper.display("node()"); + } + if (predicates.size() > 0) { + for (final Predicate predicates : predicates) { + predicates.dump(dumper); } + } } + @Override public String toString() { final StringBuilder result = new StringBuilder(); - if (axis != Constants.UNKNOWN_AXIS) - {result.append( Constants.AXISSPECIFIERS[axis] );} - result.append( "::" ); - if (test != null ) - {result.append( test.toString() );} - else - {result.append( "node()" );} - if (predicates.size() > 0 ) - for (final Predicate pred : predicates) { - result.append(pred.toString()); + + if (axis != Constants.UNKNOWN_AXIS) { + result.append(Constants.AXISSPECIFIERS[axis]); + } + + result.append("::"); + + if (test != null) { + result.append(test.toString()); + } else { + result.append("node()"); + } + + if (predicates.size() > 0) { + for (final Predicate predicates : predicates) { + result.append(predicates.toString()); } + } return result.toString(); } + @Override public int returnsType() { - //Polysemy of "." which might be atomic if the context sequence is atomic itself + // Polysemy of "." which might be atomic if the context sequence is atomic itself if (axis == Constants.SELF_AXIS) { - //Type.ITEM by default : this may change *after* evaluation + // Type.ITEM by default : this may change *after* evaluation return staticReturnType; - } else - {return Type.NODE;} + } else { + return Type.NODE; + } } @Override public Cardinality getCardinality() { return Cardinality.ZERO_OR_MORE; - } + } - public void setAxis( int axis ) { + public void setAxis(int axis) { this.axis = axis; } - public void setTest( NodeTest test ) { + public void setTest(NodeTest test) { this.test = test; } @@ -212,13 +227,11 @@ public NodeTest getTest() { return test; } - /* (non-Javadoc) - * @see org.exist.xquery.AbstractExpression#resetState() - */ + @Override public void resetState(boolean postOptimization) { super.resetState(postOptimization); - for (final Predicate pred : predicates) { - pred.resetState(postOptimization); + for (final Predicate predicate : predicates) { + predicate.resetState(postOptimization); } } } \ No newline at end of file