1 package com.icl.saxon.expr; 2 import com.icl.saxon.*; 3 import com.icl.saxon.om.*; 4 import com.icl.saxon.sort.*; 5 7 12 13 public final class SortKeyEnumeration 14 implements NodeEnumeration, LastPositionFinder, Sortable { 15 16 17 protected NodeEnumeration base; 19 20 private SortKeyDefinition[] sortkeys; 22 23 private int recordSize; 27 private Object [] nodeKeys; 28 29 private int count = -1; 31 32 private int index = 0; 34 35 private Context context; 37 private Controller controller; 38 private Comparer[] keyComparers; 39 40 public SortKeyEnumeration(Context context, NodeEnumeration _base, 41 SortKeyDefinition[] sortkeys) 42 throws XPathException { 43 this.context = context.newContext(); 44 this.controller = context.getController(); 45 this.base = _base; 46 this.sortkeys = sortkeys; 47 recordSize = sortkeys.length + 1; 48 49 keyComparers = new Comparer[sortkeys.length]; 50 for (int i=0; i<sortkeys.length; i++) { 51 keyComparers[i] = sortkeys[i].getComparer(context); 52 } 53 54 if (!base.isSorted()) { 58 boolean mustBeSorted = false; 59 for (int i=0; i<sortkeys.length; i++) { 60 SortKeyDefinition sk = sortkeys[i]; 61 Expression k = sk.getSortKey(); 62 if ((k.getDependencies() & (Context.POSITION | Context.LAST)) != 0) { 63 mustBeSorted = true; 64 break; 65 } 66 } 67 if (mustBeSorted) { 68 NodeSetExtent nsv = new NodeSetExtent(base, controller); 69 nsv.sort(); 70 base = nsv.enumerate(); 71 } 72 } 73 } 74 75 78 79 public boolean hasMoreElements() { 80 if (count<0) { 81 return base.hasMoreElements(); 82 } else { 83 return index<count; 84 } 85 } 86 87 90 91 public NodeInfo nextElement() throws XPathException { 92 if (count<0) { 93 doSort(); 94 } 95 return (NodeInfo)nodeKeys[(index++)*recordSize]; 96 } 97 98 public boolean isSorted() { 99 return true; 100 } 101 102 public boolean isReverseSorted() { 103 return false; 104 } 105 106 public boolean isPeer() { 107 return base.isPeer(); 108 } 109 110 public int getLastPosition() throws XPathException { 111 if (base instanceof LastPositionFinder && !(base instanceof LookaheadEnumerator)) { 112 return ((LastPositionFinder)base).getLastPosition(); 113 } 114 if (count<0) doSort(); 115 return count; 116 } 117 118 private void buildArray() throws XPathException { 119 int allocated; 120 if (base instanceof LastPositionFinder && !(base instanceof LookaheadEnumerator)) { 121 allocated = ((LastPositionFinder)base).getLastPosition(); 122 context.setLast(allocated); 123 } else { 124 allocated = 100; 125 } 126 nodeKeys = new Object [allocated * recordSize]; 127 count = 0; 128 129 131 while (base.hasMoreElements()) { 132 NodeInfo node = base.nextElement(); 133 if (count==allocated) { 134 allocated *= 2; 135 Object [] nk2 = new Object [allocated * recordSize]; 136 System.arraycopy(nodeKeys, 0, nk2, 0, count * recordSize); 137 nodeKeys = nk2; 138 } 139 context.setCurrentNode(node); 140 context.setContextNode(node); 141 context.setPosition(count+1); 142 143 int k = count*recordSize; 144 nodeKeys[k] = node; 145 for (int n=0; n<sortkeys.length; n++) { 146 nodeKeys[k+n+1] = sortkeys[n].getSortKey().evaluateAsString(context); 147 } 148 count++; 149 } 150 } 152 153 private void diag() { 154 System.err.println("Diagnostic print of keys"); 155 for (int i=0; i<(count*recordSize); i++) { 156 System.err.println(i + " : " + nodeKeys[i]); 157 } 158 } 159 160 161 private void doSort() throws XPathException { 162 buildArray(); 163 if (count<2) return; 164 165 167 QuickSort.sort(this, 0, count-1); 168 } 169 170 174 175 public int compare(int a, int b) { 176 int a1 = a*recordSize + 1; 177 int b1 = b*recordSize + 1; 178 for (int i=0; i<sortkeys.length; i++) { 179 Comparer c = keyComparers[i]; 180 int comp = c.compare(nodeKeys[a1+i], nodeKeys[b1+i]); 181 if (comp!=0) return comp; 182 } 183 return controller.compare( 185 (NodeInfo)nodeKeys[a1-1], 186 (NodeInfo)nodeKeys[b1-1]); 187 } 188 189 192 193 public void swap(int a, int b) { 194 int a1 = a*recordSize; 195 int b1 = b*recordSize; 196 for (int i=0; i<recordSize; i++) { 197 Object temp = nodeKeys[a1+i]; 198 nodeKeys[a1+i] = nodeKeys[b1+i]; 199 nodeKeys[b1+i] = temp; 200 } 201 } 202 203 204 } 205 206 207 | Popular Tags |