1 package net.sf.saxon.sort; 2 import net.sf.saxon.expr.LastPositionFinder; 3 import net.sf.saxon.expr.XPathContext; 4 import net.sf.saxon.om.Item; 5 import net.sf.saxon.om.SequenceIterator; 6 import net.sf.saxon.trace.Location; 7 import net.sf.saxon.trans.DynamicError; 8 import net.sf.saxon.trans.XPathException; 9 10 import java.util.Comparator ; 11 12 15 16 public class SortedIterator implements SequenceIterator, LastPositionFinder, Sortable { 17 18 protected SequenceIterator base; 20 21 protected FixedSortKeyDefinition[] sortkeys; 23 24 protected int recordSize; 29 protected Object [] nodeKeys; 30 31 protected int count = -1; 33 34 protected int index = 0; 36 37 protected XPathContext context; 39 private Comparator [] keyComparers; 40 41 private SortedIterator(){} 42 43 public SortedIterator(XPathContext context, SequenceIterator base, 44 FixedSortKeyDefinition[] sortkeys) 45 throws XPathException { 46 this.context = context.newMinorContext(); 47 this.context.setOriginatingConstructType(Location.SORT_KEY); 48 this.context.setCurrentIterator(base); 49 this.base = base; 50 this.sortkeys = sortkeys; 51 recordSize = sortkeys.length + 2; 52 53 keyComparers = new Comparator [sortkeys.length]; 54 for (int i=0; i<sortkeys.length; i++) { 55 keyComparers[i] = sortkeys[i].getComparer(context); 56 } 57 58 } 61 62 65 66 public Item next() throws XPathException { 67 if (index < 0) { 68 return null; 69 } 70 if (count<0) { 71 doSort(); 72 } 73 if (index < count) { 74 return (Item)nodeKeys[(index++)*recordSize]; 75 } else { 76 index = -1; 77 return null; 78 } 79 } 80 81 public Item current() { 82 if (index < 1) { 83 return null; 84 } 85 return (Item)nodeKeys[(index-1)*recordSize]; 86 } 87 88 public int position() { 89 return index; 90 } 91 92 public int getLastPosition() throws XPathException { 93 if (count<0) { 94 doSort(); 95 } 96 return count; 97 } 98 99 public SequenceIterator getAnother() throws XPathException { 100 if (count<0) { 103 doSort(); 104 } 105 SortedIterator s = new SortedIterator(); 106 s.base = base.getAnother(); 108 s.sortkeys = sortkeys; 109 s.recordSize = recordSize; 110 s.nodeKeys = nodeKeys; 111 s.count = count; 112 s.context = context; 113 s.keyComparers = keyComparers; 114 s.index = 0; 116 return s; 117 } 118 119 128 129 public int getProperties() { 130 return LAST_POSITION_FINDER; 131 } 132 133 protected void buildArray() throws XPathException { 134 int allocated; 135 if ((base.getProperties() & SequenceIterator.LAST_POSITION_FINDER) != 0) { 136 allocated = ((LastPositionFinder)base).getLastPosition(); 137 } else { 138 allocated = 100; 139 } 140 141 nodeKeys = new Object [allocated * recordSize]; 142 count = 0; 143 144 XPathContext c2 = context; 145 146 148 while (true) { 149 Item item = base.next(); 150 if (item == null) { 151 break; 152 } 153 if (count==allocated) { 154 allocated *= 2; 155 Object [] nk2 = new Object [allocated * recordSize]; 156 System.arraycopy(nodeKeys, 0, nk2, 0, count * recordSize); 157 nodeKeys = nk2; 158 } 159 int k = count*recordSize; 160 nodeKeys[k] = item; 161 for (int n=0; n<sortkeys.length; n++) { 164 nodeKeys[k+n+1] = sortkeys[n].getSortKey().evaluateItem(c2); 165 } 166 nodeKeys[k+sortkeys.length+1] = new Integer (count); 168 count++; 169 } 170 } 171 172 private void doSort() throws XPathException { 173 buildArray(); 174 if (count<2) return; 175 176 178 try { 180 GenericSorter.quickSort(0, count, this); 181 } catch (ClassCastException e) { 182 DynamicError err = new DynamicError("Non-comparable types found while sorting: " + e.getMessage()); 183 err.setErrorCode("XPTY0004"); 184 throw err; 186 } 187 } 189 190 194 195 public int compare(int a, int b) { 196 int a1 = a*recordSize + 1; 197 int b1 = b*recordSize + 1; 198 for (int i=0; i<sortkeys.length; i++) { 199 int comp; 200 if (nodeKeys[a1+i] == null) { 202 comp = (nodeKeys[b1+i]==null ? 0 : (sortkeys[i].getEmptyFirst() ? -1 : +1)); 204 } else if (nodeKeys[b1+i]==null) { 205 comp = (sortkeys[i].getEmptyFirst() ? +1 : -1); 207 } else { 208 comp = keyComparers[i].compare(nodeKeys[a1+i], nodeKeys[b1+i]); 209 } 210 if (comp != 0) { 211 return comp; 213 } 214 } 215 216 218 return ((Integer )nodeKeys[a1+sortkeys.length]).intValue() - 219 ((Integer )nodeKeys[b1+sortkeys.length]).intValue(); 220 } 221 222 225 226 public void swap(int a, int b) { 227 int a1 = a*recordSize; 228 int b1 = b*recordSize; 229 for (int i=0; i<recordSize; i++) { 230 Object temp = nodeKeys[a1+i]; 231 nodeKeys[a1+i] = nodeKeys[b1+i]; 232 nodeKeys[b1+i] = temp; 233 } 234 } 235 236 } 237 238 | Popular Tags |