48
48
import antlr .RecognitionException ;
49
49
import antlr .TokenStreamException ;
50
50
import antlr .collections .AST ;
51
+ import com .evolvedbinary .j8cu .list .linked .BoundedDoublyLinkedList ;
52
+ import com .evolvedbinary .j8cu .list .linked .OrderedDoublyLinkedList ;
51
53
import org .exist .EXistException ;
52
54
import org .exist .numbering .NodeId ;
53
55
import org .exist .security .Subject ;
54
56
import org .exist .storage .BrokerPool ;
55
57
import org .exist .storage .DBBroker ;
56
- import org .exist .util .OrderedLinkedList ;
57
58
import org .exist .xquery .*;
58
59
import org .exist .xquery .parser .XQueryLexer ;
59
60
import org .exist .xquery .parser .XQueryParser ;
64
65
import org .w3c .dom .Node ;
65
66
import org .w3c .dom .NodeList ;
66
67
68
+ import javax .annotation .Nullable ;
67
69
import java .io .StringReader ;
68
- import java .util .Iterator ;
69
- import java . util . NoSuchElementException ;
70
- import java . util . Optional ;
70
+ import java .util .* ;
71
+
72
+ import static com . evolvedbinary . j8cu . list . linked . Bounded . bound ;
71
73
72
74
73
75
public class SortedNodeSet extends AbstractNodeSet {
74
76
75
- private final OrderedLinkedList list = new OrderedLinkedList ( );
77
+ private final BoundedDoublyLinkedList < IteratorItem > list = bound ( new OrderedDoublyLinkedList < IteratorItem >(), Long . MAX_VALUE );
76
78
77
79
private final String sortExpr ;
78
80
private final BrokerPool pool ;
@@ -86,7 +88,7 @@ public SortedNodeSet(final BrokerPool pool, final Subject user, final String sor
86
88
87
89
@ Override
88
90
public boolean isEmpty () {
89
- return list .size () == 0 ;
91
+ return list .isEmpty () ;
90
92
}
91
93
92
94
@ Override
@@ -120,37 +122,64 @@ public void addAll(final NodeSet other) {
120
122
}
121
123
final AST ast = parser .getAST ();
122
124
LOG .debug ("generated AST: {}" , ast .toStringTree ());
123
- final PathExpr expr = new PathExpr (context );
124
- treeParser .xpath (ast , expr );
125
- if (treeParser .foundErrors ()) {
126
- LOG .debug (treeParser .getErrorMessage ());
127
- }
128
- expr .analyze (new AnalyzeContextInfo ());
129
- for (final SequenceIterator i = other .iterate (); i .hasNext (); ) {
130
- final NodeProxy p = (NodeProxy ) i .nextItem ();
131
- final IteratorItem item = new IteratorItem (p , expr );
132
- list .add (item );
125
+ final PathExpr sortExpression = new PathExpr (context );
126
+ try {
127
+ treeParser .xpath (ast , sortExpression );
128
+ if (treeParser .foundErrors ()) {
129
+ LOG .debug (treeParser .getErrorMessage ());
130
+ }
131
+ sortExpression .analyze (new AnalyzeContextInfo ());
132
+ for (final SequenceIterator i = other .iterate (); i .hasNext (); ) {
133
+ final NodeProxy p = (NodeProxy ) i .nextItem ();
134
+ final IteratorItem item = createIteratorItem (sortExpression , p );
135
+ list .add (item );
136
+ }
137
+ } finally {
138
+ sortExpression .getContext ().runCleanupTasks ();
139
+ sortExpression .getContext ().reset ();
133
140
}
134
141
} catch (final RecognitionException | TokenStreamException re ) {
135
142
LOG .debug (re ); //TODO : throw exception ! -pb
136
143
} catch (final EXistException | XPathException e ) {
137
- LOG .debug ("Exception during sort" , e ); //TODO : throw exception ! -pb
144
+ LOG .debug ("Exception during sort: " + e . getMessage () , e ); //TODO : throw exception ! -pb
138
145
}
139
146
LOG .debug ("sort-expression found {} in {}ms." , list .size (), System .currentTimeMillis () - start );
140
147
}
141
148
149
+ private IteratorItem createIteratorItem (final Expression sortExpression , final NodeProxy nodeProxy ) throws XPathException {
150
+ final Sequence seq = sortExpression .eval (nodeProxy , null );
151
+
152
+ // copy string values of items into an array
153
+ int sbCapacity = 0 ;
154
+ final String [] strings = new String [seq .getItemCount ()];
155
+ for (int i = 0 ; i < strings .length ; i ++) {
156
+ final String strItem = seq .itemAt (i ).getStringValue ().toUpperCase ();
157
+ sbCapacity += strItem .length ();
158
+ strings [i ] = strItem ;
159
+ }
160
+
161
+ // sort and then concatenate strings
162
+ Arrays .sort (strings );
163
+ final StringBuilder buf = new StringBuilder (sbCapacity );
164
+ for (int i = 0 ; i < strings .length ; i ++) {
165
+ buf .append (strings [i ]);
166
+ }
167
+
168
+ return new IteratorItem (nodeProxy , buf .toString ());
169
+ }
170
+
142
171
public void addAll (final NodeList other ) {
143
- if (!(other instanceof NodeSet )) {
172
+ if (!(other instanceof NodeSet )) {
144
173
throw new RuntimeException ("not implemented!" );
145
174
}
146
175
addAll ((NodeSet ) other );
147
176
}
148
177
149
178
@ Override
150
179
public boolean contains (final NodeProxy proxy ) {
151
- for (final Iterator < IteratorItem > i = list . iterator (); i . hasNext (); ) {
152
- final NodeProxy p = ( i . next ()) .proxy ;
153
- if (p .compareTo (proxy ) == 0 ) {
180
+ for (final IteratorItem iteratorItem : list ) {
181
+ final NodeProxy p = iteratorItem .proxy ;
182
+ if (p .compareTo (proxy ) == 0 ) {
154
183
return true ;
155
184
}
156
185
}
@@ -159,8 +188,8 @@ public boolean contains(final NodeProxy proxy) {
159
188
160
189
@ Override
161
190
public boolean containsReference (final Item item ) {
162
- for (final Iterator < IteratorItem > i = list . iterator (); i . hasNext (); ) {
163
- final NodeProxy p = ( i . next ()) .proxy ;
191
+ for (final IteratorItem iteratorItem : list ) {
192
+ final NodeProxy p = iteratorItem .proxy ;
164
193
if (p == item ) {
165
194
return true ;
166
195
}
@@ -170,8 +199,8 @@ public boolean containsReference(final Item item) {
170
199
171
200
@ Override
172
201
public boolean contains (final Item item ) {
173
- for (final Iterator < IteratorItem > i = list . iterator (); i . hasNext (); ) {
174
- final NodeProxy p = ( i . next ()) .proxy ;
202
+ for (final IteratorItem iteratorItem : list ) {
203
+ final NodeProxy p = iteratorItem .proxy ;
175
204
if (p .equals (item )) {
176
205
return true ;
177
206
}
@@ -181,15 +210,15 @@ public boolean contains(final Item item) {
181
210
182
211
@ Override
183
212
public NodeProxy get (final int pos ) {
184
- final IteratorItem item = ( IteratorItem ) list .get (pos );
213
+ final IteratorItem item = list .get (pos );
185
214
return item == null ? null : item .proxy ;
186
215
}
187
216
188
217
public NodeProxy get (final DocumentImpl doc , final NodeId nodeId ) {
189
218
final NodeProxy proxy = new NodeProxy (null , doc , nodeId );
190
- for (final Iterator < IteratorItem > i = list . iterator (); i . hasNext (); ) {
191
- final NodeProxy p = ( i . next ()) .proxy ;
192
- if (p .compareTo (proxy ) == 0 ) {
219
+ for (final IteratorItem iteratorItem : list ) {
220
+ final NodeProxy p = iteratorItem .proxy ;
221
+ if (p .compareTo (proxy ) == 0 ) {
193
222
return p ;
194
223
}
195
224
}
@@ -198,9 +227,9 @@ public NodeProxy get(final DocumentImpl doc, final NodeId nodeId) {
198
227
199
228
@ Override
200
229
public NodeProxy get (final NodeProxy proxy ) {
201
- for (final Iterator < IteratorItem > i = list . iterator (); i . hasNext (); ) {
202
- final NodeProxy p = ( i . next ()) .proxy ;
203
- if (p .compareTo (proxy ) == 0 ) {
230
+ for (final IteratorItem iteratorItem : list ) {
231
+ final NodeProxy p = iteratorItem .proxy ;
232
+ if (p .compareTo (proxy ) == 0 ) {
204
233
return p ;
205
234
}
206
235
}
@@ -209,7 +238,7 @@ public NodeProxy get(final NodeProxy proxy) {
209
238
210
239
@ Override
211
240
public int getLength () {
212
- return list .size ();
241
+ return ( int ) list .size ();
213
242
}
214
243
215
244
@ Override
@@ -219,15 +248,21 @@ public long getItemCountLong() {
219
248
220
249
@ Override
221
250
public Node item (final int pos ) {
222
- final NodeProxy p = ((IteratorItem ) list .get (pos )).proxy ;
223
- return p == null ? null : p .getNode ();
251
+ final IteratorItem iteratorItem = list .get (pos );
252
+ if (iteratorItem != null ) {
253
+ final NodeProxy p = iteratorItem .proxy ;
254
+ if (p != null ) {
255
+ return p .getOwnerDocument ().getNode (p );
256
+ }
257
+ }
258
+ return null ;
224
259
}
225
260
226
261
//TODO : evaluate both semantics (item/itemAt)
227
262
@ Override
228
263
public Item itemAt (final int pos ) {
229
- final NodeProxy p = (( IteratorItem ) list .get (pos )). proxy ;
230
- return p == null ? null : p ;
264
+ final IteratorItem iteratorItem = list .get (pos );
265
+ return iteratorItem == null ? null : iteratorItem . proxy ;
231
266
}
232
267
233
268
@ Override
@@ -245,101 +280,89 @@ public SequenceIterator unorderedIterator() {
245
280
return new SortedNodeSetIterator (list .iterator ());
246
281
}
247
282
248
- private static final class SortedNodeSetIterator implements NodeSetIterator , SequenceIterator {
249
-
283
+ private static class SortedNodeSetIterator implements NodeSetIterator , SequenceIterator {
250
284
private final Iterator <IteratorItem > ii ;
251
285
252
286
public SortedNodeSetIterator (final Iterator <IteratorItem > i ) {
253
287
ii = i ;
254
288
}
255
289
256
- public final boolean hasNext () {
290
+ public boolean hasNext () {
257
291
return ii .hasNext ();
258
292
}
259
293
260
294
@ Override
261
- public final NodeProxy next () {
262
- if (!ii .hasNext ()) {
295
+ public NodeProxy next () {
296
+ if (!ii .hasNext ()) {
263
297
throw new NoSuchElementException ();
264
298
} else {
265
299
return ii .next ().proxy ;
266
300
}
267
301
}
268
302
269
303
@ Override
270
- public final void remove () {
304
+ public void remove () {
271
305
throw new UnsupportedOperationException ();
272
306
}
273
307
274
308
@ Override
275
- public final NodeProxy peekNode () {
309
+ public NodeProxy peekNode () {
276
310
return null ;
277
311
}
278
312
279
313
@ Override
280
- public final Item nextItem () {
281
- if (!ii .hasNext ()) {
314
+ public Item nextItem () {
315
+ if (!ii .hasNext ()) {
282
316
return null ;
283
317
} else {
284
318
return ii .next ().proxy ;
285
319
}
286
320
}
287
321
288
322
@ Override
289
- public final void setPosition (final NodeProxy proxy ) {
323
+ public void setPosition (final NodeProxy proxy ) {
290
324
throw new UnsupportedOperationException ("NodeSetIterator.setPosition() is not supported by SortedNodeSetIterator" );
291
325
}
292
326
}
293
327
294
- private static final class IteratorItem extends OrderedLinkedList . Node {
328
+ private static class IteratorItem implements Comparable < IteratorItem > {
295
329
private final NodeProxy proxy ;
296
- private String value = null ;
330
+ private @ Nullable final String value ;
297
331
298
- public IteratorItem (final NodeProxy proxy , final PathExpr expr ) {
332
+ public IteratorItem (final NodeProxy proxy , final String value ) {
299
333
this .proxy = proxy ;
300
- try {
301
- final Sequence seq = expr .eval (proxy , null );
302
- final StringBuilder buf = new StringBuilder ();
303
- final OrderedLinkedList strings = new OrderedLinkedList ();
304
- Item item ;
305
- for (final SequenceIterator i = seq .iterate (); i .hasNext (); ) {
306
- item = i .nextItem ();
307
- strings .add (new OrderedLinkedList .SimpleNode (item .getStringValue ().toUpperCase ()));
308
- }
309
- for (final Iterator <OrderedLinkedList .SimpleNode > j = strings .iterator (); j .hasNext (); ) {
310
- buf .append ((j .next ()).getData ());
311
- }
312
- value = buf .toString ();
313
- } catch (final XPathException e ) {
314
- LOG .warn (e .getMessage (), e ); //TODO : throw exception ! -pb
315
- } finally {
316
- expr .getContext ().runCleanupTasks ();
317
- expr .getContext ().reset ();
318
- }
334
+ this .value = value ;
319
335
}
320
336
321
337
@ Override
322
- public int compareTo (final OrderedLinkedList .Node other ) {
323
- final IteratorItem o = (IteratorItem ) other ;
324
- if (value == null ) {
325
- return o .value == null ? Constants .EQUAL : Constants .SUPERIOR ;
326
- } else if (o .value == null ) {
338
+ public int compareTo (final IteratorItem other ) {
339
+ if (value == null ) {
340
+ return other .value == null ? Constants .EQUAL : Constants .SUPERIOR ;
341
+ } else if (other .value == null ) {
327
342
return Constants .INFERIOR ;
328
343
} else {
329
- return value .compareTo (o .value );
344
+ return value .compareTo (other .value );
330
345
}
331
346
}
332
347
333
348
@ Override
334
- public boolean equals (final OrderedLinkedList .Node other ) {
335
- final IteratorItem o = (IteratorItem ) other ;
336
- return value .equals (o .value );
349
+ public boolean equals (final Object other ) {
350
+ if (!(other instanceof IteratorItem )) {
351
+ return false ;
352
+ }
353
+
354
+ final IteratorItem otherIteratorItem = (IteratorItem ) other ;
355
+ return Objects .equals (value , otherIteratorItem .value );
356
+ }
357
+
358
+ @ Override
359
+ public int hashCode () {
360
+ return Objects .hashCode (value );
337
361
}
338
362
}
339
363
340
364
@ Override
341
365
public void add (final NodeProxy proxy ) {
342
366
LOG .info ("Called SortedNodeSet.add()" );
343
367
}
344
-
345
368
}
0 commit comments