1 package net.sf.saxon.instruct; 2 import net.sf.saxon.expr.*; 3 import net.sf.saxon.om.EmptyIterator; 4 import net.sf.saxon.om.Item; 5 import net.sf.saxon.om.NamePool; 6 import net.sf.saxon.om.SequenceIterator; 7 import net.sf.saxon.pattern.NoNodeTest; 8 import net.sf.saxon.trans.DynamicError; 9 import net.sf.saxon.trans.XPathException; 10 import net.sf.saxon.type.AnyItemType; 11 import net.sf.saxon.type.ItemType; 12 import net.sf.saxon.type.SchemaType; 13 import net.sf.saxon.type.Type; 14 import net.sf.saxon.value.Cardinality; 15 import net.sf.saxon.value.EmptySequence; 16 import net.sf.saxon.value.SequenceExtent; 17 18 import java.io.PrintStream ; 19 import java.util.*; 20 21 22 26 27 public class Block extends Instruction { 28 29 private Expression[] children; 30 31 public Block() { 32 } 33 34 public static Block makeBlock(Expression e1, Expression e2) { 35 if (e1 instanceof Block || e2 instanceof Block) { 36 Iterator it1 = (e1 instanceof Block ? e1.iterateSubExpressions() : new MonoIterator(e1)); 37 Iterator it2 = (e2 instanceof Block ? e2.iterateSubExpressions() : new MonoIterator(e2)); 38 List list = new ArrayList(10); 39 while (it1.hasNext()) { 40 list.add(it1.next()); 41 } 42 while (it2.hasNext()) { 43 list.add(it2.next()); 44 } 45 Expression[] exps = new Expression[list.size()]; 46 exps = (Expression[])list.toArray(exps); 47 Block b = new Block(); 48 b.setChildren(exps); 49 return b; 50 } else { 51 Expression[] exps = {e1, e2}; 52 Block b = new Block(); 53 b.setChildren(exps); 54 return b; 55 } 56 } 57 58 62 63 public void setChildren(Expression[] children) { 64 if (children==null || children.length==0) { 65 this.children = null; 66 } else { 67 this.children = children; 68 for (int c=0; c<children.length; c++) { 69 adoptChildExpression(children[c]); 70 } 71 } 72 } 73 74 79 80 public Expression[] getChildren() { 81 return children; 82 } 83 84 public Iterator iterateSubExpressions() { 85 if (children == null) { 86 return Collections.EMPTY_LIST.iterator(); 87 } else { 88 return Arrays.asList(children).iterator(); 89 } 90 } 91 92 96 97 public final ItemType getItemType() { 98 if (children==null || children.length==0) { 99 return NoNodeTest.getInstance(); 100 } 101 ItemType t1 = children[0].getItemType(); 102 for (int i=1; i<children.length; i++) { 103 t1 = Type.getCommonSuperType(t1, children[i].getItemType()); 104 if (t1 instanceof AnyItemType) { 105 return t1; } 107 } 108 return t1; 109 } 110 111 114 115 public final int getCardinality() { 116 if (children==null || children.length==0) { 117 return StaticProperty.EMPTY; 118 } 119 int c1 = children[0].getCardinality(); 120 for (int i=1; i<children.length; i++) { 121 c1 = Cardinality.add(c1, children[i].getCardinality()); 122 if (c1 == StaticProperty.ALLOWS_ZERO_OR_MORE) { 123 break; 124 } 125 } 126 return c1; 127 } 128 129 134 135 public final boolean createsNewNodes() { 136 if (children==null) { 137 return false; 138 }; 139 for (int i=0; i<children.length; i++) { 140 int props = children[i].getSpecialProperties(); 141 if ((props & StaticProperty.NON_CREATIVE) == 0) { 142 return true; 143 } 144 } 145 return false; 146 } 147 148 156 157 public Expression simplify(StaticContext env) throws XPathException { 158 boolean allAtomic = true; 159 boolean nested = false; 160 if (children != null) { 161 for (int c=0; c<children.length; c++) { 162 children[c] = children[c].simplify(env); 163 if (!(children[c] instanceof Item)) { 164 allAtomic = false; 165 } 166 if (children[c] instanceof Block) { 167 nested = true; 168 } else if (children[c] instanceof EmptySequence) { 169 nested = true; 170 } 171 } 172 if (children.length == 1) { 173 return getChildren()[0]; 174 } 175 if (children.length == 0) { 176 return EmptySequence.getInstance(); 177 } 178 if (nested) { 179 List list = new ArrayList(children.length*2); 180 flatten(list); 181 children = new Expression[list.size()]; 182 for (int i=0; i<children.length; i++) { 183 children[i] = (Expression)list.get(i); 184 adoptChildExpression(children[i]); 185 } 186 } 187 if (allAtomic) { 188 Item[] values = new Item[children.length]; 189 for (int c=0; c<children.length; c++) { 190 values[c] = (Item)children[c]; 191 } 192 return new SequenceExtent(values); 193 } 194 } else { 195 return EmptySequence.getInstance(); 196 } 197 198 return this; 199 } 200 201 private void flatten(List list) { 202 for (int i=0; i<children.length; i++) { 203 if (children[i] instanceof Block) { 204 ((Block)children[i]).flatten(list); 205 } else if (children[i] instanceof EmptySequence) { 206 } else { 208 list.add(children[i]); 209 } 210 } 211 } 212 213 public Expression typeCheck(StaticContext env, ItemType contextItemType) throws XPathException { 214 boolean nested = false; 215 if (children != null) { 216 for (int c=0; c<children.length; c++) { 217 children[c] = children[c].typeCheck(env, contextItemType); 218 adoptChildExpression(children[c]); 219 if (children[c] instanceof Block) { 220 nested = true; 221 } else if (children[c] instanceof EmptySequence) { 222 nested = true; 223 } 224 } 225 } 226 if (nested) { 227 List list = new ArrayList(children.length*2); 228 flatten(list); 229 children = new Expression[list.size()]; 230 for (int i=0; i<children.length; i++) { 231 children[i] = (Expression)list.get(i); 232 adoptChildExpression(children[i]); 233 } 234 } 235 if (children.length == 0) { 236 return EmptySequence.getInstance(); 237 } else if (children.length == 1) { 238 return children[0]; 239 } else { 240 return this; 241 } 242 } 243 244 public Expression optimize(Optimizer opt, StaticContext env, ItemType contextItemType) throws XPathException { 245 if (children != null) { 246 for (int c=0; c<children.length; c++) { 247 children[c] = children[c].optimize(opt, env, contextItemType); 248 adoptChildExpression(children[c]); 249 } 250 } 251 return this; 252 } 253 254 255 256 261 262 protected void promoteInst(PromotionOffer offer) throws XPathException { 263 if (children != null) { 264 for (int c=0; c<children.length; c++) { 265 children[c] = doPromotion(children[c], offer); 266 } 267 } 268 } 269 270 277 278 public void checkPermittedContents(SchemaType parentType, StaticContext env, boolean whole) throws XPathException { 279 if (children != null) { 280 for (int c=0; c<children.length; c++) { 281 children[c].checkPermittedContents(parentType, env, false); 282 } 283 } 284 } 285 286 293 294 public void display(int level, NamePool pool, PrintStream out) { 295 if (children != null) { 296 displayChildren(children, level+1, pool, out); 297 } 298 } 299 300 303 304 public static void displayChildren(Expression[] children, int level, NamePool pool, PrintStream out) { 305 if (children != null) { 306 for (int c=0; c<children.length; c++) { 307 children[c].display(level+1, pool, out); 308 } 309 } 310 } 311 312 313 public TailCall processLeavingTail(XPathContext context) throws XPathException { 314 315 if (children==null) { 316 return null; 317 } 318 319 TailCall tc = null; 320 for (int i=0; i<children.length; i++) { 321 try { 322 if (children[i] instanceof TailCallReturner) { 323 tc = ((TailCallReturner)children[i]).processLeavingTail(context); 324 } else { 325 children[i].process(context); 326 tc = null; 327 } 328 } catch (DynamicError e) { 329 if (e.getXPathContext() == null) { 330 e.setXPathContext(context); 331 } 332 if (e.getLocator()==null) { 333 e.setLocator(ExpressionTool.getLocator(children[i])); 334 } 335 throw e; 336 } 337 } 338 return tc; 339 } 340 341 346 347 public int getImplementationMethod() { 348 return ITERATE_METHOD | PROCESS_METHOD; 349 } 350 351 354 355 public SequenceIterator iterate(XPathContext context) throws XPathException { 356 if (children==null || children.length == 0) { 357 return EmptyIterator.getInstance(); 358 } else if (children.length == 1) { 359 return children[0].iterate(context); 360 } else { 361 return new BlockIterator(context); 362 } 363 } 364 365 369 370 private class BlockIterator implements SequenceIterator { 371 372 private int i = 0; 373 private SequenceIterator child; 374 private XPathContext context; 375 private Item current; 376 private int position = 0; 377 378 public BlockIterator(XPathContext context) { 379 this.context = context; 380 } 381 382 389 390 public Item next() throws XPathException { 391 if (position < 0) { 392 return null; 393 } 394 while (true) { 395 if (child == null) { 396 child = children[i++].iterate(context); 397 } 398 current = child.next(); 399 if (current != null) { 400 position++; 401 return current; 402 } 403 child = null; 404 if (i >= children.length) { 405 current = null; 406 position = -1; 407 return null; 408 } 409 } 410 } 411 412 421 422 public Item current() { 423 return current; 424 } 425 426 434 435 public int position() { 436 return position; 437 } 438 439 448 449 public SequenceIterator getAnother() throws XPathException { 450 return new BlockIterator(context); 451 } 452 453 462 463 public int getProperties() { 464 return 0; 465 } 466 } 467 } 468 | Popular Tags |