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.dbforms.config;
25
26 import org.apache.commons.logging.Log;
27 import org.apache.commons.logging.LogFactory;
28
29 import org.dbforms.interfaces.DbEventInterceptorData;
30 import org.dbforms.interfaces.IDbEventInterceptor;
31 import org.dbforms.interfaces.IEscaper;
32
33 import org.dbforms.util.Util;
34
35 import java.sql.ResultSet;
36 import java.sql.ResultSetMetaData;
37 import java.sql.SQLException;
38
39 import java.util.HashMap;
40 import java.util.Hashtable;
41 import java.util.Map;
42 import java.util.Vector;
43
44 /***
45 * <p>
46 * In version 0.5, this class held the actual data of a ResultSet (SELECT from a
47 * table). The main weakness of this class was that it used too much memory and
48 * processor time:
49 *
50 * <ul>
51 * <li>1. every piece of data gots stored in an array (having a table with a
52 * million datasets will mean running into trouble because all the memory gets
53 * allocated at one time.)</li>
54 * <li>2. every piece of data gots converted into a String and trim()ed</li>
55 * </ul>
56 * </p>
57 *
58 * <p>
59 * since version 0.7 DbForms queries only those record from the database the
60 * user really wants to see. this way you can query from a table with millions
61 * of records and you will still have no memory problems, [exception: you choose
62 * count="" in DbForms-tag :=) -> see org.dbforms.taglib.DbFormTag]
63 * </p>
64 *
65 * @author Joe Peer
66 */
67 public class ResultSetVector implements java.io.Serializable {
68 private static Log logCat = LogFactory.getLog(ResultSetVector.class
69 .getName());
70
71 private Hashtable selectFieldsHashtable;
72
73 private Map attributes = new HashMap();
74
75 private Table table = null;
76
77 private Vector objectVector = new Vector();
78
79 private Vector selectFields = new Vector();
80
81 private boolean firstPage = false;
82
83 private boolean lastPage = false;
84
85
86 private int pointer = 0;
87
88 /***
89 * Creates a new, empty ResultSetVector object.
90 */
91 public ResultSetVector() {
92 }
93
94 /***
95 * Creates a new ResultSetVector object with the given FieldList
96 *
97 * @param table
98 * The FieldList to use
99 */
100 public ResultSetVector(Table table) {
101 this.table = table;
102
103 if (table != null) {
104 setupSelectFieldsHashtable(table.getFields());
105 setupSelectFieldsHashtable(table.getCalcFields());
106 }
107 }
108
109 /***
110 * Creates a new ResultSetVector object.
111 *
112 * @param table
113 * DOCUMENT ME!
114 * @param selectedFields
115 * DOCUMENT ME!
116 */
117 public ResultSetVector(Table table, Vector selectedFields) {
118 this.table = table;
119 setupSelectFieldsHashtable(selectedFields);
120 }
121
122 /***
123 * Checks if the given ResultSetVector is null
124 *
125 * @param rsv
126 * ResultSetVector to check
127 *
128 * @return true if ResultSetVector is null
129 */
130 public static final boolean isNull(ResultSetVector rsv) {
131 return ((rsv == null) || (rsv.size() == 0));
132 }
133
134 /***
135 * Stores a value in the attributes list
136 *
137 * @param key
138 * key for the value
139 * @param value
140 * value to store
141 */
142 public void setAttribute(String key, Object value) {
143 attributes.put(key, value);
144 }
145
146 /***
147 * reads a value from the attributes list
148 *
149 * @param key
150 * key to read
151 *
152 * @return The value. If not found null
153 */
154 public Object getAttribute(String key) {
155 return attributes.get(key);
156 }
157
158 /***
159 * DOCUMENT ME!
160 *
161 * @return Returns the attributes.
162 */
163 public Map getAttributes() {
164 return attributes;
165 }
166
167 public String getTableName() {
168 String result = null;
169 if (table != null)
170 result = table.getName();
171 return result;
172 }
173
174 /***
175 * DOCUMENT ME!
176 *
177 * @return DOCUMENT ME!
178 */
179 public String[] getCurrentRow() {
180 Object[] obj = getCurrentRowAsObjects();
181 String[] res = null;
182
183 if (obj != null) {
184 res = new String[obj.length];
185
186 for (int i = 0; i < obj.length; i++) {
187 res[i] = getField(i);
188 }
189 }
190
191 return res;
192 }
193
194 /***
195 * DOCUMENT ME!
196 *
197 * @return DOCUMENT ME!
198 *
199 * @throws IllegalArgumentException
200 * DOCUMENT ME!
201 */
202 public FieldValues getCurrentRowAsFieldValues() {
203 if (selectFields == null) {
204 throw new IllegalArgumentException(
205 "no field vector was provided to this result");
206 }
207
208 String[] rowData = getCurrentRow();
209
210 if (rowData == null) {
211 return null;
212 }
213
214 FieldValues fvHT = new FieldValues();
215
216 for (int i = 0; i < selectFields.size(); i++) {
217 Field f = (Field) selectFields.elementAt(i);
218 FieldValue fv = new FieldValue(f, rowData[i]);
219 fvHT.put(fv);
220 }
221
222 return fvHT;
223 }
224
225 /***
226 * DOCUMENT ME!
227 *
228 * @return DOCUMENT ME!
229 *
230 * @throws IllegalArgumentException
231 * DOCUMENT ME!
232 */
233 public Map getCurrentRowAsMap() {
234 if (selectFields == null) {
235 throw new IllegalArgumentException(
236 "no field vector was provided to this result");
237 }
238
239 String[] rowData = getCurrentRow();
240
241 if (rowData == null) {
242 return null;
243 }
244
245 Hashtable ht = new Hashtable();
246
247 for (int i = 0; i < selectFields.size(); i++) {
248 Field f = (Field) selectFields.elementAt(i);
249 ht.put(f.getName(), rowData[i]);
250 }
251
252 return ht;
253 }
254
255 /***
256 * DOCUMENT ME!
257 *
258 * @return DOCUMENT ME!
259 */
260 public Object[] getCurrentRowAsObjects() {
261 Object[] res = null;
262 if (isPointerLegal(pointer)) {
263 res = (Object[]) objectVector.elementAt(pointer);
264 }
265 return res;
266 }
267
268 /***
269 * returns the fieldValues String representation given by index i
270 *
271 * @param i
272 * Index into the objectArray
273 *
274 * @return the object
275 */
276 public String getField(int i) {
277 Object obj = getFieldAsObject(i);
278
279 return (obj != null) ? obj.toString() : "";
280 }
281
282 /***
283 * returns the fieldValues string representation given by it's name
284 *
285 * @param fieldName
286 * name of the field
287 *
288 * @return the object
289 */
290 public String getField(String fieldName) {
291 int fieldIndex = getFieldIndex(fieldName);
292
293 if (fieldIndex < 0) {
294 return null;
295 }
296
297 return getField(fieldIndex);
298 }
299
300 /***
301 * returns the fieldValues Object given by index i
302 *
303 * @param i
304 * Index into the objectArray
305 *
306 * @return the object
307 */
308 public Object getFieldAsObject(int i) {
309 return getFieldAsObject(pointer, i);
310 }
311
312 /***
313 * returns the fieldValues Object given by row row and index i
314 *
315 * @param row
316 * row in the rsv
317 * @param i
318 * Index into the objectArray
319 *
320 * @return the object
321 */
322 public Object getFieldAsObject(int row, int i) {
323 Object res = null;
324 if (isPointerLegal(row)) {
325 try {
326 res = ((Object[]) objectVector.elementAt(row))[i];
327 } catch (Exception e) {
328 logCat.error("getFieldAsObject", e);
329 }
330 }
331 return res;
332 }
333
334 /***
335 * sets the fieldValue Object given by row row and index i
336 *
337 * @param row
338 * row in the rsv
339 * @param i
340 * Index into the objectArray
341 *
342 * @return the object
343 */
344 public void setFieldAsObject(int row, int i, Object obj) {
345 if (isPointerLegal(row)) {
346 try {
347 Object[] objRow = (Object[]) objectVector.elementAt(row);
348 objRow[i] = obj;
349 } catch (Exception e) {
350 logCat.error("setFieldAsObject", e);
351 }
352 }
353 }
354
355 /***
356 * returns the fieldValues Object given by it's name
357 *
358 * @param fieldName
359 * name of the field
360 *
361 * @return the object
362 */
363 public Object getFieldAsObject(String fieldName) {
364 return getFieldAsObject(pointer, fieldName);
365 }
366
367 /***
368 * returns the fieldValues Object given by row row and fieldName
369 *
370 * @param row
371 * row in the rsv
372 *
373 * @return the object
374 */
375 public Object getFieldAsObject(int row, String fieldName) {
376 int fieldIndex = getFieldIndex(fieldName);
377
378 if (fieldIndex < 0) {
379 return null;
380 }
381
382 return getFieldAsObject(row, fieldIndex);
383 }
384
385 /***
386 * sets the fieldValue Object given by row row and fieldName
387 *
388 * @param row
389 * row in the rsv
390 * @param fieldName
391 * name of the field
392 *
393 * @return the object
394 */
395 public void setFieldAsObject(int row, String fieldName, Object obj) {
396 int fieldIndex = getFieldIndex(fieldName);
397 if (fieldIndex >= 0) {
398 setFieldAsObject(row, fieldIndex, obj);
399 }
400 }
401
402 /***
403 * gets the Field object to a given fieldName
404 *
405 * @param fieldName
406 * name of the field
407 *
408 * @return the Field object of the given name null if not found
409 */
410 public Field getFieldDescription(String fieldName) {
411 return (Field) selectFieldsHashtable.get(fieldName);
412 }
413
414 /***
415 * returns the index of a given fieldName
416 *
417 * @param fieldName
418 * name of the field
419 *
420 * @return the index of the field in the data arrays
421 */
422 public int getFieldIndex(String fieldName) {
423 int res = -1;
424
425 if (!Util.isNull(fieldName)) {
426 Field f = (Field) selectFieldsHashtable.get(fieldName);
427
428 if (f != null) {
429 res = selectFields.indexOf(f);
430 }
431 }
432
433 return res;
434 }
435
436 /***
437 * Return true if the current record is the first record
438 *
439 * @return true if the first record is reached
440 */
441 public boolean isFirst() {
442 return (pointer == 0);
443 }
444
445 /***
446 * DOCUMENT ME!
447 *
448 * @param b
449 * value to set
450 */
451 public void setFirstPage(boolean b) {
452 firstPage = b;
453 }
454
455 /***
456 * DOCUMENT ME!
457 *
458 * @return DOCUMENT ME!
459 */
460 public boolean isFirstPage() {
461 return firstPage;
462 }
463
464 /***
465 * Return true if the current record is the last record
466 *
467 * @return true if the last record is reached
468 */
469 public boolean isLast() {
470 return (pointer == (size() - 1));
471 }
472
473 /***
474 * DOCUMENT ME!
475 *
476 * @param b
477 * value to set
478 */
479 public void setLastPage(boolean b) {
480 lastPage = b;
481 }
482
483 /***
484 * DOCUMENT ME!
485 *
486 * @return DOCUMENT ME!
487 */
488 public boolean isLastPage() {
489 return lastPage;
490 }
491
492 /***
493 * DOCUMENT ME!
494 *
495 * @param interceptorData
496 * DOCUMENT ME!
497 * @param rs
498 * DOCUMENT ME!
499 *
500 * @throws SQLException
501 * DOCUMENT ME!
502 */
503 public void addResultSet(DbEventInterceptorData interceptorData,
504 ResultSet rs) throws SQLException {
505 ResultSetMetaData rsmd = rs.getMetaData();
506 int columns = rsmd.getColumnCount();
507 IEscaper escaper = null;
508
509 try {
510
511 while (rs.next()) {
512 Object[] objectRow = new Object[columns];
513
514 for (int i = 0; i < columns; i++) {
515 if ((selectFields != null) && (i < selectFields.size())) {
516 Field curField = (Field) selectFields.elementAt(i);
517
518 if (curField != null) {
519 escaper = curField.getEscaper();
520 }
521 }
522
523 if (table != null) {
524 escaper = (escaper == null) ? escaper : table
525 .getEscaper();
526 }
527
528 if (escaper == null) {
529 try {
530 escaper = DbFormsConfigRegistry.instance().lookup()
531 .getEscaper();
532 } catch (Exception e) {
533 logCat.error(
534 "cannot create the new default escaper", e);
535 }
536 }
537
538 objectRow[i] = JDBCDataHelper.getData(rs, escaper, i + 1);
539 }
540
541 addRow(interceptorData, objectRow);
542 }
543 } finally {
544 rs.close();
545 }
546 }
547
548 /***
549 * adds a row to the ResultSetVector
550 *
551 * @param interceptorData
552 * DOCUMENT ME!
553 * @param objectRow
554 * row to add
555 */
556 public void addRow(DbEventInterceptorData interceptorData,
557 Object[] objectRow) {
558 if (objectRow != null) {
559 boolean doit = true;
560 int size = (objectRow.length > selectFields.size()) ? objectRow.length
561 : selectFields.size();
562
563 Object[] newRow = new Object[size];
564
565 for (int i = 0; i < objectRow.length; i++) {
566 newRow[i] = objectRow[i];
567 }
568
569 if ((interceptorData != null)
570 && (interceptorData.getTable() != null)) {
571 interceptorData.setAttribute(DbEventInterceptorData.RESULTSET,
572 this);
573 interceptorData.setAttribute(DbEventInterceptorData.OBJECTROW,
574 newRow);
575
576 int res = IDbEventInterceptor.GRANT_OPERATION;
577
578 try {
579 res = interceptorData.getTable().processInterceptors(
580 IDbEventInterceptor.PRE_ADDROW, interceptorData);
581 } catch (MultipleValidationException e) {
582 logCat.error("addRow", e);
583 }
584
585 doit = (res == IDbEventInterceptor.GRANT_OPERATION);
586 }
587
588 if (doit) {
589 objectVector.addElement(newRow);
590
591 if ((interceptorData != null)
592 && (interceptorData.getTable() != null)) {
593 try {
594 interceptorData.getTable()
595 .processInterceptors(
596 IDbEventInterceptor.POST_ADDROW,
597 interceptorData);
598 } catch (MultipleValidationException e) {
599 logCat.error("addRow", e);
600 }
601 }
602 }
603 }
604 }
605
606 /***
607 * DOCUMENT ME!
608 */
609 public void flip() {
610 int vSize = this.size();
611
612 if (vSize > 1) {
613 logCat.info("flipping " + vSize + " elements!");
614
615 for (int i = 1; i < vSize; i++) {
616 Object o = objectVector.elementAt(i);
617 objectVector.remove(i);
618 objectVector.insertElementAt(o, 0);
619 }
620 }
621 }
622
623 /***
624 * moves to the first record
625 */
626 public void moveFirst() {
627 this.pointer = 0;
628 }
629
630 /***
631 * moves to the last record
632 */
633 public void moveLast() {
634 this.pointer = size() - 1;
635 }
636
637 /***
638 * moves to the next record
639 *
640 * @return true if end is reached
641 */
642 public boolean moveNext() {
643 pointer++;
644
645 return (pointer >= size());
646 }
647
648 /***
649 * moves to the previous record
650 *
651 * @return true if beginning is reached
652 */
653 public boolean movePrevious() {
654 pointer--;
655
656 return (pointer < 0);
657 }
658
659 /***
660 * implements size()
661 *
662 * @return the sizeof the vector
663 */
664 public int size() {
665 return objectVector.size();
666 }
667
668 private boolean isPointerLegal(int p) {
669 return ((p >= 0) && (p < size()));
670 }
671
672 private void setupSelectFieldsHashtable(Vector paramSelectFields) {
673 this.selectFields.addAll(paramSelectFields);
674 selectFieldsHashtable = new Hashtable();
675
676 for (int i = 0; i < selectFields.size(); i++) {
677 Field f = (Field) selectFields.elementAt(i);
678 selectFieldsHashtable.put(f.getName(), f);
679 }
680 }
681 }