1 package net.sf.saxon.sort; 2 3 import net.sf.saxon.expr.Expression; 4 import net.sf.saxon.expr.LastPositionFinder; 5 import net.sf.saxon.expr.XPathContext; 6 import net.sf.saxon.om.Item; 7 import net.sf.saxon.om.ListIterator; 8 import net.sf.saxon.om.SequenceIterator; 9 import net.sf.saxon.om.LookaheadIterator; 10 import net.sf.saxon.trace.Location; 11 import net.sf.saxon.trans.XPathException; 12 import net.sf.saxon.value.AtomicValue; 13 14 import java.util.ArrayList ; 15 import java.util.Comparator ; 16 import java.util.HashMap ; 17 import java.util.List ; 18 19 33 34 public class GroupByIterator implements GroupIterator, LastPositionFinder, LookaheadIterator { 35 36 43 private SequenceIterator population; 44 private Expression keyExpression; 45 private Comparator collator; 46 private XPathContext keyContext; 47 private int position = 0; 48 49 private ArrayList groups = new ArrayList (40); 53 54 private ArrayList groupKeys = new ArrayList (40); 57 58 private ArrayList initialItems = new ArrayList (40); 61 62 private AtomicSortComparer comparer; 64 65 66 74 75 public GroupByIterator(SequenceIterator population, Expression keyExpression, 76 XPathContext keyContext, Comparator collator) 77 throws XPathException { 78 this.population = population; 79 this.keyExpression = keyExpression; 80 this.keyContext = keyContext; 81 this.collator = collator; 82 this.comparer = new AtomicSortComparer(collator, keyContext); 83 buildIndexedGroups(); 84 } 85 86 91 92 private void buildIndexedGroups() throws XPathException { 93 HashMap index = new HashMap (40); 94 XPathContext c2 = keyContext.newMinorContext(); 95 c2.setCurrentIterator(population); 96 c2.setOriginatingConstructType(Location.GROUPING_KEY); 97 while (true) { 98 Item item = population.next(); 99 if (item==null) { 100 break; 101 } 102 SequenceIterator keys = keyExpression.iterate(c2); 103 boolean firstKey = true; 104 while (true) { 105 AtomicValue key = (AtomicValue) keys.next(); 106 if (key==null) { 107 break; 108 } 109 AtomicSortComparer.ComparisonKey comparisonKey = comparer.getComparisonKey(key); 110 ArrayList g = (ArrayList ) index.get(comparisonKey); 111 if (g == null) { 112 ArrayList newGroup = new ArrayList (20); 113 newGroup.add(item); 114 groups.add(newGroup); 115 groupKeys.add(key); 116 initialItems.add(item); 117 index.put(comparisonKey, newGroup); 118 } else { 119 if (firstKey) { 120 g.add(item); 121 } else { 122 if (g.get(g.size() - 1) != item) { 127 g.add(item); 128 } 129 } 130 } 131 firstKey = false; 132 } 133 } 134 } 135 136 140 141 public AtomicValue getCurrentGroupingKey() { 142 return (AtomicValue)groupKeys.get(position-1); 143 } 144 145 149 150 public SequenceIterator iterateCurrentGroup() { 151 return new ListIterator((ArrayList )groups.get(position-1)); 152 } 153 154 158 159 public List getCurrentGroup() { 160 return (ArrayList )groups.get(position-1); 161 } 162 163 public boolean hasNext() { 164 return position < groups.size(); 165 } 166 167 public Item next() throws XPathException { 168 if (position < groups.size()) { 169 position++; 170 return current(); 171 } else { 172 position = -1; 173 return null; 174 } 175 } 176 177 public Item current() { 178 if (position < 1) { 179 return null; 180 } 181 return (Item)((ArrayList )groups.get(position-1)).get(0); 183 } 184 185 public int position() { 186 return position; 187 } 188 189 public SequenceIterator getAnother() throws XPathException { 190 XPathContext c2 = keyContext.newMinorContext(); 191 c2.setOriginatingConstructType(Location.GROUPING_KEY); 192 return new GroupByIterator(population.getAnother(), keyExpression, c2, collator); 193 } 194 195 204 205 public int getProperties() { 206 return LAST_POSITION_FINDER | LOOKAHEAD; 207 } 208 209 212 213 public int getLastPosition() throws XPathException { 214 return groups.size(); 215 } 216 217 } 218 219 220 | Popular Tags |