Source Code Cross Referenced for Recordset.java in  » J2EE » Dinamica » dinamica » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » J2EE » Dinamica » dinamica 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        package dinamica;
002:
003:        import java.text.MessageFormat;
004:        import java.util.ArrayList;
005:        import java.util.Collections;
006:        import java.util.Comparator;
007:        import java.util.HashMap;
008:        import java.util.Iterator;
009:        import java.io.Serializable;
010:        import java.io.StringWriter;
011:        import java.io.PrintWriter;
012:        import java.sql.*;
013:
014:        /**
015:         * Core-level framework class: Recordset - General purpose, tabular data structure.
016:         * <br><br>
017:         * Represents a disconnected recordset, a kind of multi-purpose ResultSet
018:         * without connection to the database, much like
019:         * the famous ADO disconnected recordset from VB6, 
020:         * can be created from a SQL query or manufactured
021:         * by code to represent any tabular data. It is a kind of
022:         * generic data container that may save a lot of work because
023:         * it can be used to represent several entities avoiding the need
024:         * to write custom classes to represent each specific entity.
025:         * It is serializable, so it can be safely used in HTTP Sessions, JNDI, etc. 
026:         * <br><br>
027:         * This recordset mantains all data in memory and does not need
028:         * an open connection to the database, provides several constructors
029:         * to isolate the programmer from the task of programming with the
030:         * JDBC API, but also provides low level access if desired.
031:         * <br><br>
032:         * Each field in the recordset is mantained in its native data type
033:         * as represented by the JDBC driver, or a java null value.
034:         * <br>
035:         * <br>
036:         * Creation date: 10/09/2003<br>
037:         * Last Update: 11/09/2003<br>
038:         * (c) 2003 Martin Cordova<br>
039:         * This code is released under the LGPL license<br>
040:         * @author Martin Cordova (dinamica@martincordova.com)
041:         */
042:        public class Recordset implements  Serializable {
043:
044:            /**
045:             * 
046:             */
047:            private static final long serialVersionUID = 1L;
048:
049:            /** contains list of fields */
050:            private HashMap<String, RecordsetField> _fields = new HashMap<String, RecordsetField>();
051:
052:            /** contains list of records */
053:            private ArrayList<Record> _data = new ArrayList<Record>();
054:
055:            /** recordset position (0...N-1)*/
056:            private int _recordNumber = -1;
057:
058:            /** paging support */
059:            private int _pageCount = 0;
060:            private int _pageSize = 0;
061:            private int _currentPage = 0;
062:
063:            /** recordset ID */
064:            private String _ID = null;
065:
066:            private String _lastSortColName = null;
067:            private String _lastSortMode = null;
068:
069:            /**
070:             * Return records per page (page size) for recordsets 
071:             * used in paged views
072:             * @return
073:             */
074:            public int getPageSize() {
075:                return _pageSize;
076:            }
077:
078:            /**
079:             * Create a recordset with one record containing
080:             * general recordset parameters like: recordcount, pagecount, currentpage 
081:             * @return Recordset Object
082:             * @throws Throwable
083:             */
084:            public Recordset getRecordsetInfo() throws Throwable {
085:
086:                Recordset rs = new Recordset();
087:                rs.append("recordcount", Types.INTEGER);
088:                rs.append("pagecount", Types.INTEGER);
089:                rs.append("currentpage", Types.INTEGER);
090:                rs.append(_ID + ".recordcount", Types.INTEGER);
091:
092:                rs.addNew();
093:                rs.setValue("recordcount", new Integer(_data.size()));
094:                rs.setValue("pagecount", new Integer(_pageCount));
095:                rs.setValue("currentpage", new Integer(_currentPage));
096:                rs.setValue(_ID + ".recordcount", new Integer(_data.size()));
097:
098:                return rs;
099:
100:            }
101:
102:            /**
103:             * Set recordset ID (an arbitrary String)
104:             * @param id
105:             */
106:            public void setID(String id) {
107:                _ID = id;
108:            }
109:
110:            /**
111:             * Paging support.<br>
112:             * Returns the number of record pages determined by setPageSize
113:             */
114:            public int getPageCount() {
115:                return _pageCount;
116:            }
117:
118:            /**
119:             * Paging support.<br>
120:             * Returns the current page number (1...N)
121:             */
122:            public int getPageNumber() {
123:                return _currentPage;
124:            }
125:
126:            /**
127:             * Paging support.<br>
128:             * Define page size (records per page)
129:             */
130:            public void setPageSize(int p) throws Throwable {
131:
132:                if (p <= 0) {
133:                    throw new Throwable("Invalid page size, must be > 0!");
134:                }
135:
136:                if (_data.size() == 0) {
137:                    throw new Throwable(
138:                            "Invalid page size, recordset is empty!");
139:                }
140:
141:                _pageSize = p;
142:
143:                java.math.BigDecimal b1 = new java.math.BigDecimal(_data.size());
144:                java.math.BigDecimal b2 = new java.math.BigDecimal(_pageSize);
145:                _pageCount = b1.divide(b2, java.math.BigDecimal.ROUND_UP)
146:                        .intValue();
147:
148:                if (getRecordCount() > 0)
149:                    _currentPage = 1;
150:
151:            }
152:
153:            /**
154:             * Paging support.<br>
155:             * Get Recordset representing the requeste page of records
156:             */
157:            @SuppressWarnings("unchecked")
158:            public Recordset getPage(int p) throws Throwable {
159:
160:                if (p < 1 || p > _pageCount)
161:                    throw new Throwable("Invalid page number: " + p
162:                            + " - the Recordset contains " + _pageCount
163:                            + " pages.");
164:
165:                _currentPage = p;
166:
167:                /* calculate first and last row numbers for this page */
168:                int row1 = (p - 1) * _pageSize;
169:                int row2 = (p * _pageSize) - 1;
170:                if (row2 > (_data.size() - 1))
171:                    row2 = _data.size() - 1;
172:
173:                /* 
174:                 create an identical recordset 
175:                 containing only the records 
176:                 for the requested page
177:                 */
178:                ArrayList<Record> newData = new ArrayList<Record>(_pageSize);
179:                for (int i = row1; i <= row2; i++) {
180:                    newData.add((Record) _data.get(i));
181:                }
182:                Recordset x = new Recordset();
183:                x.setFields((HashMap<String, RecordsetField>) _fields.clone());
184:                x.setData(newData);
185:
186:                /* return "page" */
187:                return x;
188:
189:            }
190:
191:            /**
192:             * Feed the recordset metadata (column structure)
193:             * @param fields HashMap containing the recordset field objects
194:             */
195:            @SuppressWarnings("unchecked")
196:            protected void setFields(HashMap fields) {
197:                this ._fields = fields;
198:            }
199:
200:            /**
201:             * Feed the recordset data
202:             * @param data ArrayList containing record objects
203:             */
204:            @SuppressWarnings("unchecked")
205:            protected void setData(ArrayList data) {
206:                this ._data = data;
207:            }
208:
209:            /**
210:             * Returns the current record position (0...N-1)
211:             * @return
212:             */
213:            public int getRecordNumber() {
214:                return _recordNumber;
215:            }
216:
217:            /**
218:             * Returns the number of records in recordset
219:             * @return
220:             */
221:            public int getRecordCount() {
222:                return _data.size();
223:            }
224:
225:            /**
226:             * Returns number of fields in recordset
227:             * @return
228:             */
229:            public int getFieldCount() {
230:                return _fields.size();
231:            }
232:
233:            /**
234:             * Returns HashMap containing RecordsetField objects
235:             * representing the Recordset fields
236:             * @return 
237:             */
238:            public HashMap<String, RecordsetField> getFields() {
239:                return _fields;
240:            }
241:
242:            /**
243:             * Returns ArrayList containing the recordset data (the records)
244:             * @return 
245:             */
246:            public ArrayList<Record> getData() {
247:                return _data;
248:            }
249:
250:            /**
251:             * Append a field to the recordset structure.<br>
252:             * It is used when creating a Recordset from a JDBC query
253:             * @param fieldName Field Name
254:             * @param nativeSqlType SQL native data type name
255:             * @param type JDBC data type (java.sql.Types)
256:             */
257:            private void append(String fieldName, String nativeSqlType, int type) {
258:                RecordsetField f = new RecordsetField(fieldName, nativeSqlType,
259:                        type);
260:                _fields.put(fieldName, f);
261:            }
262:
263:            /**
264:             * Append a field to the recordset structure.<br>
265:             * It is used when manufacturing a Recordset from code
266:             * @param fieldName Field Name
267:             * @param nativeSqlType SQL native data type name
268:             * @param type JDBC data type (java.sql.Types) - only INTEGER, LONG, VARCHAR, DATE, TIMESTAMP or DOUBLE are supported
269:             */
270:            public void append(String fieldName, int type)
271:                    throws RecordsetException {
272:
273:                String sqlTypeName = null;
274:
275:                switch (type) {
276:                case Types.INTEGER:
277:                    sqlTypeName = "INTEGER";
278:                    break;
279:
280:                case Types.BIGINT:
281:                    sqlTypeName = "LONG";
282:                    break;
283:
284:                case Types.VARCHAR:
285:                    sqlTypeName = "VARCHAR";
286:                    break;
287:
288:                case Types.DATE:
289:                    sqlTypeName = "DATE";
290:                    break;
291:
292:                case Types.TIMESTAMP:
293:                    sqlTypeName = "TIMESTAMP";
294:                    break;
295:
296:                case Types.DOUBLE:
297:                    sqlTypeName = "DOUBLE";
298:                    break;
299:
300:                }
301:
302:                if (sqlTypeName == null) {
303:                    String args[] = { String.valueOf(type) };
304:                    String msg = Errors.INVALID_DATATYPE;
305:                    msg = MessageFormat.format(msg, (Object[]) args);
306:                    throw new RecordsetException(msg);
307:                }
308:
309:                append(fieldName, sqlTypeName, type);
310:
311:            }
312:
313:            /**
314:             * Add a record to the recordset and set record number position
315:             * to the new inserted record
316:             *
317:             */
318:            public void addNew() {
319:
320:                HashMap<String, Object> values = new HashMap<String, Object>();
321:                Iterator<String> i = _fields.keySet().iterator();
322:                while (i.hasNext()) {
323:                    String f = (String) i.next();
324:                    values.put(f, null);
325:                }
326:
327:                _data.add(new Record(values));
328:
329:                /* set record number */
330:                _recordNumber++;
331:
332:            }
333:
334:            /**
335:             * Set record position inside recordset
336:             * @param recNum Record Number (0...getRecordCount()-1)
337:             * @throws Throwable
338:             */
339:            public void setRecordNumber(int recNum) throws RecordsetException {
340:
341:                checkRecordPosition(recNum);
342:                _recordNumber = recNum;
343:
344:            }
345:
346:            /**
347:             * Set field value for current record (determined by getRecordNumber())
348:             * @param fieldName Field Name
349:             * @param value Field Value (Date, String, int, double, null)
350:             * @throws Throwable
351:             */
352:            public void setValue(String fieldName, Object value)
353:                    throws RecordsetException {
354:
355:                checkRecordPosition();
356:
357:                RecordsetField f;
358:                try {
359:                    f = getField(fieldName);
360:                } catch (Throwable e) {
361:                    throw new RecordsetException(e.getMessage());
362:                }
363:
364:                if (value != null) {
365:                    switch (f.getType()) {
366:
367:                    case java.sql.Types.DATE:
368:                        if (!(value instanceof  java.util.Date))
369:                            throw new RecordsetException(
370:                                    "Invalid data type of field: "
371:                                            + fieldName
372:                                            + "; passed value must be a DATE object.");
373:                        break;
374:
375:                    case java.sql.Types.INTEGER:
376:                        if (!(value instanceof  java.lang.Integer))
377:                            throw new RecordsetException(
378:                                    "Invalid data type of field: "
379:                                            + fieldName
380:                                            + "; passed value must be an INTEGER object.");
381:                        break;
382:
383:                    case java.sql.Types.DOUBLE:
384:                        if (!(value instanceof  java.lang.Double))
385:                            throw new RecordsetException(
386:                                    "Invalid data type of field: "
387:                                            + fieldName
388:                                            + "; passed value must be an DOUBLE object.");
389:                        break;
390:                    }
391:                }
392:
393:                Record rec = (Record) _data.get(_recordNumber);
394:                rec.setValue(fieldName, value);
395:
396:            }
397:
398:            /**
399:             * Return field value given a field name
400:             * @param fieldName Field Name. May be reserved field names: _rowIndex (0...N-1) or _rowNumber (1...N)
401:             * @return
402:             * @throws Throwable
403:             */
404:            public Object getValue(String fieldName) throws Throwable {
405:
406:                /* check for valid cursor position */
407:                checkRecordPosition();
408:
409:                /* special treatment for reserved field names */
410:                if (fieldName.equals("_rowIndex")) {
411:                    return new Integer(_recordNumber);
412:                } else if (fieldName.equals("_rowNumber")) {
413:                    return new Integer(_recordNumber + 1);
414:                } else {
415:                    Record rec = (Record) _data.get(_recordNumber);
416:                    return rec.getFieldValue(fieldName);
417:                }
418:
419:            }
420:
421:            /**
422:             * Fill recordset with resultset data and metadata. It is the
423:             * responsability of the caller of this method to close the resultset
424:             * and other jdbc objects involved. The resultset must be positioned before
425:             * the first record
426:             * @param rs Resultset
427:             * @throws Throwable
428:             */
429:            private void loadRecords(java.sql.ResultSet rs) throws Throwable {
430:
431:                /* default fields */
432:                //append("_rowIndex", "INTEGER", Types.INTEGER);
433:                //append("_rowNumber", "INTEGER", Types.INTEGER);
434:                /* load field definitions */
435:                ResultSetMetaData md = rs.getMetaData();
436:                int cols = md.getColumnCount();
437:                for (int i = 1; i <= cols; i++) {
438:                    append(md.getColumnName(i).toLowerCase(), md
439:                            .getColumnTypeName(i), md.getColumnType(i));
440:                }
441:
442:                /* load data */
443:                while (rs.next()) {
444:                    HashMap<String, Object> flds = new HashMap<String, Object>(
445:                            cols);
446:                    for (int i = 1; i <= cols; i++) {
447:                        flds.put(md.getColumnName(i).toLowerCase(), rs
448:                                .getObject(i));
449:                    }
450:                    _data.add(new Record(flds));
451:                }
452:
453:            }
454:
455:            /**
456:             * Create a recordset given a resultset. It is the
457:             * responsability of the caller of this method to close the resultset
458:             * and other jdbc objects involved.
459:             * @param rs ResultSet positiones before the first record
460:             * @throws Throwable
461:             */
462:            public Recordset(ResultSet rs) throws Throwable {
463:                loadRecords(rs);
464:            }
465:
466:            /**
467:             * Creates a recordset given a SQL query
468:             * @param conn Database Connection
469:             * @param sql SQL Query that returns a Resultset
470:             * @throws Throwable
471:             */
472:            public Recordset(Connection conn, String sql) throws Throwable {
473:                this (conn, sql, 0);
474:            }
475:
476:            /**
477:             * Creates a recordset given a SQL query. 
478:             * @param conn Database Connection
479:             * @param sql SQL Query that returns a Resultset
480:             * @param limit Maximum number of rows to read from the DataBase
481:             * @throws Throwable
482:             */
483:            public Recordset(java.sql.Connection conn, String sql, int limit)
484:                    throws Throwable {
485:
486:                ResultSet rs = null;
487:                Statement stmt = null;
488:
489:                try {
490:
491:                    /* execute query */
492:                    stmt = conn.createStatement();
493:
494:                    if (limit > 0)
495:                        stmt.setMaxRows(limit);
496:
497:                    rs = stmt.executeQuery(sql);
498:                    loadRecords(rs);
499:
500:                } catch (Throwable e) {
501:                    throw e;
502:                } finally {
503:                    if (rs != null)
504:                        rs.close();
505:                    if (stmt != null)
506:                        stmt.close();
507:                }
508:
509:            }
510:
511:            /**
512:             * Default constructor used when creating 
513:             * the recordset from code (a "manufactured" recordset)
514:             *
515:             */
516:            public Recordset() {
517:                /* default fields */
518:                //append("_rowIndex", "INTEGER", Types.INTEGER);
519:                //append("_rowNumber", "INTEGER", Types.INTEGER);
520:            }
521:
522:            /**
523:             * Move pointer to next record. Returns true if not EOF
524:             * @return
525:             */
526:            public boolean next() {
527:                if (_recordNumber < (_data.size() - 1)) {
528:                    _recordNumber++;
529:                    return true;
530:                } else {
531:                    return false;
532:                }
533:            }
534:
535:            /**
536:             * Returns a text-formatted report with the
537:             * structure of the recordset, very usefull for
538:             * debugging purposes
539:             */
540:            public String toString() {
541:                StringWriter sw = new StringWriter(1000);
542:                PrintWriter pw = new PrintWriter(sw);
543:
544:                pw.println("Recordset Information");
545:                pw.println("Record Count: " + getRecordCount());
546:                pw.println("Field Count: " + getFieldCount());
547:                pw.println("Structure:");
548:                pw.println("----------------------------------");
549:                pw.println("NAME|SQL-TYPE-NAME|JDBC-TYPE-ID");
550:
551:                Iterator<RecordsetField> i = _fields.values().iterator();
552:                while (i.hasNext()) {
553:                    RecordsetField f = (RecordsetField) i.next();
554:
555:                    pw.println(f.getName() + "|" + f.getSqlTypeName() + "|"
556:                            + f.getType());
557:                }
558:
559:                return sw.toString();
560:            }
561:
562:            /**
563:             * Set cursor position before first record,
564:             * it is like a "rewind" command
565:             *
566:             */
567:            public void top() {
568:                _recordNumber = -1;
569:            }
570:
571:            /**
572:             * Set cursor position on first record
573:             * @throws Throwable
574:             */
575:            public void first() throws Throwable {
576:                setRecordNumber(0);
577:            }
578:
579:            /**
580:             * Set cursor position on last record
581:             * @throws Throwable
582:             */
583:            public void last() throws Throwable {
584:                setRecordNumber(_data.size() - 1);
585:            }
586:
587:            /**
588:             * Delete record (from memory)
589:             * @param recNum Record Number (0..N-1)
590:             */
591:            public void delete(int recNum) throws Throwable {
592:                checkRecordPosition(recNum);
593:                _data.remove(recNum);
594:                _recordNumber--;
595:            }
596:
597:            /**
598:             * Return a Recordset field object describing its properties
599:             * @param fieldName Field name to locate the field object
600:             * @return Reference to Recordset field
601:             * @throws Throwable if fieldName does not exist in Recordset metadata
602:             */
603:            public RecordsetField getField(String fieldName) throws Throwable {
604:                if (_fields.containsKey(fieldName))
605:                    return (RecordsetField) _fields.get(fieldName);
606:                else
607:                    throw new Throwable("Field not found:" + fieldName);
608:            }
609:
610:            /**
611:             * Copy record values from this recordset to
612:             * a destination recordset, using the current
613:             * record of both recordsets. Destination recordset
614:             * fields that match names with source recordset fields
615:             * must be of the same type too. It does not matter if some
616:             * fields from the source recordset are not defined in the destination
617:             * recordset. Only name-matching fields will be considered
618:             * for the operation. 
619:             * @param rs Destination recordsets
620:             * @throws Throwable
621:             */
622:            public void copyValues(Recordset rs) throws Throwable {
623:                checkRecordPosition();
624:                HashMap<String, RecordsetField> flds = rs.getFields();
625:                Iterator<RecordsetField> i = _fields.values().iterator();
626:                while (i.hasNext()) {
627:                    RecordsetField f = (RecordsetField) i.next();
628:                    String name = f.getName();
629:                    if (flds.containsKey(name)) {
630:                        rs.setValue(name, getValue(name));
631:                    }
632:                }
633:
634:            }
635:
636:            /**
637:             * Wrapper method for getValue() - avoids casting the data type
638:             * @param colName Column name to retrieve its value from the current record
639:             * @return The column value in its native data type
640:             * @throws Throwable
641:             */
642:            public String getString(String colName) throws Throwable {
643:                Object obj = getValue(colName);
644:                if (obj != null)
645:                    return String.valueOf(obj);
646:                else
647:                    return null;
648:            }
649:
650:            /**
651:             * Wrapper method for getValue() - avoids casting the data type
652:             * @param colName Column name to retrieve its value from the current record
653:             * @return The column value in its native data type
654:             * @throws Throwable
655:             */
656:            public java.util.Date getDate(String colName) throws Throwable {
657:                java.util.Date d = null;
658:                d = (java.util.Date) getValue(colName);
659:                return d;
660:            }
661:
662:            /**
663:             * Wrapper method for getValue() - avoids casting the data type
664:             * @param colName Column name to retrieve its value from the current record
665:             * @return The column value in its native data type
666:             * @throws Throwable
667:             */
668:            public double getDouble(String colName) throws Throwable {
669:                Double d = new Double(String.valueOf(getValue(colName)));
670:                return d.doubleValue();
671:            }
672:
673:            /**
674:             * Wrapper method for getValue() - avoids casting the data type
675:             * @param colName Column name to retrieve its value from the current record
676:             * @return The column value in its native data type
677:             * @throws Throwable
678:             */
679:            public int getInt(String colName) throws Throwable {
680:                Integer i = new Integer(String.valueOf(getValue(colName)));
681:                return i.intValue();
682:            }
683:
684:            /**
685:             * Wrapper method for getValue() - avoids casting the data type
686:             * @param colName Column name to retrieve its value from the current record
687:             * @return The column value in its native data type
688:             * @throws Throwable
689:             */
690:            public Integer getInteger(String colName) throws Throwable {
691:                Integer i = new Integer(String.valueOf(getValue(colName)));
692:                return i;
693:            }
694:
695:            /**
696:             * Tests if the give column value is null for the
697:             * current record
698:             * @param colName Column name
699:             * @return TRUE if the value is null
700:             * @throws Throwable If record position is not valid or the column does not exist in the recordset
701:             */
702:            public boolean isNull(String colName) throws Throwable {
703:                if (getValue(colName) == null)
704:                    return true;
705:                else
706:                    return false;
707:            }
708:
709:            /**
710:             * Check if recordset contains field with a given name
711:             * @param name Name of the field to check its existence
712:             * @return TRUE if field exists, FALSE if not
713:             */
714:            public boolean containsField(String name) {
715:                if (_fields.containsKey(name))
716:                    return true;
717:                else
718:                    return false;
719:            }
720:
721:            /**
722:             * Tests if a given record number represents
723:             * a valid record position in the Recordset
724:             * @param recNum Record number (between 0...N-1 where N is the number of records)
725:             * @throws RecordsetException If the test fails
726:             */
727:            private void checkRecordPosition(int recNum)
728:                    throws RecordsetException {
729:                if (recNum < 0 || recNum > _data.size() - 1) {
730:
731:                    StringBuffer errMsg = new StringBuffer();
732:
733:                    errMsg.append("Invalid record position: " + recNum + "; ");
734:                    if (recNum == -1)
735:                        errMsg
736:                                .append("After creating a Recordset you must move to a valid record using next(), first(), last() or setRecordNumber() methods before attempting read/write operations with any record of this Recordset; ");
737:                    errMsg
738:                            .append("This Recordset contains "
739:                                    + _data.size()
740:                                    + " record(s); Set the record position between 0 and N-1 where N is the number of records.");
741:
742:                    throw new RecordsetException(errMsg.toString());
743:
744:                }
745:            }
746:
747:            /**
748:             * Tests if the current record number represents
749:             * a valid record position in the Recordset. This overload
750:             * reuses the checkRecordPosition(int recNum) method.
751:             * @throws RecordsetException If the test fails
752:             */
753:            private void checkRecordPosition() throws RecordsetException {
754:                checkRecordPosition(this ._recordNumber);
755:            }
756:
757:            /**
758:             * Set the children recordset for the current record
759:             * @param rs Children recordset
760:             * @throws Throwable If the record position is not valid
761:             */
762:            public void setChildrenRecordset(Recordset rs) throws Throwable {
763:                checkRecordPosition();
764:                Record rec = (Record) _data.get(_recordNumber);
765:                rec.setChildren(rs);
766:            }
767:
768:            /**
769:             * Retrieve current record's children recordset
770:             * @return A reference to the children recordset or null if no children recordset exists
771:             * @throws Throwable If the record position is not valid
772:             */
773:            public Recordset getChildrenRecordset() throws Throwable {
774:                checkRecordPosition();
775:                Record rec = (Record) _data.get(_recordNumber);
776:                return rec.getChildren();
777:            }
778:
779:            /**
780:             * Sort Recordset data in ascending order by the given column
781:             * @param col Name of the column to be used for the sort
782:             * @throws Throwable
783:             */
784:            @SuppressWarnings("unchecked")
785:            public void sort(String col) throws Throwable {
786:
787:                //patch 2007-06-19
788:                //when ordering for 2nd time on the same column, apply descending order
789:                if (_lastSortColName != null && _lastSortColName.equals(col)) {
790:                    if (_lastSortMode == null)
791:                        _lastSortMode = "desc";
792:                    else
793:                        _lastSortMode = null;
794:
795:                } else {
796:                    _lastSortMode = null;
797:                    _lastSortColName = col;
798:                }
799:
800:                Comparator comp = new Comp(col, _lastSortMode);
801:                Collections.sort(_data, comp);
802:
803:            }
804:
805:            /**
806:             * Comparator inner class that provides sorting support
807:             */
808:            class Comp implements  Serializable, Comparator<Record> {
809:                /**
810:                 * 
811:                 */
812:                private static final long serialVersionUID = 1L;
813:                private String _sortCol = null;
814:                private String _sortMode = null;
815:
816:                public Comp(String colName, String sortMode) throws Throwable {
817:                    _sortMode = sortMode;
818:                    _sortCol = colName;
819:
820:                    if (!containsField(colName))
821:                        throw new Throwable(
822:                                "Invalid column name passed to sort() method: "
823:                                        + colName);
824:                }
825:
826:                @SuppressWarnings("unchecked")
827:                public int compare(Record r1, Record r2) {
828:
829:                    /*Record r1 = (Record)o1;
830:                    Record r2 = (Record)o2;*/
831:
832:                    int result = 0;
833:
834:                    try {
835:                        if (r1.getFieldValue(_sortCol) == null) {
836:                            result = 0;
837:                        } else if (r2.getFieldValue(_sortCol) == null) {
838:                            result = 1;
839:                        } else {
840:                            Comparable<Object> x1 = (Comparable) r1
841:                                    .getFieldValue(_sortCol);
842:                            result = x1.compareTo(r2.getFieldValue(_sortCol));
843:
844:                            //descending order?
845:                            if (_sortMode != null) {
846:                                if (result < 0)
847:                                    result = 1;
848:                                else if (result > 0)
849:                                    result = -1;
850:                            }
851:                        }
852:                    } catch (Throwable e) {
853:                        System.err.println("SORT ERROR: " + e.getMessage());
854:                    }
855:
856:                    return result;
857:
858:                }
859:
860:            }
861:
862:            /**
863:             * Retrieve recordset metadata. This method returns
864:             * a Recordset containing the columns: name, typename, typeid.
865:             * "typeid" is the java.sql.Type value<br>
866:             * There will be one record for each column.
867:             * @return Recordset
868:             * @throws Throwable
869:             */
870:            public Recordset getMetaData() throws Throwable {
871:
872:                // prepare the new Recordset structure
873:                Recordset rs = new Recordset();
874:                rs.append("name", java.sql.Types.VARCHAR);
875:                rs.append("typename", java.sql.Types.VARCHAR);
876:                rs.append("typeid", java.sql.Types.INTEGER);
877:
878:                //get recordset structure
879:                HashMap<String, RecordsetField> flds = this .getFields();
880:                Iterator<RecordsetField> i = flds.values().iterator();
881:
882:                // fill the structure with the data
883:                while (i.hasNext()) {
884:                    RecordsetField f = (RecordsetField) i.next();
885:                    rs.addNew();
886:                    rs.setValue("name", f.getName());
887:                    rs.setValue("typename", f.getSqlTypeName());
888:                    rs.setValue("typeid", new Integer(f.getType()));
889:                }
890:
891:                return rs;
892:
893:            }
894:
895:            /**
896:             * Duplicate the Recordset structure in a new Recordset without any data
897:             * @return Empty Recordset with the same structure
898:             * @throws Throwable
899:             */
900:            public Recordset copyStructure() throws Throwable {
901:
902:                //new recordset
903:                Recordset newRS = new Recordset();
904:
905:                //get metadata
906:                Recordset infoRS = getMetaData();
907:                infoRS.top();
908:                while (infoRS.next()) {
909:                    // obtain the column's data
910:                    String name = infoRS.getString("name");
911:                    int jdbcTypeId = infoRS.getInt("typeid");
912:
913:                    //add column def
914:                    newRS.append(name, jdbcTypeId);
915:                }
916:
917:                return newRS;
918:
919:            }
920:
921:            /**
922:             * Clear current record values, set every field's value to null
923:             */
924:            public void clear() throws Throwable {
925:                checkRecordPosition();
926:                Iterator<RecordsetField> i = _fields.values().iterator();
927:                while (i.hasNext()) {
928:                    RecordsetField f = (RecordsetField) i.next();
929:                    setValue(f.getName(), null);
930:                }
931:            }
932:
933:            /**
934:             * Find a record where a column's value matches a given value
935:             * @param colName Column to use for the search
936:             * @param value Value to search for
937:             * @return Record position (0...N-1) or -1 if not found
938:             * @throws Throwable
939:             */
940:            public int findRecord(String colName, int value) throws Throwable {
941:                int rc = -1;
942:
943:                top();
944:                while (next()) {
945:                    if (value == getInt(colName)) {
946:                        rc = this .getRecordNumber();
947:                        break;
948:                    }
949:                }
950:
951:                return rc;
952:            }
953:
954:            /** 
955:             * Find a record where a column's value matches a given value
956:             * @param colName Column to use for the search
957:             * @param value Value to search for
958:             * @return Record position (0...N-1) or -1 if not found
959:             * @throws Throwable
960:             */
961:            public int findRecord(String colName, String value)
962:                    throws Throwable {
963:                int rc = -1;
964:
965:                top();
966:                while (next()) {
967:                    if (value.equals(getString(colName))) {
968:                        rc = this .getRecordNumber();
969:                        break;
970:                    }
971:                }
972:
973:                return rc;
974:            }
975:
976:            /** 
977:             * Find a record where a column's value matches a given Date value
978:             * @param colName Column to use for the search
979:             * @param value Date value to search for
980:             * @return Record position (0...N-1) or -1 if not found
981:             * @throws Throwable
982:             */
983:            public int findRecord(String colName, java.util.Date value)
984:                    throws Throwable {
985:                int rc = -1;
986:
987:                top();
988:                while (next()) {
989:                    if (value.compareTo(getDate(colName)) == 0) {
990:                        rc = this.getRecordNumber();
991:                        break;
992:                    }
993:                }
994:
995:                return rc;
996:            }
997:
998:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.