1 package net.sf.saxon.expr; 2 import net.sf.saxon.om.Item; 3 import net.sf.saxon.om.NodeInfo; 4 import net.sf.saxon.om.SequenceIterator; 5 import net.sf.saxon.trace.Location; 6 import net.sf.saxon.trans.XPathException; 7 import net.sf.saxon.value.*; 8 9 14 15 public class FilterIterator implements SequenceIterator { 16 17 protected SequenceIterator base; 18 protected Expression filter; 19 private int position = 0; 20 private Item current = null; 21 protected XPathContext filterContext; 22 23 29 30 public FilterIterator(SequenceIterator base, Expression filter, 31 XPathContext context) { 32 this.base = base; 33 this.filter = filter; 34 filterContext = context.newMinorContext(); 35 filterContext.setCurrentIterator(base); 36 filterContext.setOriginatingConstructType(Location.FILTER_EXPRESSION); 37 } 38 39 42 43 public Item next() throws XPathException { 44 current = getNextMatchingItem(); 45 if (current == null) { 46 position = -1; 47 } else { 48 position++; 49 } 50 return current; 51 } 52 53 57 58 protected Item getNextMatchingItem() throws XPathException { 59 while (true) { 60 Item next = base.next(); 61 if (next == null) { 62 return null; 63 } 64 if (matches()) { 65 return next; 66 } 67 } 68 } 69 70 73 74 protected boolean matches() throws XPathException { 75 76 79 82 SequenceIterator iterator = filter.iterate(filterContext); 83 Item first = iterator.next(); 84 if (first == null) { 85 return false; 86 } 87 if (first instanceof NodeInfo) { 88 return true; 89 } else { 90 if (first instanceof BooleanValue) { 91 if (iterator.next() != null) { 92 ExpressionTool.ebvError("sequence of two or more items starting with an atomic value"); 93 } 94 return ((BooleanValue)first).getBooleanValue(); 95 } else if (first instanceof StringValue) { 96 if (iterator.next() != null) { 97 ExpressionTool.ebvError("sequence of two or more items starting with an atomic value"); 98 } 99 return (first.getStringValueCS().length()!=0); 100 } else if (first instanceof NumericValue) { 101 if (iterator.next() != null) { 102 ExpressionTool.ebvError("sequence of two or more items starting with an atomic value"); 103 } 104 IntegerValue basePos = new IntegerValue(base.position()); 105 return first.equals(basePos); 106 } else { 107 ExpressionTool.ebvError("sequence starting with an atomic value other than a boolean, number, or string"); 108 return false; 109 } 110 } 111 } 112 113 public Item current() { 114 return current; 115 } 116 117 public int position() { 118 return position; 119 } 120 121 124 125 public SequenceIterator getAnother() throws XPathException { 126 return new FilterIterator(base.getAnother(), filter, 127 filterContext); 128 } 129 130 139 140 public int getProperties() { 141 return 0; 142 } 143 144 148 149 public static final class NonNumeric extends FilterIterator { 150 151 public NonNumeric(SequenceIterator base, Expression filter, 152 XPathContext context) { 153 super(base, filter, context); 154 } 155 156 159 160 protected boolean matches() throws XPathException { 161 return filter.effectiveBooleanValue(filterContext); 162 } 163 164 167 168 public SequenceIterator getAnother() throws XPathException { 169 return new FilterIterator.NonNumeric(base.getAnother(), filter, 170 filterContext); 171 } 172 } 173 174 178 179 public static final class Leading extends FilterIterator { 180 181 public Leading(SequenceIterator base, Expression filter, 182 XPathContext context) { 183 super(base, filter, context); 184 } 185 186 189 190 protected boolean matches() throws XPathException { 191 return filter.effectiveBooleanValue(filterContext); 192 } 193 194 197 198 protected Item getNextMatchingItem() throws XPathException { 199 while (true) { 200 Item next = base.next(); 201 if (next == null) { 202 return null; 203 } 204 if (matches()) { 205 return next; 206 } else { 207 return null; 209 } 210 } 211 } 212 213 216 217 public SequenceIterator getAnother() throws XPathException { 218 return new FilterIterator.Leading(base.getAnother(), filter, 219 filterContext); 220 } 221 222 223 } 224 225 226 } 227 228 229 230 | Popular Tags |