1 package net.sf.saxon.instruct; 2 3 import net.sf.saxon.Controller; 4 import net.sf.saxon.expr.*; 5 import net.sf.saxon.om.Item; 6 import net.sf.saxon.om.NamePool; 7 import net.sf.saxon.om.SequenceIterator; 8 import net.sf.saxon.pattern.PatternSponsor; 9 import net.sf.saxon.sort.*; 10 import net.sf.saxon.style.StandardNames; 11 import net.sf.saxon.trace.TraceListener; 12 import net.sf.saxon.trans.XPathException; 13 import net.sf.saxon.type.ItemType; 14 import net.sf.saxon.type.SchemaType; 15 import net.sf.saxon.value.EmptySequence; 16 import net.sf.saxon.value.Value; 17 18 import java.io.PrintStream ; 19 import java.util.ArrayList ; 20 import java.util.Comparator ; 21 import java.util.Iterator ; 22 23 27 28 public class ForEachGroup extends Instruction implements MappingFunction { 29 30 public static final int GROUP_BY = 0; 31 public static final int GROUP_ADJACENT = 1; 32 public static final int GROUP_STARTING = 2; 33 public static final int GROUP_ENDING = 3; 34 35 36 private Expression select; 37 private Expression action; 38 private byte algorithm; 39 private Expression key; private Comparator collator = null; 41 private SortKeyDefinition[] sortKeys = null; 42 43 public ForEachGroup(Expression select, 44 Expression action, 45 byte algorithm, 46 Expression key, 47 Comparator collator, 48 SortKeyDefinition[] sortKeys) { 49 this.select = select; 50 this.action = action; 51 this.algorithm = algorithm; 52 this.key = key; 53 this.collator = collator; 54 this.sortKeys = sortKeys; 55 Iterator kids = iterateSubExpressions(); 56 while (kids.hasNext()) { 57 Expression child = (Expression)kids.next(); 58 adoptChildExpression(child); 59 } 60 } 61 62 65 66 public int getInstructionNameCode() { 67 return StandardNames.XSL_FOR_EACH_GROUP; 68 } 69 70 73 74 public Expression getActionExpression() { 75 return action; 76 } 77 78 86 87 public Expression simplify(StaticContext env) throws XPathException { 88 select = select.simplify(env); 89 action = action.simplify(env); 90 key = key.simplify(env); 91 return this; 92 } 93 94 public Expression typeCheck(StaticContext env, ItemType contextItemType) throws XPathException { 95 select = select.typeCheck(env, contextItemType); 96 action = action.typeCheck(env, select.getItemType()); 97 key = key.typeCheck(env, select.getItemType()); 98 adoptChildExpression(select); 99 adoptChildExpression(action); 100 adoptChildExpression(key); 101 if (select instanceof EmptySequence) { 102 return EmptySequence.getInstance(); 103 } 104 if (action instanceof EmptySequence) { 105 return EmptySequence.getInstance(); 106 } 107 return this; 108 } 109 110 public Expression optimize(Optimizer opt, StaticContext env, ItemType contextItemType) throws XPathException { 111 select = select.optimize(opt, env, contextItemType); 112 action = action.optimize(opt, env, select.getItemType()); 113 key = key.optimize(opt, env, select.getItemType()); 114 adoptChildExpression(select); 115 adoptChildExpression(action); 116 adoptChildExpression(key); 117 if (select instanceof EmptySequence) { 118 return EmptySequence.getInstance(); 119 } 120 if (action instanceof EmptySequence) { 121 return EmptySequence.getInstance(); 122 } 123 return this; 124 } 125 126 131 132 public ItemType getItemType() { 133 return action.getItemType(); 134 } 135 136 145 146 public int computeDependencies() { 147 int dependencies = 0; 150 dependencies |= select.getDependencies(); 151 dependencies |= key.getDependencies() & ~StaticProperty.DEPENDS_ON_FOCUS; 152 dependencies |= (action.getDependencies() 153 &~ (StaticProperty.DEPENDS_ON_FOCUS | StaticProperty.DEPENDS_ON_CURRENT_GROUP)); 154 if (sortKeys != null) { 155 for (int i = 0; i < sortKeys.length; i++) { 156 dependencies |= (sortKeys[i].getSortKey().getDependencies() &~ StaticProperty.DEPENDS_ON_FOCUS); 157 Expression e = sortKeys[i].getCaseOrder(); 158 if (e != null && !(e instanceof Value)) { 159 dependencies |= (e.getDependencies()); 160 } 161 e = sortKeys[i].getDataTypeExpression(); 162 if (e != null && !(e instanceof Value)) { 163 dependencies |= (e.getDependencies()); 164 } 165 e = sortKeys[i].getLanguage(); 166 if (e != null && !(e instanceof Value)) { 167 dependencies |= (e.getDependencies()); 168 } 169 } 170 } 171 return dependencies; 172 } 173 174 179 180 public final boolean createsNewNodes() { 181 int props = action.getSpecialProperties(); 182 return ((props & StaticProperty.NON_CREATIVE) == 0); 183 } 184 185 191 192 protected void promoteInst(PromotionOffer offer) throws XPathException { 193 select = doPromotion(select, offer); 194 action = doPromotion(action, offer); 195 key = doPromotion(key, offer); 196 } 197 198 203 204 public Iterator iterateSubExpressions() { 205 ArrayList list = new ArrayList (3); 206 list.add(select); 207 list.add(action); 208 list.add(key); 209 if (sortKeys != null) { 210 for (int i = 0; i < sortKeys.length; i++) { 211 list.add(sortKeys[i].getSortKey()); 212 Expression e = sortKeys[i].getOrder(); 213 if (e != null && !(e instanceof Value)) { 214 list.add(e); 215 } 216 e = sortKeys[i].getCaseOrder(); 217 if (e != null && !(e instanceof Value)) { 218 list.add(e); 219 } 220 e = sortKeys[i].getDataTypeExpression(); 221 if (e != null && !(e instanceof Value)) { 222 list.add(e); 223 } 224 e = sortKeys[i].getLanguage(); 225 if (e != null && !(e instanceof Value)) { 226 list.add(e); 227 } 228 } 229 } 230 return list.iterator(); 231 } 232 233 240 241 public void checkPermittedContents(SchemaType parentType, StaticContext env, boolean whole) throws XPathException { 242 action.checkPermittedContents(parentType, env, false); 243 } 244 245 public TailCall processLeavingTail(XPathContext context) throws XPathException { 246 Controller controller = context.getController(); 247 248 GroupIterator groupIterator = getGroupIterator(context); 249 250 XPathContextMajor c2 = context.newContext(); 251 c2.setOrigin(this); 252 c2.setCurrentIterator(groupIterator); 253 c2.setCurrentGroupIterator(groupIterator); 254 c2.setCurrentTemplate(null); 255 256 if (controller.isTracing()) { 257 TraceListener listener = controller.getTraceListener(); 258 while (true) { 259 Item item = groupIterator.next(); 260 if (item == null) { 261 break; 262 } 263 listener.startCurrentItem(item); 264 action.process(c2); 265 listener.endCurrentItem(item); 266 } 267 } else { 268 while (true) { 269 Item item = groupIterator.next(); 270 if (item == null) { 271 break; 272 } 273 action.process(c2); 274 } 275 } 276 277 return null; 278 } 279 280 private GroupIterator getGroupIterator(XPathContext context) throws XPathException { 281 SequenceIterator population = select.iterate(context); 282 283 285 GroupIterator groupIterator; 286 switch (algorithm) { 287 case GROUP_BY: 288 { 289 XPathContext c2 = context.newMinorContext(); 290 c2.setOrigin(this); 291 c2.setCurrentIterator(population); 292 groupIterator = new GroupByIterator(population, key, c2, collator); 293 break; 294 } 295 case GROUP_ADJACENT: 296 { 297 groupIterator = new GroupAdjacentIterator(population, key, context, collator); 298 break; 299 } 300 case GROUP_STARTING: 301 groupIterator = new GroupStartingIterator(population, 302 ((PatternSponsor)key).getPattern(), 303 context); 304 break; 305 case GROUP_ENDING: 306 groupIterator = new GroupEndingIterator(population, 307 ((PatternSponsor)key).getPattern(), 308 context); 309 break; 310 default: 311 throw new AssertionError ("Unknown grouping algorithm"); 312 } 313 314 315 317 if (sortKeys != null) { 318 FixedSortKeyDefinition[] reducedSortKeys = new FixedSortKeyDefinition[sortKeys.length]; 320 XPathContext xpc = context.newMinorContext(); 321 for (int s = 0; s < sortKeys.length; s++) { 322 reducedSortKeys[s] = sortKeys[s].reduce(xpc); 323 } 324 groupIterator = new SortedGroupIterator(xpc, 325 groupIterator, 326 reducedSortKeys, 327 this); 328 } 329 return groupIterator; 330 } 331 332 348 349 public SequenceIterator iterate(XPathContext context) throws XPathException { 350 GroupIterator master = getGroupIterator(context); 351 XPathContextMajor c2 = context.newContext(); 352 c2.setOrigin(this); 353 c2.setCurrentIterator(master); 354 c2.setCurrentGroupIterator(master); 355 c2.setCurrentTemplate(null); 356 return new MappingIterator(master, this, c2); 357 } 358 359 370 371 public Object map(Item item, XPathContext context) throws XPathException { 372 return action.iterate(context); 373 } 374 375 382 383 public void display(int level, NamePool pool, PrintStream out) { 384 out.println(ExpressionTool.indent(level) + "for-each-group"); 385 out.println(ExpressionTool.indent(level) + "select"); 386 select.display(level + 1, pool, out); 387 out.println(ExpressionTool.indent(level) + "return"); 388 action.display(level + 1, pool, out); 389 } 390 } 391 392 | Popular Tags |