1 package com.icl.saxon.expr; 2 import com.icl.saxon.Context; 3 import com.icl.saxon.om.NodeEnumeration; 4 import com.icl.saxon.functions.Last; 5 import com.icl.saxon.functions.Position; 6 7 11 12 class FilterExpression extends NodeSetExpression { 13 14 private Expression start; 15 private Expression filter; 16 private int dependencies = -1; 17 18 24 25 public FilterExpression(Expression start, Expression filter) { 26 this.start = start; 27 this.filter = filter; 28 } 29 30 33 34 public Expression simplify() throws XPathException { 35 36 start = start.simplify(); 37 filter = filter.simplify(); 38 39 if (start instanceof EmptyNodeSet) { 41 return start; 42 } 43 44 if (filter instanceof Value && !(filter instanceof NumericValue)) { 46 boolean f = ((Value)filter).asBoolean(); 47 if (f) { 48 return start; 49 } else { 50 return new EmptyNodeSet(); 51 } 52 } 53 54 57 if (filter instanceof Last) { 58 filter = new IsLastExpression(true); 59 } 60 61 66 if (start instanceof NodeSetIntent && 67 filter instanceof PositionRange) { 68 PositionRange pred = (PositionRange)filter; 69 if (pred.getMinPosition()==2 && pred.getMaxPosition()==Integer.MAX_VALUE) { 70 NodeSetIntent b = (NodeSetIntent)start; 72 if (b.getNodeSetExpression() instanceof FilterExpression) { 74 FilterExpression t = (FilterExpression)b.getNodeSetExpression(); 75 if (t.filter instanceof PositionRange) { 76 PositionRange pred2 = (PositionRange)t.filter; 77 if (pred2.getMaxPosition()==Integer.MAX_VALUE) { 78 return new FilterExpression(t.start, 80 new PositionRange(pred2.getMinPosition()+1, Integer.MAX_VALUE)); 81 } 82 } 83 } 84 } 85 } 86 87 return this; 88 } 89 90 95 96 public NodeEnumeration enumerate(Context context, boolean sort) throws XPathException { 97 98 103 int actualdep = getDependencies(); 104 int removedep = 0; 105 106 if ((actualdep & Context.XSLT_CONTEXT) != 0) { 107 removedep |= Context.XSLT_CONTEXT; 108 } 109 110 if (start.isContextDocumentNodeSet() && ((actualdep & Context.CONTEXT_DOCUMENT) != 0)) { 111 removedep |= Context.CONTEXT_DOCUMENT; 112 } 113 114 if (removedep != 0) { 115 return reduce(removedep, context).enumerate(context, sort); 116 } 117 118 if (!sort) { 119 if ( filter.getDataType()==Value.NUMBER || 121 filter.getDataType()==Value.ANY || 122 (filter.getDependencies() & (Context.POSITION|Context.LAST)) != 0 ) { 123 sort = true; 124 } 125 } 126 127 if (start instanceof SingletonNodeSet) { 128 if (!((SingletonNodeSet)start).isGeneralUseAllowed()) { 129 throw new XPathException("To use a result tree fragment in a filter expression, either use exsl:node-set() or specify version='1.1'"); 130 } 131 } 132 133 NodeEnumeration base = start.enumerate(context, sort); 134 if (!base.hasMoreElements()) { 135 return base; } 137 138 return new FilterEnumerator(base, filter, context, false); 139 } 140 141 146 147 public int getDependencies() { 148 if (dependencies==-1) { 151 dependencies = start.getDependencies() | 152 (filter.getDependencies() & Context.XSLT_CONTEXT); 153 } 154 return dependencies; 156 } 157 158 166 167 public Expression reduce(int dep, Context context) throws XPathException { 168 if ((dep & getDependencies()) != 0) { 169 Expression newstart = start.reduce(dep, context); 170 Expression newfilter = filter.reduce(dep & Context.XSLT_CONTEXT, context); 171 Expression e = new FilterExpression(newstart, newfilter); 172 e.setStaticContext(getStaticContext()); 173 return e.simplify(); 174 } else { 175 return this; 176 } 177 } 178 179 184 185 public boolean isContextDocumentNodeSet() { 186 return start.isContextDocumentNodeSet(); 187 } 188 189 192 193 public void display(int level) { 194 System.err.println(indent(level) + "filter"); 195 start.display(level+1); 196 filter.display(level+1); 197 } 198 199 } 200 201 202 203 | Popular Tags |