1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 package org.modeshape.jdbc.metadata;
25
26 import java.io.ByteArrayInputStream;
27 import java.io.IOException;
28 import java.io.InputStream;
29 import java.math.BigDecimal;
30 import java.sql.ResultSetMetaData;
31 import java.sql.SQLException;
32 import java.util.Calendar;
33 import java.util.Date;
34 import java.util.Iterator;
35 import java.util.List;
36 import java.util.NoSuchElementException;
37
38 import javax.jcr.Binary;
39 import javax.jcr.ItemNotFoundException;
40 import javax.jcr.Node;
41 import javax.jcr.NodeIterator;
42 import javax.jcr.RepositoryException;
43 import javax.jcr.Value;
44 import javax.jcr.ValueFormatException;
45 import javax.jcr.query.Row;
46 import javax.jcr.query.RowIterator;
47
48
49
50
51
52
53
54
55 public class MetaDataQueryResult implements javax.jcr.query.QueryResult {
56
57 private ResultSetMetaData rsmd;
58 private String[] columnNames = null;
59 private List<List<?>> tuplesArray = null;
60
61
62 public static MetaDataQueryResult createResultSet(List<List<?>> records, ResultSetMetaData resultSetMetaData) {
63 MetaDataQueryResult mdqr = new MetaDataQueryResult(records, resultSetMetaData);
64 return mdqr;
65 }
66
67
68 MetaDataQueryResult(List<List<?>> tuples, ResultSetMetaData rsmd) {
69 this.rsmd = rsmd;
70 this.tuplesArray = tuples;
71 getColumnNames();
72 }
73
74 @Override
75 public String[] getColumnNames() {
76 if (columnNames != null) {
77 return columnNames;
78 }
79
80 try {
81 columnNames = new String[rsmd.getColumnCount()];
82 for (int col = 0; col < columnNames.length; col++) {
83 columnNames[col] = rsmd.getColumnName(col + 1);
84 }
85
86 return columnNames;
87 } catch (SQLException sqle) {
88 sqle.printStackTrace();
89
90 }
91 return null;
92 }
93
94 @Override
95 public NodeIterator getNodes() {
96 throw new UnsupportedOperationException();
97 }
98
99 @Override
100 public RowIterator getRows() {
101 RowIterator ri = new QueryResultRowIterator(tuplesArray, columnNames);
102 return ri;
103 }
104
105 public String[] getColumnTypes() {
106 String[] columnTypes = new String[columnNames.length];
107 for (int i = 0; i <= columnNames.length; i++) {
108 try {
109 columnTypes[i] = rsmd.getColumnTypeName(i + 1);
110 } catch (SQLException e) {
111 columnTypes[i] = "NotFound";
112 }
113 }
114 return columnTypes;
115 }
116
117 @Override
118 public String[] getSelectorNames() {
119 throw new UnsupportedOperationException();
120 }
121
122 }
123
124
125
126
127 class QueryResultNodeIterator implements NodeIterator {
128 private final Node[] nodes;
129 private final int size;
130 private long position = 0L;
131
132 protected QueryResultNodeIterator(Node[] nodes) {
133 this.nodes = nodes;
134 this.size = nodes.length;
135 }
136
137
138
139
140
141
142 public Node nextNode() {
143 Node node = nodes[(int) (position)];
144 ++position;
145 return node;
146 }
147
148
149
150
151
152
153 public long getPosition() {
154 return position;
155 }
156
157
158
159
160
161
162 public long getSize() {
163 return size;
164 }
165
166
167
168
169
170
171 public void skip(long skipNum) {
172 for (long i = 0L; i != skipNum; ++i)
173 nextNode();
174 }
175
176
177
178
179
180
181 public boolean hasNext() {
182 return (nodes.length > position);
183 }
184
185
186
187
188
189
190 public Object next() {
191 return nextNode();
192 }
193
194
195
196
197
198
199 public void remove() {
200 throw new UnsupportedOperationException();
201 }
202 }
203
204 class QueryResultRowIterator implements RowIterator {
205 private final Iterator<List<?>> tuples;
206 private long position = 0L;
207 private long numRows;
208 private Row nextRow;
209 private String[] colNames;
210
211 protected QueryResultRowIterator( List<List<?>> tuplesArray,
212 String[] columnNames) {
213 this.tuples = tuplesArray.iterator();
214 this.numRows = tuplesArray.size();
215 this.colNames = columnNames;
216 }
217
218 public boolean hasSelector(String selectorName) {
219 return false;
220 }
221
222
223
224
225
226
227 public Row nextRow() {
228 if (nextRow == null) {
229
230 if (!hasNext()) {
231 throw new NoSuchElementException();
232 }
233 }
234 assert nextRow != null;
235 Row result = nextRow;
236 nextRow = null;
237 position++;
238 return result;
239 }
240
241
242
243
244
245
246 public long getPosition() {
247 return position;
248 }
249
250
251
252
253
254
255 public long getSize() {
256 return numRows;
257 }
258
259
260
261
262
263
264 public void skip(long skipNum) {
265 for (long i = 0L; i != skipNum; ++i) {
266 tuples.next();
267 }
268 position += skipNum;
269 }
270
271
272
273
274
275
276 public boolean hasNext() {
277 if (nextRow != null) {
278 return true;
279 }
280
281 while (tuples.hasNext()) {
282 final List<?> tuple = tuples.next();
283 try {
284
285 nextRow = getNextRow(tuple);
286 if (nextRow != null)
287 return true;
288 } catch (RepositoryException e) {
289
290 }
291 --numRows;
292 }
293 return false;
294 }
295
296
297
298
299
300
301 private Row getNextRow(List<?> tuple) throws RepositoryException {
302 return new QueryResultRow(this, tuple, colNames);
303 }
304
305
306
307
308
309
310 public Object next() {
311 return nextRow();
312 }
313
314
315
316
317
318
319 public void remove() {
320 throw new UnsupportedOperationException();
321 }
322 }
323
324 class QueryResultRow implements Row {
325 protected final QueryResultRowIterator iterator;
326 protected final List<?> tuple;
327 private String[] columnNames = null;
328
329 protected QueryResultRow(QueryResultRowIterator iterator,
330 List<?> tuple, String[] colNames) {
331 this.iterator = iterator;
332 this.tuple = tuple;
333 this.columnNames = colNames;
334 }
335
336
337
338
339
340
341 @Override
342 public Node getNode() throws RepositoryException {
343 throw new UnsupportedOperationException();
344 }
345
346 @Override
347 public Node getNode(String selectorName) throws RepositoryException {
348 throw new UnsupportedOperationException();
349 }
350
351
352
353
354
355
356 @Override
357 public String getPath() throws RepositoryException {
358 throw new UnsupportedOperationException();
359 }
360
361
362
363
364
365
366 @Override
367 public String getPath(String selectorName) throws RepositoryException {
368 throw new UnsupportedOperationException();
369 }
370
371
372
373
374
375
376 @Override
377 public double getScore()
378 throw new UnsupportedOperationException();
379 }
380
381
382
383
384
385
386 @Override
387 public double getScore(String selectorName)
388 throw new UnsupportedOperationException();
389 }
390
391
392
393
394 @Override
395 public Value getValue(String arg0) throws ItemNotFoundException {
396 int pos = getColumnPosition(arg0);
397 if (pos >= 0) {
398 return createValue(tuple.get(pos));
399 }
400
401 throw new ItemNotFoundException("Item " + arg0 + " not found");
402 }
403
404 private int getColumnPosition(String colName) {
405 for (int i = 0; i < columnNames.length; i++) {
406 if (columnNames[i].equals(colName))
407 return i;
408 }
409 return -1;
410
411 }
412
413
414
415
416 @Override
417 public Value[] getValues() throws RepositoryException {
418 Value[] values = new Value[tuple.size()];
419 for (int i = 0; i < values.length; i++) {
420 values[i] = createValue(tuple.get(i));
421
422 }
423 return values;
424 }
425
426 private Value createValue(final Object value) {
427
428 if (value == null)
429 return null;
430
431 Value rtnvalue = new Value() {
432 final Object valueObject = value;
433
434 @Override
435 public boolean getBoolean() throws ValueFormatException,
436 IllegalStateException, RepositoryException {
437 if (value instanceof Boolean) {
438 return ((Boolean) valueObject).booleanValue();
439 }
440 throw new ValueFormatException("Value not a Boolean");
441 }
442
443 @Override
444 public Calendar getDate() throws ValueFormatException,
445 IllegalStateException, RepositoryException {
446 if (value instanceof Date) {
447 Calendar c = Calendar.getInstance();
448 c.setTime((Date) value);
449
450 return c;
451 }
452 throw new ValueFormatException("Value not instance of Date");
453 }
454
455 @Override
456 public double getDouble() throws ValueFormatException,
457 IllegalStateException, RepositoryException {
458 if (value instanceof Double) {
459 return ((Double) valueObject).doubleValue();
460 }
461
462 throw new ValueFormatException("Value not a Double");
463 }
464
465 @Override
466 public long getLong() throws ValueFormatException,
467 IllegalStateException, RepositoryException {
468 if (value instanceof Long) {
469 return ((Long) valueObject).longValue();
470 }
471 throw new ValueFormatException("Value not a Long");
472 }
473
474
475
476
477
478
479 @Override
480 public Binary getBinary() throws RepositoryException {
481 if (value instanceof Binary) {
482 return ((Binary) valueObject);
483 }
484 if (value instanceof byte[]) {
485 final byte[] bytes = (byte[]) value;
486 return new Binary() {
487
488 @Override
489 public void dispose() {
490 }
491
492 @Override
493 public long getSize() {
494 return bytes.length;
495 }
496
497 @Override
498 public InputStream getStream() {
499 return new ByteArrayInputStream(bytes);
500 }
501
502 @Override
503 public int read(byte[] b, long position)
504 throws IOException {
505 if (getSize() <= position)
506 return -1;
507 InputStream stream = null;
508 IOException error = null;
509 try {
510 stream = getStream();
511
512 long skip = position;
513 while (skip > 0) {
514 long skipped = stream.skip(skip);
515 if (skipped <= 0)
516 return -1;
517 skip -= skipped;
518 }
519 return stream.read(b);
520 } catch (IOException e) {
521 error = e;
522 throw e;
523 } finally {
524 if (stream != null) {
525 try {
526 stream.close();
527 } catch (RuntimeException t) {
528
529
530 if (error == null)
531 throw t;
532 } catch (IOException t) {
533
534
535 if (error == null)
536 throw t;
537 }
538 }
539 }
540 }
541
542 };
543 }
544 throw new ValueFormatException("Value not a Binary");
545 }
546
547
548
549
550
551
552 @Override
553 public BigDecimal getDecimal() throws ValueFormatException,
554 RepositoryException {
555 if (value instanceof BigDecimal) {
556 return ((BigDecimal) valueObject);
557 }
558 throw new ValueFormatException("Value not a Decimal");
559 }
560
561 @Override
562 public InputStream getStream() throws IllegalStateException,
563 RepositoryException {
564 if (value instanceof Binary) {
565 return ((Binary) valueObject).getStream();
566 }
567 if (value instanceof InputStream) {
568 return ((InputStream) valueObject);
569 }
570 throw new ValueFormatException("Value not an InputStream");
571 }
572
573 @Override
574 public String getString() throws IllegalStateException {
575 if (value instanceof String) {
576 return (String) valueObject;
577 }
578 return valueObject.toString();
579 }
580
581 @Override
582 public int getType() {
583 return 1;
584 }
585
586 };
587
588 return rtnvalue;
589
590 }
591
592 }
593