0001: /**
0002: * Copyright (C) 2006, 2007 David Bulmore, Software Sensation Inc.
0003: * All Rights Reserved.
0004: *
0005: * This file is part of JPersist.
0006: *
0007: * JPersist is free software; you can redistribute it and/or modify it under
0008: * the terms of the GNU General Public License (Version 2) as published by
0009: * the Free Software Foundation.
0010: *
0011: * JPersist is distributed in the hope that it will be useful, but WITHOUT
0012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0014: * for more details.
0015: *
0016: * You should have received a copy of the GNU General Public License
0017: * along with JPersist; if not, write to the Free Software Foundation,
0018: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
0019: */package jpersist;
0020:
0021: import java.io.InputStream;
0022: import java.io.Reader;
0023: import java.lang.reflect.Proxy;
0024: import java.math.BigDecimal;
0025: import java.net.URL;
0026: import java.sql.Array;
0027: import java.sql.Blob;
0028: import java.sql.Clob;
0029: import java.sql.Date;
0030: import java.sql.Ref;
0031: import java.sql.ResultSet;
0032: import java.sql.Statement;
0033: import java.sql.Time;
0034: import java.sql.Timestamp;
0035: import java.util.Collection;
0036: import java.util.Iterator;
0037: import java.util.NoSuchElementException;
0038: import java.util.logging.Level;
0039: import java.util.logging.Logger;
0040: import jpersist.interfaces.AsciiStream;
0041: import jpersist.interfaces.AsciiStreamAdapter;
0042: import jpersist.interfaces.BinaryStream;
0043: import jpersist.interfaces.BinaryStreamAdapter;
0044: import jpersist.interfaces.CharacterStreamAdapter;
0045: import jpersist.interfaces.CharacterStream;
0046: import jpersist.interfaces.ResultObject;
0047:
0048: /**
0049: * The result class is created and returned by all query methods in jpersist.Database
0050: * and jpersist.DatabaseManager, and basically wraps a ResultSet with ResultSet
0051: * functionality, along with ListIterator and object loading functionality.
0052: */
0053: @SuppressWarnings("unchecked")
0054: // working to complete a Java 1.5 version
0055: public class Result<T> implements ResultObject<T> {
0056: private static Logger logger = Logger.getLogger(Result.class
0057: .getName());
0058: private boolean isClosed, resultSetIsEmpty;
0059: private ResultSet resultSet;
0060: private Database db;
0061: private Class<T> cs;
0062:
0063: /**
0064: * Create an instance of Result by passing in a jpersist.Database instance
0065: * and a ResultSet instance returned from a query (statement.getResultSet()).
0066: *
0067: * @param db
0068: * @param resultSet
0069: */
0070: public Result(Database db, ResultSet resultSet)
0071: throws JPersistException {
0072: this .db = db;
0073: this .resultSet = resultSet;
0074:
0075: try {
0076: boolean beforeFirst = resultSet.isBeforeFirst(), afterLast = resultSet
0077: .isAfterLast();
0078: resultSetIsEmpty = !(beforeFirst || afterLast)
0079: || (beforeFirst && afterLast);
0080: } catch (Exception e) {
0081: throw new JPersistException(e);
0082: }
0083: }
0084:
0085: /**
0086: * Create an instance of Result by passing in a jpersist.Database instance
0087: * and a ResultSet instance returned from a query (statement.getResultSet()).
0088: *
0089: * @param db
0090: * @param resultSet
0091: *
0092: * Setting the class allows next() and previous() to return loaded
0093: * (with data from the current row) objects of the class.
0094: */
0095: public Result(Database db, ResultSet resultSet, Class<T> cs)
0096: throws JPersistException {
0097: this .db = db;
0098: this .resultSet = resultSet;
0099: this .cs = cs;
0100:
0101: try {
0102: boolean beforeFirst = resultSet.isBeforeFirst(), afterLast = resultSet
0103: .isAfterLast();
0104: resultSetIsEmpty = !(beforeFirst || afterLast)
0105: || (beforeFirst && afterLast);
0106: } catch (Exception e) {
0107: throw new JPersistException(e);
0108: }
0109: }
0110:
0111: /**
0112: * If class (see setClass()) is defined, iteration will return instances of
0113: * class loaded with the current row of data.
0114: *
0115: * @return returns this
0116: */
0117:
0118: public Iterator<T> iterator() {
0119: return this ;
0120: }
0121:
0122: /**
0123: * Setting the class allows next() and previous() to return loaded
0124: * (with data from the current row) objects of the class.
0125: *
0126: * @param cs the class to create instances for
0127: *
0128: * @return returns this
0129: */
0130: public Result setClass(Class<T> cs) {
0131: this .cs = cs;
0132:
0133: return this ;
0134: }
0135:
0136: /**
0137: * Closes all resources associated with a JDBC Statement and ResultSet.
0138: */
0139: public void close() throws JPersistException {
0140: if (!isClosed)
0141: try {
0142: isClosed = true;
0143: resultSet.getStatement().close();
0144: } catch (Exception e) {
0145: throw new JPersistException(e);
0146: }
0147: }
0148:
0149: /**
0150: * Closes the result (simply calls close()), can be used in EL. For example:
0151: *
0152: * <pre>
0153: * ${result.close}
0154: * </pre>
0155: *
0156: * @throws JPersistException
0157: */
0158:
0159: public String getClose() throws JPersistException {
0160: close();
0161:
0162: return null;
0163: }
0164:
0165: /**
0166: * Closes the result (simply calls close()), via a JavaBeans setter. For example:
0167: * <pre>
0168: * <jsp:useBean id="result" scope="request" class="jpersist.Result" />
0169: * <jsp:setProperty name="result" property="closed" value="true"/>
0170: * </pre>
0171: *
0172: * @throws JPersistException
0173: */
0174:
0175: public void setClosed(boolean true_only) throws JPersistException {
0176: close();
0177: }
0178:
0179: /**
0180: * Returns true if the result is closed, false otherwise.
0181: *
0182: * @return true or false
0183: */
0184:
0185: public boolean isClosed() {
0186: return isClosed;
0187: }
0188:
0189: /**
0190: * Return the current ResultSet, if there is a current ResultSet instance.
0191: *
0192: * @return a JDBC ResultSet instance or null if there isn't one.
0193: *
0194: * @throws JPersistException
0195: */
0196:
0197: public ResultSet getResultSet() throws JPersistException {
0198: if (isClosed)
0199: throw new JPersistException(
0200: JPersistException.DATABASE_CLOSED);
0201:
0202: return resultSet;
0203: }
0204:
0205: /**
0206: * Return the current ResultSet, if there is a current ResultSet instance.
0207: *
0208: * @return a JDBC ResultSet instance or null if there isn't one.
0209: *
0210: * @throws JPersistException
0211: */
0212:
0213: public Database getDatabase() throws JPersistException {
0214: if (isClosed)
0215: throw new JPersistException(
0216: JPersistException.DATABASE_CLOSED);
0217:
0218: return db;
0219: }
0220:
0221: /**
0222: * Returns the current statement or null if no statement is active.
0223: *
0224: * @return a JDBC statement
0225: *
0226: * @throws JPersistException
0227: */
0228:
0229: public Statement getStatement() throws JPersistException {
0230: if (isClosed)
0231: throw new JPersistException(
0232: JPersistException.DATABASE_CLOSED);
0233:
0234: try {
0235: return resultSet.getStatement();
0236: } catch (Exception e) {
0237: throw new JPersistException(e);
0238: }
0239: }
0240:
0241: /**
0242: * See same in java.sql.Statement
0243: *
0244: * @see java.sql.Statement
0245: */
0246:
0247: public boolean getMoreResults() throws JPersistException {
0248: if (isClosed)
0249: throw new JPersistException(
0250: JPersistException.DATABASE_CLOSED);
0251:
0252: logger.finer("Attempting to get more results");
0253:
0254: try {
0255: Statement statement = getStatement();
0256:
0257: if (statement != null && statement.getMoreResults()) {
0258: resultSet = statement.getResultSet();
0259:
0260: boolean beforeFirst = resultSet.isBeforeFirst(), afterLast = resultSet
0261: .isAfterLast();
0262: resultSetIsEmpty = !(beforeFirst || afterLast)
0263: || (beforeFirst && afterLast);
0264:
0265: return true;
0266: }
0267:
0268: resultSet = null;
0269: resultSetIsEmpty = false;
0270:
0271: return false;
0272: } catch (Exception e) {
0273: throw new JPersistException(e);
0274: }
0275: }
0276:
0277: /**
0278: * See same in java.sql.Statement
0279: *
0280: * @see java.sql.Statement
0281: */
0282:
0283: public boolean getMoreResults(int doWhatWithCurrent)
0284: throws JPersistException {
0285: if (isClosed)
0286: throw new JPersistException(
0287: JPersistException.DATABASE_CLOSED);
0288:
0289: logger.finer("Attempting to get more results");
0290:
0291: try {
0292: Statement statement = getStatement();
0293:
0294: if (statement != null
0295: && statement.getMoreResults(doWhatWithCurrent)) {
0296: resultSet = statement.getResultSet();
0297:
0298: boolean beforeFirst = resultSet.isBeforeFirst(), afterLast = resultSet
0299: .isAfterLast();
0300: resultSetIsEmpty = !(beforeFirst || afterLast)
0301: || (beforeFirst && afterLast);
0302:
0303: return true;
0304: }
0305:
0306: resultSet = null;
0307: resultSetIsEmpty = false;
0308:
0309: return false;
0310: } catch (Exception e) {
0311: throw new JPersistException(e);
0312: }
0313: }
0314:
0315: /**
0316: * Load an instance of the class (using set methods that match columns in a table matched to the class name)
0317: * with the results of the current ResultSet row.
0318: *
0319: * @param cs any class with an empty constructor
0320: *
0321: * @return a new instance of cs
0322: *
0323: * @throws JPersistException
0324: */
0325:
0326: public <C> C loadObject(Class<C> cs) throws JPersistException {
0327: return loadObject(cs, true);
0328: }
0329:
0330: /**
0331: * Load an instance of the class (using set methods that match columns in a table matched to the class name)
0332: * with the results of the current ResultSet row.
0333: *
0334: * @param cs any class with an empty constructor
0335: * @param loadAssociations true to load associations
0336: *
0337: * @return a new instance of cs
0338: *
0339: * @throws JPersistException
0340: */
0341:
0342: public <C> C loadObject(Class<C> cs, boolean loadAssociations)
0343: throws JPersistException {
0344: try {
0345: return loadObject(cs.newInstance(), loadAssociations);
0346: } catch (Exception ex) {
0347: throw new JPersistException(ex);
0348: }
0349: }
0350:
0351: /**
0352: * Load the object (using set methods that match columns in a table matched to the class name)
0353: * with the results of the current ResultSet row.
0354: *
0355: * @param object any Object (POJO, PersistentObject, etc.)
0356: *
0357: * @return the object passed in
0358: *
0359: * @throws JPersistException
0360: */
0361:
0362: public <C> C loadObject(C object) throws JPersistException {
0363: return loadObject(object, true);
0364: }
0365:
0366: /**
0367: * Load the object (using set methods that match columns in a table matched to the class name)
0368: * with the results of the current ResultSet row.
0369: *
0370: * @param object any Object (POJO, PersistentObject, etc.)
0371: * @param loadAssociations true to load associations
0372: *
0373: * @return the object passed in
0374: *
0375: * @throws JPersistException
0376: */
0377:
0378: public <C> C loadObject(C object, boolean loadAssociations)
0379: throws JPersistException {
0380: if (isClosed)
0381: throw new JPersistException(
0382: JPersistException.DATABASE_CLOSED);
0383:
0384: try {
0385: return (C) ObjectSupport.loadObject(this , object,
0386: loadAssociations);
0387: } catch (Exception e) {
0388: throw new JPersistException(e);
0389: }
0390: }
0391:
0392: /**
0393: * Loads objects (using set methods that match columns in a table matched to the class name)
0394: * into a collection with the results of the current ResultSet.
0395: *
0396: * @param collection an instance of Collection (i.e. Vector, Set, etc.)
0397: * @param cs any class with an empty constructor
0398: *
0399: * @return the collection passed in
0400: *
0401: * @throws JPersistException
0402: */
0403:
0404: public <C> Collection<C> loadObjects(Collection<C> collection,
0405: Class<C> cs) throws JPersistException {
0406: return loadObjects(collection, cs, true);
0407: }
0408:
0409: /**
0410: * Loads objects (using set methods that match columns in a table matched to the class name)
0411: * into a collection with the results of the current ResultSet.
0412: *
0413: * @param collection an instance of Collection (i.e. Vector, Set, etc.)
0414: * @param cs any class with an empty constructor
0415: * @param loadAssociations true to load associations
0416: *
0417: * @return the collection passed in
0418: *
0419: * @throws JPersistException
0420: */
0421:
0422: public <C> Collection<C> loadObjects(Collection<C> collection,
0423: Class<C> cs, boolean loadAssociations)
0424: throws JPersistException {
0425: if (isClosed)
0426: throw new JPersistException(
0427: JPersistException.DATABASE_CLOSED);
0428:
0429: try {
0430: while (hasNext())
0431: collection.add((C) next(loadAssociations));
0432: } catch (Exception e) {
0433: throw new JPersistException(e);
0434: }
0435:
0436: return collection;
0437: }
0438:
0439: /**
0440: * Loads an objects associations.
0441: *
0442: * @param object the object whose associations are to be loaded
0443: *
0444: * @throws jpersist.JPersistException
0445: */
0446: public void loadAssociations(Object object)
0447: throws JPersistException {
0448: if (isClosed)
0449: throw new JPersistException(
0450: JPersistException.DATABASE_CLOSED);
0451:
0452: try {
0453: ObjectSupport.loadAssociations(db, object);
0454: } catch (Exception e) {
0455: throw new JPersistException(e);
0456: }
0457: }
0458:
0459: /**
0460: * See same in java.sql.ResultSet
0461: *
0462: * @see java.sql.ResultSet
0463: */
0464:
0465: public void moveToCurrentRow() throws JPersistException {
0466: if (isClosed)
0467: throw new JPersistException(
0468: JPersistException.DATABASE_CLOSED);
0469:
0470: try {
0471: getResultSet().moveToCurrentRow();
0472: } catch (Exception e) {
0473: throw new JPersistException(e);
0474: }
0475: }
0476:
0477: /**
0478: * See same in java.sql.ResultSet
0479: *
0480: * @see java.sql.ResultSet
0481: */
0482:
0483: public void moveToInsertRow() throws JPersistException {
0484: if (isClosed)
0485: throw new JPersistException(
0486: JPersistException.DATABASE_CLOSED);
0487:
0488: try {
0489: if (getResultSet() != null)
0490: getResultSet().moveToInsertRow();
0491: } catch (Exception e) {
0492: throw new JPersistException(e);
0493: }
0494: }
0495:
0496: /**
0497: * See same in java.sql.ResultSet
0498: *
0499: * @see java.sql.ResultSet
0500: */
0501:
0502: public void insertRow() throws JPersistException {
0503: if (isClosed)
0504: throw new JPersistException(
0505: JPersistException.DATABASE_CLOSED);
0506:
0507: try {
0508: getResultSet().insertRow();
0509: } catch (Exception e) {
0510: throw new JPersistException(e);
0511: }
0512: }
0513:
0514: /**
0515: * See same in java.sql.ResultSet
0516: *
0517: * @see java.sql.ResultSet
0518: */
0519:
0520: public boolean rowInserted() throws JPersistException {
0521: if (isClosed)
0522: throw new JPersistException(
0523: JPersistException.DATABASE_CLOSED);
0524:
0525: try {
0526: return getResultSet().rowInserted();
0527: } catch (Exception e) {
0528: throw new JPersistException(e);
0529: }
0530: }
0531:
0532: /**
0533: * See same in java.sql.ResultSet
0534: *
0535: * @see java.sql.ResultSet
0536: */
0537:
0538: public void deleteRow() throws JPersistException {
0539: if (isClosed)
0540: throw new JPersistException(
0541: JPersistException.DATABASE_CLOSED);
0542:
0543: try {
0544: getResultSet().deleteRow();
0545: } catch (Exception e) {
0546: throw new JPersistException(e);
0547: }
0548: }
0549:
0550: /**
0551: * See same in java.sql.ResultSet
0552: *
0553: * @see java.sql.ResultSet
0554: */
0555:
0556: public boolean rowDeleted() throws JPersistException {
0557: if (isClosed)
0558: throw new JPersistException(
0559: JPersistException.DATABASE_CLOSED);
0560:
0561: try {
0562: return getResultSet().rowDeleted();
0563: } catch (Exception e) {
0564: throw new JPersistException(e);
0565: }
0566: }
0567:
0568: /**
0569: * See same in java.sql.ResultSet
0570: *
0571: * @see java.sql.ResultSet
0572: */
0573:
0574: public void updateRow() throws JPersistException {
0575: if (isClosed)
0576: throw new JPersistException(
0577: JPersistException.DATABASE_CLOSED);
0578:
0579: try {
0580: getResultSet().updateRow();
0581: } catch (Exception e) {
0582: throw new JPersistException(e);
0583: }
0584: }
0585:
0586: /**
0587: * See same in java.sql.ResultSet
0588: *
0589: * @see java.sql.ResultSet
0590: */
0591:
0592: public boolean rowUpdated() throws JPersistException {
0593: if (isClosed)
0594: throw new JPersistException(
0595: JPersistException.DATABASE_CLOSED);
0596:
0597: try {
0598: return getResultSet().rowUpdated();
0599: } catch (Exception e) {
0600: throw new JPersistException(e);
0601: }
0602: }
0603:
0604: /**
0605: * See same in java.sql.ResultSet
0606: *
0607: * @see java.sql.ResultSet
0608: */
0609:
0610: public void setFetchDirection(int direction)
0611: throws JPersistException {
0612: if (isClosed)
0613: throw new JPersistException(
0614: JPersistException.DATABASE_CLOSED);
0615:
0616: if (logger.isLoggable(Level.FINER))
0617: logger.finer("Setting fetch direction = " + direction);
0618:
0619: try {
0620: getResultSet().setFetchDirection(direction);
0621: } catch (Exception e) {
0622: throw new JPersistException(e);
0623: }
0624: }
0625:
0626: /**
0627: * See same in java.sql.ResultSet
0628: *
0629: * @see java.sql.ResultSet
0630: */
0631:
0632: public boolean first() throws JPersistException {
0633: if (isClosed)
0634: throw new JPersistException(
0635: JPersistException.DATABASE_CLOSED);
0636:
0637: try {
0638: return getResultSet().first();
0639: } catch (Exception e) {
0640: throw new JPersistException(e);
0641: }
0642: }
0643:
0644: /**
0645: * See same in java.sql.ResultSet
0646: *
0647: * @see java.sql.ResultSet
0648: */
0649:
0650: public boolean isFirst() throws JPersistException {
0651: if (isClosed)
0652: throw new JPersistException(
0653: JPersistException.DATABASE_CLOSED);
0654:
0655: try {
0656: return getResultSet().isFirst();
0657: } catch (Exception e) {
0658: throw new JPersistException(e);
0659: }
0660: }
0661:
0662: /**
0663: * See same in java.sql.ResultSet
0664: *
0665: * @see java.sql.ResultSet
0666: */
0667:
0668: public void beforeFirst() throws JPersistException {
0669: if (isClosed)
0670: throw new JPersistException(
0671: JPersistException.DATABASE_CLOSED);
0672:
0673: try {
0674: getResultSet().beforeFirst();
0675: } catch (Exception e) {
0676: throw new JPersistException(e);
0677: }
0678: }
0679:
0680: /**
0681: * See same in java.sql.ResultSet
0682: *
0683: * @see java.sql.ResultSet
0684: */
0685:
0686: public boolean isBeforeFirst() throws JPersistException {
0687: if (isClosed)
0688: throw new JPersistException(
0689: JPersistException.DATABASE_CLOSED);
0690:
0691: try {
0692: return getResultSet().isBeforeFirst();
0693: } catch (Exception e) {
0694: throw new JPersistException(e);
0695: }
0696: }
0697:
0698: /**
0699: * See same in java.sql.ResultSet
0700: *
0701: * @see java.sql.ResultSet
0702: */
0703:
0704: public boolean last() throws JPersistException {
0705: if (isClosed)
0706: throw new JPersistException(
0707: JPersistException.DATABASE_CLOSED);
0708:
0709: try {
0710: return getResultSet().last();
0711: } catch (Exception e) {
0712: throw new JPersistException(e);
0713: }
0714: }
0715:
0716: /**
0717: * See same in java.sql.ResultSet
0718: *
0719: * @see java.sql.ResultSet
0720: */
0721:
0722: public boolean isLast() throws JPersistException {
0723: if (isClosed)
0724: throw new JPersistException(
0725: JPersistException.DATABASE_CLOSED);
0726:
0727: try {
0728: return getResultSet().isLast();
0729: } catch (Exception e) {
0730: throw new JPersistException(e);
0731: }
0732: }
0733:
0734: /**
0735: * See same in java.sql.ResultSet
0736: *
0737: * @see java.sql.ResultSet
0738: */
0739:
0740: public void afterLast() throws JPersistException {
0741: if (isClosed)
0742: throw new JPersistException(
0743: JPersistException.DATABASE_CLOSED);
0744:
0745: try {
0746: getResultSet().afterLast();
0747: } catch (Exception e) {
0748: throw new JPersistException(e);
0749: }
0750: }
0751:
0752: /**
0753: * See same in java.sql.ResultSet
0754: *
0755: * @see java.sql.ResultSet
0756: */
0757:
0758: public boolean isAfterLast() throws JPersistException {
0759: if (isClosed)
0760: throw new JPersistException(
0761: JPersistException.DATABASE_CLOSED);
0762:
0763: try {
0764: return getResultSet().isAfterLast();
0765: } catch (Exception e) {
0766: throw new JPersistException(e);
0767: }
0768: }
0769:
0770: /**
0771: * See same in java.sql.ResultSet
0772: *
0773: * @see java.sql.ResultSet
0774: */
0775:
0776: public void refreshRow() throws JPersistException {
0777: if (isClosed)
0778: throw new JPersistException(
0779: JPersistException.DATABASE_CLOSED);
0780:
0781: try {
0782: getResultSet().refreshRow();
0783: } catch (Exception e) {
0784: throw new JPersistException(e);
0785: }
0786: }
0787:
0788: /**
0789: * See same in java.sql.ListIterator
0790: *
0791: * @see java.util.ListIterator
0792: */
0793:
0794: public boolean hasNext() {
0795: try {
0796: ResultSet resultSet = getResultSet();
0797:
0798: return !resultSetIsEmpty
0799: && (resultSet.isBeforeFirst() || !resultSet
0800: .isLast());
0801: } catch (Exception e) {
0802: throw new RuntimeException(e);
0803: }
0804: }
0805:
0806: /**
0807: * Returns the next record. If object is non-null, it is loaded with
0808: * matching data. If the object is null, then if class is defined, a new
0809: * instance will be loaded and returned. If object is null and class is not
0810: * defined, then this (Result) is returned. If there is no next
0811: * record, then null is returned.
0812: *
0813: * This method performs as defined in ListIterator with the following
0814: * exception: if type is TYPE_FORWARD_ONLY, then null is returned. This
0815: * allows the next method to perform similar to ResultSet.next(), with
0816: * next() != null instead of next() != false, which is the case with
0817: * ResultSet.next().
0818: *
0819: * @return the loaded object
0820: *
0821: * @see java.util.ListIterator
0822: */
0823:
0824: public T next() {
0825: return next(true);
0826: }
0827:
0828: /**
0829: * Returns the next record. If object is non-null, it is loaded with
0830: * matching data. If the object is null, then if class is defined, a new
0831: * instance will be loaded and returned. If object is null and class is not
0832: * defined, then this (Result) is returned. If there is no next
0833: * record, then null is returned.
0834: *
0835: * This method performs as defined in ListIterator with the following
0836: * exception: if type is TYPE_FORWARD_ONLY, then null is returned. This
0837: * allows the next method to perform similar to ResultSet.next(), with
0838: * next() != null instead of next() != false, which is the case with
0839: * ResultSet.next().
0840: *
0841: * @param loadAssociations load the objects associations
0842: *
0843: * @return the loaded object
0844: *
0845: * @see java.util.ListIterator
0846: */
0847:
0848: public T next(boolean loadAssociations) {
0849: return next(null, loadAssociations);
0850: }
0851:
0852: /**
0853: * Returns the next record. If object is non-null, it is loaded with
0854: * matching data. If the object is null, then if class is defined, a new
0855: * instance will be loaded and returned. If object is null and class is not
0856: * defined, then this (Result) is returned. If there is no next
0857: * record, then null is returned.
0858: *
0859: * This method performs as defined in ListIterator with the following
0860: * exception: if type is TYPE_FORWARD_ONLY, then null is returned. This
0861: * allows the next method to perform similar to ResultSet.next(), with
0862: * next() != null instead of next() != false, which is the case with
0863: * ResultSet.next().
0864: *
0865: * @param object the object to load
0866: *
0867: * @return the loaded object
0868: *
0869: * @see java.util.ListIterator
0870: */
0871:
0872: public T next(T object) {
0873: return next(object, true);
0874: }
0875:
0876: /**
0877: * Returns the next record. If object is non-null, it is loaded with
0878: * matching data. If the object is null, then if class is defined, a new
0879: * instance will be loaded and returned. If object is null and class is not
0880: * defined, then this (Result) is returned. If there is no next
0881: * record, then null is returned.
0882: *
0883: * This method performs as defined in ListIterator with the following
0884: * exception: if type is TYPE_FORWARD_ONLY, then null is returned. This
0885: * allows the next method to perform similar to ResultSet.next(), with
0886: * next() != null instead of next() != false, which is the case with
0887: * ResultSet.next().
0888: *
0889: * @param object the object to load
0890: * @param loadAssociations load the objects associations
0891: *
0892: * @return the loaded object
0893: *
0894: * @see java.util.ListIterator
0895: */
0896:
0897: public T next(T object, boolean loadAssociations) {
0898: try {
0899: ResultSet resultSet = getResultSet();
0900:
0901: if (resultSet.next()) {
0902: if (cs == null && object == null)
0903: return (T) this ;
0904: else
0905: return loadObject(object == null ? cs.newInstance()
0906: : object, loadAssociations);
0907: }
0908:
0909: if (resultSet.getType() == ResultSet.TYPE_FORWARD_ONLY)
0910: return null;
0911: } catch (Exception e) {
0912: throw new RuntimeException(e);
0913: }
0914:
0915: throw new NoSuchElementException();
0916: }
0917:
0918: /**
0919: * See same in java.sql.ListIterator
0920: *
0921: * @see java.util.ListIterator
0922: */
0923:
0924: public boolean hasPrevious() {
0925: try {
0926: ResultSet resultSet = getResultSet();
0927:
0928: return !resultSetIsEmpty
0929: && (resultSet.isAfterLast() || !resultSet.isFirst());
0930: } catch (Exception e) {
0931: throw new RuntimeException(e);
0932: }
0933: }
0934:
0935: /**
0936: * Returns the previous record. If object is non-null, it is loaded with
0937: * matching data. If the object is null, then if class is defined, a new
0938: * instance will be loaded and returned. If the object is null and class is
0939: * not defined, then this (Result) is returned. If there is no previous
0940: * record, then null is returned.
0941: *
0942: * @return the loaded object
0943: *
0944: * @see java.util.ListIterator
0945: */
0946: public T previous() {
0947: return previous(true);
0948: }
0949:
0950: /**
0951: * Returns the previous record. If object is non-null, it is loaded with
0952: * matching data. If the object is null, then if class is defined, a new
0953: * instance will be loaded and returned. If the object is null and class is
0954: * not defined, then this (Result) is returned. If there is no previous
0955: * record, then null is returned.
0956: *
0957: * @param loadAssociations load the objects associations
0958: *
0959: * @return the loaded object
0960: *
0961: * @see java.util.ListIterator
0962: */
0963: public T previous(boolean loadAssociations) {
0964: return previous(null, loadAssociations);
0965: }
0966:
0967: /**
0968: * Returns the previous record. If object is non-null, it is loaded with
0969: * matching data. If the object is null, then if class is defined, a new
0970: * instance will be loaded and returned. If the object is null and class is
0971: * not defined, then this (Result) is returned. If there is no previous
0972: * record, then null is returned.
0973: *
0974: * @param object the object to load
0975: *
0976: * @return the loaded object
0977: *
0978: * @see java.util.ListIterator
0979: */
0980: public T previous(T object) {
0981: return previous(object, true);
0982: }
0983:
0984: /**
0985: * Returns the previous record. If object is non-null, it is loaded with
0986: * matching data. If the object is null, then if class is defined, a new
0987: * instance will be loaded and returned. If the object is null and class is
0988: * not defined, then this (Result) is returned. If there is no previous
0989: * record, then null is returned.
0990: *
0991: * @param object the object to load
0992: * @param loadAssociations load the objects associations
0993: *
0994: * @return the loaded object
0995: *
0996: * @see java.util.ListIterator
0997: */
0998: public T previous(T object, boolean loadAssociations) {
0999: try {
1000: if (getResultSet().previous()) {
1001: if (cs == null && object == null)
1002: return (T) this ;
1003: else
1004: return loadObject(object == null ? cs.newInstance()
1005: : object, loadAssociations);
1006: }
1007: } catch (Exception e) {
1008: throw new RuntimeException(e);
1009: }
1010:
1011: throw new NoSuchElementException();
1012: }
1013:
1014: /**
1015: * See same in java.sql.ListIterator
1016: *
1017: * @see java.util.ListIterator
1018: */
1019:
1020: public int nextIndex() {
1021: try {
1022: if (hasNext())
1023: return getResultSet().getRow() + 1;
1024: } catch (Exception ex) {
1025: throw new RuntimeException(ex);
1026: }
1027:
1028: return -1;
1029: }
1030:
1031: /**
1032: * See same in java.sql.ListIterator
1033: *
1034: * @see java.util.ListIterator
1035: */
1036:
1037: public int previousIndex() {
1038: try {
1039: if (hasPrevious())
1040: return getResultSet().getRow() - 1;
1041: } catch (Exception ex) {
1042: throw new RuntimeException(ex);
1043: }
1044:
1045: return -1;
1046: }
1047:
1048: /**
1049: * See same in java.sql.ListIterator
1050: *
1051: * @see java.util.ListIterator
1052: */
1053:
1054: public void remove() {
1055: try {
1056: deleteRow();
1057: } catch (Exception e) {
1058: throw new RuntimeException(e);
1059: }
1060: }
1061:
1062: /**
1063: * See same in java.sql.ListIterator. Not supported, and no need to.
1064: *
1065: * @throws UnsupportedOperationException
1066: */
1067:
1068: public void add(Object o) {
1069: throw new UnsupportedOperationException();
1070: }
1071:
1072: /**
1073: * See same in java.sql.ListIterator. Not supported, and no need to.
1074: *
1075: * @throws UnsupportedOperationException
1076: */
1077:
1078: public void set(Object o) {
1079: throw new UnsupportedOperationException();
1080: }
1081:
1082: /**
1083: * Returns the object defined by named column from the current row in the result set.
1084: *
1085: * @param columnName the column name
1086: *
1087: * @return the object
1088: *
1089: * @throws JPersistException
1090: */
1091:
1092: public <C> C getColumnValue(String columnName)
1093: throws JPersistException {
1094: if (isClosed)
1095: throw new JPersistException(
1096: JPersistException.DATABASE_CLOSED);
1097:
1098: try {
1099: return (C) getResultSet().getObject(columnName);
1100: } catch (Exception e) {
1101: throw new JPersistException(e);
1102: }
1103: }
1104:
1105: /**
1106: * Returns the object (after converting it to returnType) defined by named column from the current row in the result set.
1107: *
1108: * @param returnType converts the return type to returnType
1109: * @param columnName the column name
1110: *
1111: * @return the object
1112: *
1113: * @throws JPersistException
1114: */
1115:
1116: public <C> C getColumnValue(Class<C> returnType, String columnName)
1117: throws JPersistException {
1118: if (isClosed)
1119: throw new JPersistException(
1120: JPersistException.DATABASE_CLOSED);
1121:
1122: try {
1123: Object value = null;
1124:
1125: if (returnType != null)
1126: if (returnType == Array.class)
1127: value = getResultSet().getArray(columnName);
1128: else if (returnType == BigDecimal.class)
1129: value = getResultSet().getBigDecimal(columnName);
1130: else if (returnType == Blob.class)
1131: value = getResultSet().getBlob(columnName);
1132: else if (returnType == Clob.class)
1133: value = getResultSet().getClob(columnName);
1134: else if (returnType == Date.class)
1135: value = getResultSet().getDate(columnName);
1136: else if (returnType == InputStream.class) {
1137: throw new JPersistException(
1138: "Must use jpersist.interfaces.AsciiStream or jpersist.interfaces.BinaryStream instead of InputStream");
1139: } else if (returnType
1140: .isAssignableFrom(AsciiStream.class))
1141: value = new AsciiStreamAdapter(-1, getResultSet()
1142: .getAsciiStream(columnName));
1143: else if (returnType
1144: .isAssignableFrom(BinaryStream.class))
1145: value = new BinaryStreamAdapter(-1, getResultSet()
1146: .getBinaryStream(columnName));
1147: else if (returnType == Reader.class) {
1148: throw new JPersistException(
1149: "Must use jpersist.interfaces.ReaderHandler instead of Reader");
1150: } else if (returnType
1151: .isAssignableFrom(CharacterStream.class))
1152: value = new CharacterStreamAdapter(-1,
1153: getResultSet().getCharacterStream(
1154: columnName));
1155: else if (returnType == Ref.class)
1156: value = getResultSet().getRef(columnName);
1157: else if (returnType == String.class)
1158: value = getResultSet().getString(columnName);
1159: else if (returnType == Time.class)
1160: value = getResultSet().getTime(columnName);
1161: else if (returnType == Timestamp.class)
1162: value = getResultSet().getTimestamp(columnName);
1163: else if (returnType == URL.class)
1164: value = getResultSet().getURL(columnName);
1165:
1166: if (value == null)
1167: value = getResultSet().getObject(columnName);
1168:
1169: return (C) value;
1170: } catch (Exception e) {
1171: throw new JPersistException(e);
1172: }
1173: }
1174:
1175: /**
1176: * Returns the object defined by column index from the current row in the result set.
1177: *
1178: * @param columnIndex the column index
1179: *
1180: * @return the object
1181: *
1182: * @throws JPersistException
1183: */
1184:
1185: public <C> C getColumnValue(int columnIndex)
1186: throws JPersistException {
1187: if (isClosed)
1188: throw new JPersistException(
1189: JPersistException.DATABASE_CLOSED);
1190:
1191: try {
1192: return (C) getResultSet().getObject(columnIndex);
1193: } catch (Exception e) {
1194: throw new JPersistException(e);
1195: }
1196: }
1197:
1198: /**
1199: * Returns the object (after converting it to returnType) defined by named column from the current row in the result set.
1200: *
1201: * @param returnType converts the return type to returnType
1202: * @param columnIndex the column index
1203: *
1204: * @return the object
1205: *
1206: * @throws JPersistException
1207: */
1208:
1209: public <C> C getColumnValue(Class<C> returnType, int columnIndex)
1210: throws JPersistException {
1211: if (isClosed)
1212: throw new JPersistException(
1213: JPersistException.DATABASE_CLOSED);
1214:
1215: try {
1216: Object value = null;
1217:
1218: if (returnType != null)
1219: if (returnType == Array.class)
1220: value = getResultSet().getArray(columnIndex);
1221: else if (returnType == BigDecimal.class)
1222: value = getResultSet().getBigDecimal(columnIndex);
1223: else if (returnType == Blob.class)
1224: value = getResultSet().getBlob(columnIndex);
1225: else if (returnType == Clob.class)
1226: value = getResultSet().getClob(columnIndex);
1227: else if (returnType == Date.class)
1228: value = getResultSet().getDate(columnIndex);
1229: else if (returnType == InputStream.class) {
1230: throw new JPersistException(
1231: "Must use jpersist.interfaces.AsciiStream or jpersist.interfaces.BinaryStream instead of InputStream");
1232: } else if (returnType
1233: .isAssignableFrom(AsciiStream.class))
1234: value = new AsciiStreamAdapter(-1, getResultSet()
1235: .getAsciiStream(columnIndex));
1236: else if (returnType
1237: .isAssignableFrom(BinaryStream.class))
1238: value = new BinaryStreamAdapter(-1, getResultSet()
1239: .getBinaryStream(columnIndex));
1240: else if (returnType == Reader.class) {
1241: throw new JPersistException(
1242: "Must use jpersist.interfaces.ReaderHandler instead of Reader");
1243: } else if (returnType
1244: .isAssignableFrom(CharacterStream.class))
1245: value = new CharacterStreamAdapter(-1,
1246: getResultSet().getCharacterStream(
1247: columnIndex));
1248: else if (returnType == Ref.class)
1249: value = getResultSet().getRef(columnIndex);
1250: else if (returnType == String.class)
1251: value = getResultSet().getString(columnIndex);
1252: else if (returnType == Time.class)
1253: value = getResultSet().getTime(columnIndex);
1254: else if (returnType == Timestamp.class)
1255: value = getResultSet().getTimestamp(columnIndex);
1256: else if (returnType == URL.class)
1257: value = getResultSet().getURL(columnIndex);
1258:
1259: if (value == null)
1260: value = getResultSet().getObject(columnIndex);
1261:
1262: return (C) value;
1263: } catch (Exception e) {
1264: throw new JPersistException(e);
1265: }
1266: }
1267:
1268: /**
1269: * Sets the object value defined by column name in the current row in the result set.
1270: *
1271: * @param columnName the column name
1272: * @param object the object being stored in the database
1273: *
1274: * @throws JPersistException
1275: */
1276:
1277: public void setColumnValue(String columnName, Object object)
1278: throws JPersistException {
1279: if (isClosed)
1280: throw new JPersistException(
1281: JPersistException.DATABASE_CLOSED);
1282:
1283: try {
1284: if (object instanceof Array)
1285: resultSet.updateArray(columnName, (Array) object);
1286: else if (object instanceof BigDecimal)
1287: resultSet.updateBigDecimal(columnName,
1288: (BigDecimal) object);
1289: else if (object instanceof Blob)
1290: resultSet.updateBlob(columnName, (Blob) object);
1291: else if (object instanceof Clob)
1292: resultSet.updateClob(columnName, (Clob) object);
1293: else if (object instanceof Date)
1294: resultSet.updateDate(columnName, (Date) object);
1295: else if (object instanceof InputStream) {
1296: throw new JPersistException(
1297: "Must use jpersist.interfaces.AsciiStream or jpersist.interfaces.BinaryStream instead of InputStream");
1298: } else if (object instanceof AsciiStream)
1299: resultSet.updateAsciiStream(columnName,
1300: ((AsciiStream) object).getInputStream(),
1301: ((AsciiStream) object).getLength());
1302: else if (object instanceof BinaryStream)
1303: resultSet.updateBinaryStream(columnName,
1304: ((BinaryStream) object).getInputStream(),
1305: ((BinaryStream) object).getLength());
1306: else if (object instanceof Reader) {
1307: throw new JPersistException(
1308: "Must use jpersist.interfaces.ReaderHandler instead of Reader");
1309: } else if (object instanceof CharacterStream)
1310: resultSet.updateCharacterStream(columnName,
1311: ((CharacterStream) object).getReader(),
1312: ((CharacterStream) object).getLength());
1313: else if (object instanceof Ref)
1314: resultSet.updateRef(columnName, (Ref) object);
1315: else if (object instanceof String)
1316: resultSet.updateString(columnName, (String) object);
1317: else if (object instanceof Time)
1318: resultSet.updateTime(columnName, (Time) object);
1319: else if (object instanceof Timestamp)
1320: resultSet.updateTimestamp(columnName,
1321: (Timestamp) object);
1322: //else if (object instanceof URL)
1323: // resultSet.updateURL(columnName, (URL)object);
1324: else
1325: resultSet.updateObject(columnName, object);
1326: } catch (Exception e) {
1327: throw new JPersistException(e);
1328: }
1329: }
1330:
1331: /**
1332: * Sets the object value defined by column index in the current row in the result set.
1333: *
1334: * @param columnIndex the column number
1335: * @param object the object being stored in the database
1336: * @throws JPersistException
1337: */
1338:
1339: public void setColumnValue(int columnIndex, Object object)
1340: throws JPersistException {
1341: if (isClosed)
1342: throw new JPersistException(
1343: JPersistException.DATABASE_CLOSED);
1344:
1345: try {
1346: if (object instanceof Array)
1347: resultSet.updateArray(columnIndex, (Array) object);
1348: else if (object instanceof BigDecimal)
1349: resultSet.updateBigDecimal(columnIndex,
1350: (BigDecimal) object);
1351: else if (object instanceof Blob)
1352: resultSet.updateBlob(columnIndex, (Blob) object);
1353: else if (object instanceof Clob)
1354: resultSet.updateClob(columnIndex, (Clob) object);
1355: else if (object instanceof Date)
1356: resultSet.updateDate(columnIndex, (Date) object);
1357: else if (object instanceof InputStream) {
1358: throw new JPersistException(
1359: "Must use jpersist.interfaces.AsciiStream or jpersist.interfaces.BinaryStream instead of InputStream");
1360: } else if (object instanceof AsciiStream)
1361: resultSet.updateAsciiStream(columnIndex,
1362: ((AsciiStream) object).getInputStream(),
1363: ((AsciiStream) object).getLength());
1364: else if (object instanceof BinaryStream)
1365: resultSet.updateBinaryStream(columnIndex,
1366: ((BinaryStream) object).getInputStream(),
1367: ((BinaryStream) object).getLength());
1368: else if (object instanceof Reader) {
1369: throw new JPersistException(
1370: "Must use jpersist.interfaces.ReaderHandler instead of Reader");
1371: } else if (object instanceof CharacterStream)
1372: resultSet.updateCharacterStream(columnIndex,
1373: ((CharacterStream) object).getReader(),
1374: ((CharacterStream) object).getLength());
1375: else if (object instanceof Ref)
1376: resultSet.updateRef(columnIndex, (Ref) object);
1377: else if (object instanceof String)
1378: resultSet.updateString(columnIndex, (String) object);
1379: else if (object instanceof Time)
1380: resultSet.updateTime(columnIndex, (Time) object);
1381: else if (object instanceof Timestamp)
1382: resultSet.updateTimestamp(columnIndex,
1383: (Timestamp) object);
1384: //else if (object instanceof URL)
1385: // resultSet.updateURL(columnIndex, (URL)object);
1386: else
1387: resultSet.updateObject(columnIndex, object);
1388: } catch (Exception e) {
1389: throw new JPersistException(e);
1390: }
1391: }
1392:
1393: /**
1394: * Casts the result to an interface. Any get methods in the interface
1395: * that can be mapped to the current resultSet will automatically return the
1396: * coresponding value from the current row in the resultSet.
1397: *
1398: * <p>Handlers are objects that provide backing to one or more interface methods.
1399: * jPersist will check the array of objects for an object that can service a
1400: * given method and call that method on the object. If no object is found
1401: * to handle the method it's assumed to be a call to get a column of data
1402: * from the database.
1403: *
1404: * @param interfaceClass the interface to cast the result to
1405: * @param handlers objects that provide backing to one or more interface methods
1406: *
1407: * @return an instance of the interface
1408: *
1409: * @throws JPersistException
1410: */
1411:
1412: public Object castToInterface(Class interfaceClass,
1413: Object... handlers) throws JPersistException {
1414: if (isClosed)
1415: throw new JPersistException(
1416: JPersistException.DATABASE_CLOSED);
1417:
1418: if (logger.isLoggable(Level.FINER))
1419: logger.finer("Casting Result to "
1420: + interfaceClass.getName());
1421:
1422: try {
1423: Object object = Proxy.newProxyInstance(interfaceClass
1424: .getClassLoader(), new Class[] { interfaceClass },
1425: new ResultProxy(this , interfaceClass, handlers));
1426:
1427: if (object == null)
1428: throw new JPersistException(
1429: "Dynamic Proxy Returned null");
1430:
1431: return object;
1432: } catch (Exception e) {
1433: throw new JPersistException(e);
1434: }
1435: }
1436: }
|