1 package net.sf.saxon.expr; 2 3 import net.sf.saxon.om.*; 4 import net.sf.saxon.sort.DocumentOrderIterator; 5 import net.sf.saxon.sort.GlobalOrderComparer; 6 import net.sf.saxon.trace.Location; 7 import net.sf.saxon.trans.DynamicError; 8 import net.sf.saxon.trans.XPathException; 9 import net.sf.saxon.type.ItemType; 10 import net.sf.saxon.value.AtomicValue; 11 import net.sf.saxon.value.Cardinality; 12 13 import java.io.PrintStream ; 14 import java.util.Iterator ; 15 16 20 21 public final class SimpleMappingExpression extends ComputedExpression implements MappingFunction { 22 23 private Expression start; 24 private Expression step; 25 private boolean isHybrid; 26 27 36 37 public SimpleMappingExpression(Expression start, Expression step, boolean isHybrid) { 38 this.start = start; 39 this.step = step; 40 this.isHybrid = isHybrid; 41 adoptChildExpression(start); 42 adoptChildExpression(step); 43 44 } 45 46 49 50 public Expression getStartExpression() { 51 return start; 52 } 53 54 57 58 public Expression getStepExpression() { 59 return step; 60 } 61 65 66 public final ItemType getItemType() { 67 return step.getItemType(); 68 } 69 70 74 75 public Expression simplify(StaticContext env) { 76 return this; 78 } 79 80 83 84 public Expression typeCheck(StaticContext env, ItemType contextItemType) { 85 return this; 87 } 88 89 public Expression optimize(Optimizer opt, StaticContext env, ItemType contextItemType) throws XPathException { 90 return this; 91 } 92 93 96 97 public Expression promote(PromotionOffer offer) throws XPathException { 98 Expression exp = offer.accept(this); 99 if (exp != null) { 100 return exp; 101 } else { 102 start = doPromotion(start, offer); 103 if (offer.action == PromotionOffer.INLINE_VARIABLE_REFERENCES || 104 offer.action == PromotionOffer.REPLACE_CURRENT) { 105 step = doPromotion(step, offer); 109 } 110 resetStaticProperties(); 111 return this; 112 } 113 } 114 115 118 119 public Iterator iterateSubExpressions() { 120 return new PairIterator(start, step); 121 } 122 127 128 public int computeDependencies() { 129 return start.getDependencies() | 130 (step.getDependencies() & StaticProperty.DEPENDS_ON_XSLT_CONTEXT); 133 } 134 135 140 141 public int computeSpecialProperties() { 142 int p = super.computeSpecialProperties(); 143 if ((start.getSpecialProperties() & step.getSpecialProperties() & StaticProperty.NON_CREATIVE) != 0) { 144 p |= StaticProperty.NON_CREATIVE; 145 } 146 return p; 147 } 148 149 152 153 public int computeCardinality() { 154 int c1 = start.getCardinality(); 155 int c2 = step.getCardinality(); 156 return Cardinality.multiply(c1, c2); 157 } 158 159 162 163 public boolean equals(Object other) { 164 if (!(other instanceof SimpleMappingExpression)) { 165 return false; 166 } 167 SimpleMappingExpression p = (SimpleMappingExpression) other; 168 return (start.equals(p.start) && step.equals(p.step)); 169 } 170 171 174 175 public int hashCode() { 176 return "SimpleMappingExpression".hashCode() + start.hashCode() + step.hashCode(); 177 } 178 179 183 184 public SequenceIterator iterate(XPathContext context) throws XPathException { 185 186 190 SequenceIterator result = start.iterate(context); 191 XPathContext context2 = context.newMinorContext(); 192 context2.setCurrentIterator(result); 193 context2.setOriginatingConstructType(Location.PATH_EXPRESSION); 194 195 result = new MappingIterator(result, this, context2); 196 if (isHybrid) { 197 Item first = result.next(); 201 if (first == null) { 202 return EmptyIterator.getInstance(); 203 } else if (first instanceof AtomicValue) { 204 return new MappingIterator(result.getAnother(), AtomicValueChecker.theInstance, null); 205 } else { 206 return new DocumentOrderIterator( 207 new MappingIterator(result.getAnother(), NodeChecker.theInstance, null), 208 GlobalOrderComparer.getInstance()); 209 } 210 } else { 211 return result; 212 } 213 } 214 215 219 220 public Object map(Item item, XPathContext context) throws XPathException { 221 return step.iterate(context); 222 } 223 224 227 228 public void display(int level, NamePool pool, PrintStream out) { 229 out.println(ExpressionTool.indent(level) + "map /"); 230 start.display(level + 1, pool, out); 231 step.display(level + 1, pool, out); 232 } 233 234 private static class AtomicValueChecker implements MappingFunction { 235 public static AtomicValueChecker theInstance = new AtomicValueChecker(); 236 public Object map(Item item, XPathContext context) throws XPathException { 237 if (item instanceof AtomicValue) { 238 return item; 239 } else { 240 DynamicError err = new DynamicError( 241 "Cannot mix nodes and atomic values in the result of a path expression"); 242 err.setErrorCode("XPTY0018"); 243 err.setXPathContext(context); 244 throw err; 245 } 246 } 247 } 248 249 private static class NodeChecker implements MappingFunction { 250 public static NodeChecker theInstance = new NodeChecker(); 251 public Object map(Item item, XPathContext context) throws XPathException { 252 if (item instanceof NodeInfo) { 253 return item; 254 } else { 255 DynamicError err = new DynamicError( 256 "Cannot mix nodes and atomic values in the result of a path expression"); 257 err.setErrorCode("XPTY0018"); 258 err.setXPathContext(context); 259 throw err; 260 } 261 } 262 } 263 } 264 265 266 | Popular Tags |