0001: package org.julp;
0002:
0003: import java.util.*;
0004: import java.sql.*;
0005: import java.lang.reflect.*;
0006: import javax.sql.DataSource;
0007:
0008: public abstract class DomainObjectFactory implements
0009: java.io.Serializable, Cloneable {
0010:
0011: public DomainObjectFactory() {
0012: if (Boolean.getBoolean("debug-julp")
0013: || Boolean.getBoolean("debug-" + getClass().getName())) {
0014: debug = true;
0015: }
0016: }
0017:
0018: public DomainObjectFactory(boolean synchronizedAccess) {
0019: this .setSynchronizedAccess(synchronizedAccess);
0020: }
0021:
0022: public DomainObjectFactory(Class requestor,
0023: boolean synchronizedAccess) {
0024: this .requestor = requestor;
0025: this .setSynchronizedAccess(synchronizedAccess);
0026: }
0027:
0028: public DomainObjectFactory(Class requestor) {
0029: this .requestor = requestor;
0030: }
0031:
0032: /*================================== members start =======================*/
0033: protected boolean debug = false;
0034:
0035: protected MetaData metaData = null;
0036: /* Mapping of DB Table columns to object fields */
0037: protected Map mapping = null;
0038: /* Object to persist */
0039: protected Class requestor = null;
0040: /* objectId */
0041: protected int objectId = 0;
0042: /* Collection of Objects (data) */
0043: protected List objectList = new ArrayList();
0044: /* Collection of Objects to delete from DB */
0045: protected List removedObjects = new ArrayList();
0046: /* Useful to send only modified objects to another tier */
0047: protected boolean discardUnmodifiedObjects;
0048: /* Set sequence or disable update/insert/delete */
0049: protected char[] dataModificationSequence;
0050: public static final char DATA_MODIFICATION_SEQUENCE_DELETE = 'D';
0051: public static final char DATA_MODIFICATION_SEQUENCE_INSERT = 'I';
0052: public static final char DATA_MODIFICATION_SEQUENCE_UPDATE = 'U';
0053: /* Disable DB modifications*/
0054: protected boolean readOnly = false;
0055:
0056: /* Optimistic lock settings ****************************************/
0057: /* Generates WHERE stastement with key only */
0058: public static final char KEY_COLUMNS = 'K';
0059: /* Generates WHERE stastement with key and columns modified */
0060: public static final char KEY_AND_MODIFIED_COLUMNS = 'M';
0061: /* Generates WHERE stastement with key and all updateble columns - this is
0062: the strictest concurrency check */
0063: public static final char KEY_AND_UPDATEBLE_COLUMNS = 'U';
0064: /* Current Optimistic lock setting.
0065: Default is KEY_COLUMNS (Primary Key only) */
0066: protected char optimisticLock = KEY_COLUMNS;
0067:
0068: /*
0069: Throw exception if PreparedStatement.executeUpdate() does not return 1
0070: for each DomainObject.
0071: It means that the row in DB Table most likely was modified or deleted
0072: by another user/process.
0073: */
0074: protected boolean throwOptimisticLockDeleteException = true;
0075: protected boolean throwOptimisticLockUpdateException = true;
0076: protected boolean throwFailedInsertException = true;
0077:
0078: /* END of Optimistic lock settings *********************************/
0079: /* Target DB catalog */
0080: protected String catalog = null;
0081: /* If overrideCatalogName == true and catalog from this.metaData is null than use catalog member variable */
0082: protected boolean overrideCatalogName = false;
0083: /* Target DB schema */
0084: protected String schema = null;
0085: /* Target DB Table */
0086: protected String table = null;
0087: /* This object generates SQL for data modification */
0088: protected DataWriter dataWriter = null;
0089: /* This is JDBC utility */
0090: protected DBServices dbServices = null;
0091: /* used as argument in method.invoke(obj, EMPTY_READ_ARG)*/
0092: protected Object[] EMPTY_READ_ARG = new Object[0];
0093: /* use synchronized Collections */
0094: protected boolean synchronizedAccess = false;
0095: /* If lazyLoding == true than set only original values vs. original and current */
0096: protected boolean lazyLoading = false;
0097: /* Records per page */
0098: protected int pageSize = 0;
0099: /* Do not execute INSERTS/UPDATES/DELETES - just generate SQL and parameters */
0100: protected boolean generateSQLOnly = false;
0101: /* control if load() append objects to objectList )*/
0102: protected boolean append = false;
0103: /* Some databases (like hsqdb 1.7.1) failed when UPDATE statement is
0104: using TABLE_NAME.COLUMN_NAME in SET clause. INSERT also failed */
0105: protected boolean noFullColumnName = false;
0106: /* Throw Exception or ignore if DomainObject has less fields than mapping */
0107: protected boolean throwMissingFieldException = false;
0108: /* Used to determine if created/deleted/updated DomainObject belongs to this factory*/
0109: protected long domainFactoryId = System.currentTimeMillis(); // ??..
0110: /* if not null object should handle exceptions */
0111: protected ExceptionHandler exceptionHandler;
0112: /* If false suppress exception when call writeData on empty objectList */
0113: protected boolean exceptionOnEmptyObjectList = false;
0114: /* Just a convinient member/method */
0115: protected boolean valid = true;
0116: /* Create and populate MetaData automatically */
0117: protected boolean createDefaultMetaData = true;
0118: /* Get value from ResultSet as specified datatype */
0119: protected Converter converter = null;
0120:
0121: /*================================== members end==========================*/
0122:
0123: public int load(ResultSet[] rs) throws java.sql.SQLException {
0124: boolean origAppend = this .isAppend();
0125: this .setAppend(true);
0126: int rowCount = 0;
0127: if (debug)
0128: System.out.println("julp @@@@@@@@@@@@@@ rs.length: "
0129: + rs.length);
0130: if (debug)
0131: System.out.println("julp @@@@@@@@@@@@@@ rs: "
0132: + Arrays.asList(rs));
0133:
0134: for (int i = 0; i < rs.length; i++) {
0135: if (debug)
0136: System.out.println("julp @@@@@@@@@@@@@@ resultSet[" + i
0137: + "]: " + rs[i]);
0138: rowCount = rowCount + load(rs[i]);
0139: if (debug)
0140: System.out.println("julp @@@@@@@@@@@@@@ rowCount_" + i
0141: + ": " + rowCount);
0142: }
0143: this .setAppend(origAppend);
0144: return rowCount;
0145: }
0146:
0147: public int load(ResultSet rs) throws java.sql.SQLException {
0148: long ts1 = -1;
0149: long ts2 = -1;
0150: String columnName = null;
0151: String fieldName = null;
0152: ResultSetMetaData rsmd = rs.getMetaData();
0153: int rsColCount = rsmd.getColumnCount();
0154: List rsColumns = new ArrayList(rsColCount);
0155: for (int i = 1; i <= rsColCount; i++) {
0156: rsColumns.add(rsmd.getColumnName(i));
0157: }
0158: int columnCount = 0;
0159: if (debug)
0160: System.out.println("julp ============= "
0161: + new java.util.Date() + " " + this .getClass()
0162: + "::" + this + "::load()::requestor class::"
0163: + requestor.getName());
0164: if (!isAppend()) {
0165: this .objectList.clear();
0166: if (debug)
0167: System.out.println("julp ============= "
0168: + new java.util.Date() + " " + this .getClass()
0169: + "::" + this + "::load()::objectId 1: "
0170: + objectId);
0171: this .objectId = 0;
0172: if (debug)
0173: System.out.println("julp ============= "
0174: + new java.util.Date() + " " + this .getClass()
0175: + "::load()::objectId 2: " + objectId);
0176: }
0177: try {
0178: if (debug)
0179: ts1 = System.currentTimeMillis();
0180: if (this .metaData == null) {
0181: populateMetaData();
0182: if (debug)
0183: ts2 = System.currentTimeMillis();
0184: if (debug)
0185: System.out.println("julp ============= "
0186: + new java.util.Date() + " "
0187: + this .getClass() + "::" + this
0188: + "::populateMetaData: " + (ts2 - ts1)
0189: + " ms");
0190: }
0191: columnCount = this .metaData.getColumnCount();
0192: if (debug)
0193: System.out.println("julp ============= "
0194: + new java.util.Date() + " " + this .getClass()
0195: + "::" + this + "::load()::columnCount: "
0196: + columnCount);
0197: if (converter == null) {
0198: converter = new DefaultConverter(rs);
0199: } else {
0200: converter.setResultSet(rs);
0201: }
0202: while (rs.next()) {
0203: DataHolder originalValues = null;
0204: if (!isReadOnly()) {
0205: originalValues = new DataHolder(columnCount);
0206: }
0207: Object domainObject = requestor.newInstance();
0208: if (!isLazyLoading()) {
0209: ((DomainObject) domainObject).setLoading(true);
0210: }
0211: for (int columnIndex = 1; columnIndex <= columnCount; columnIndex++) {
0212: fieldName = this .metaData.getFieldName(columnIndex);
0213: if (debug)
0214: System.out.println("julp ============= "
0215: + new java.util.Date() + " "
0216: + this .getClass() + "::" + this
0217: + "::load()::fieldName: " + fieldName);
0218: if (fieldName != null) { // ResultSet may have more columns then this Object fields, so skip unneeded column
0219: columnName = this .metaData
0220: .getColumnName(columnIndex);
0221: if (!rsColumns.contains(columnName)) {
0222: // ResultSet has less columns then DomainObject fields
0223: this .metaData.setWritable(columnIndex,
0224: false);
0225: continue;
0226: }
0227: String fieldClassName = this .metaData
0228: .getFieldClassName(columnIndex);
0229: Object[] convertedValue = converter.convert(
0230: fieldClassName, columnName);
0231: if (!isReadOnly()) {
0232: originalValues.setFieldNameAndValue(
0233: columnIndex, fieldName,
0234: convertedValue[0]);
0235: }
0236: if (!isLazyLoading() || isReadOnly()) {
0237: this .metaData.getWriteMethod(columnIndex)
0238: .invoke(domainObject,
0239: convertedValue);
0240: }
0241: }
0242: if (debug)
0243: System.out.print("\n");
0244: }
0245: if (!isReadOnly()) {
0246: ((DomainObject) domainObject)
0247: .setOriginalValues(originalValues);
0248: }
0249: if (!isLazyLoading()) {
0250: ((DomainObject) domainObject).setLoading(false);
0251: ((DomainObject) domainObject).setLoaded(true);
0252: }
0253: if (isSynchronizedAccess()) {
0254: ((DomainObject) domainObject).setObjectId(this
0255: .getSyncNextObjectId());
0256: } else {
0257: ((DomainObject) domainObject).setObjectId(this
0258: .getNextObjectId());
0259: }
0260: ((DomainObject) domainObject)
0261: .setPersistentState(DomainObject.ORIGINAL);
0262: ((DomainObject) domainObject)
0263: .setDomainFactoryId(domainFactoryId);
0264: this .objectList.add(domainObject);
0265: }
0266: } catch (InstantiationException ie) {
0267: ie.printStackTrace();
0268: throw new java.sql.SQLException("Cannot Instantiate: "
0269: + requestor);
0270: } catch (IllegalAccessException iae) {
0271: iae.printStackTrace();
0272: throw new java.sql.SQLException(iae.getMessage());
0273: } catch (InvocationTargetException ite) {
0274: ite.printStackTrace();
0275: throw new java.sql.SQLException(ite.getTargetException()
0276: .getMessage());
0277: } catch (Exception e) {
0278: e.printStackTrace();
0279: throw new java.sql.SQLException(e.getMessage());
0280: }
0281: ts2 = System.currentTimeMillis();
0282: if (debug)
0283: System.out.println("julp ============= "
0284: + new java.util.Date() + " " + this .getClass()
0285: + "::" + this + "::load() total: "
0286: + (ts2 - ts1 + " ms"));
0287: return this .objectList.size();
0288: }
0289:
0290: /** Getter for property mapping.
0291: * @return Value of property mapping.
0292: *
0293: */
0294: public Map getMapping() {
0295: return mapping;
0296: }
0297:
0298: /** Setter for property mapping.
0299: * @param mapping New value of property mapping.
0300: *
0301: */
0302: public void setMapping(Map mapping) {
0303: this .mapping = mapping;
0304: }
0305:
0306: public void setMapping(String mapping) {
0307: StringTokenizer tokenizer = new StringTokenizer(mapping, ",",
0308: false);
0309: if (this .mapping == null) {
0310: this .mapping = new Properties();
0311: } else {
0312: this .mapping.clear();
0313: }
0314: while (tokenizer.hasMoreTokens()) {
0315: String token = tokenizer.nextToken();
0316: int idx = token.indexOf("=");
0317: if (idx == -1) {
0318: throw new IllegalArgumentException(
0319: "DomainObjectFactory::setMapping(String mapping): "
0320: + mapping
0321: + "(Argument format: <COLUMN_NAME>=<fieldName>)");
0322: }
0323: this .mapping.put(token.substring(0, idx).trim(), token
0324: .substring(idx + 1).trim());
0325: }
0326: }
0327:
0328: /** Getter for property requestor.
0329: * @return Value of property requestor.
0330: *
0331: */
0332: public java.lang.Class getRequestor() {
0333: return requestor;
0334: }
0335:
0336: /** Setter for property requestor.
0337: * @param requestor New value of property requestor.
0338: *
0339: */
0340: public void setRequestor(java.lang.Class requestor) {
0341: this .requestor = requestor;
0342: }
0343:
0344: public List getPrimaryKey(String catalog, String schema,
0345: String table) throws SQLException {
0346: Object pk = PKCache.getInstance().getPrimaryKey(catalog,
0347: schema, table);
0348: if (pk == null) {
0349: pk = PKCache.getInstance().getPrimaryKey(
0350: this .dbServices.getConnection(), catalog, schema,
0351: table);
0352: }
0353: return (List) pk;
0354: }
0355:
0356: public void setPrimaryKey(String catalog, String schema,
0357: String table, List pk) {
0358: PKCache.getInstance().setPrimaryKey(catalog, schema, table, pk);
0359: }
0360:
0361: public int setObject(DomainObject domainObject) {
0362: int idx = -1;
0363: int id = 0;
0364: if (domainObject.getDomainFactoryId() != domainFactoryId) {
0365: domainObject.setDomainFactoryId(domainFactoryId);
0366: if (isSynchronizedAccess()) {
0367: id = this .getSyncNextObjectId();
0368: domainObject.setObjectId(id);
0369: } else {
0370: id = this .getNextObjectId();
0371: domainObject.setObjectId(id);
0372: }
0373: this .objectList.add(domainObject);
0374: idx = this .objectList.size() + 1;
0375: } else {
0376: id = domainObject.getObjectId();
0377: if (id == 0) { // new object
0378: if (isSynchronizedAccess()) {
0379: id = this .getSyncNextObjectId();
0380: domainObject.setObjectId(id);
0381: } else {
0382: id = this .getNextObjectId();
0383: domainObject.setObjectId(id);
0384: }
0385: this .objectList.add(domainObject);
0386: idx = this .objectList.size() + 1;
0387: } else {
0388: idx = findIdxByObjectId(id);
0389: if (idx > 0) {
0390: this .objectList.set(idx - 1, domainObject);
0391: } else {
0392: this .objectList.add(domainObject);
0393: }
0394: }
0395: }
0396: return idx;
0397: }
0398:
0399: /** This is NOT zero based index: idx of the first object is 1, the second is 2, etc... */
0400: public void setObject(int index, DomainObject domainObject) {
0401: int id = 0;
0402: if (domainObject.getDomainFactoryId() != domainFactoryId) {
0403: domainObject.setDomainFactoryId(domainFactoryId);
0404: if (isSynchronizedAccess()) {
0405: id = this .getSyncNextObjectId();
0406: domainObject.setObjectId(id);
0407: } else {
0408: id = this .getNextObjectId();
0409: domainObject.setObjectId(id);
0410: }
0411: } else {
0412: if (domainObject.getObjectId() == 0) {
0413: if (isSynchronizedAccess()) {
0414: id = this .getSyncNextObjectId();
0415: domainObject.setObjectId(id);
0416: } else {
0417: id = this .getNextObjectId();
0418: domainObject.setObjectId(id);
0419: }
0420: }
0421: }
0422: this .objectList.set(index - 1, domainObject);
0423: }
0424:
0425: /** This is NOT zero based index: idx of the first object is 1, the second is 2, etc...*/
0426: public void addObject(int index, DomainObject domainObject) {
0427: int id = 0;
0428: if (domainObject.getDomainFactoryId() != domainFactoryId) {
0429: domainObject.setDomainFactoryId(domainFactoryId);
0430: if (isSynchronizedAccess()) {
0431: id = this .getSyncNextObjectId();
0432: domainObject.setObjectId(id);
0433: } else {
0434: id = this .getNextObjectId();
0435: domainObject.setObjectId(id);
0436: }
0437: } else {
0438: if (domainObject.getObjectId() == 0) {
0439: if (isSynchronizedAccess()) {
0440: id = this .getSyncNextObjectId();
0441: domainObject.setObjectId(id);
0442: } else {
0443: id = this .getNextObjectId();
0444: domainObject.setObjectId(id);
0445: }
0446: }
0447: }
0448: this .objectList.add(index - 1, domainObject);
0449: }
0450:
0451: public int addObject(DomainObject domainObject) {
0452: int id = 0;
0453: if (domainObject.getDomainFactoryId() != domainFactoryId) {
0454: domainObject.setDomainFactoryId(domainFactoryId);
0455: if (isSynchronizedAccess()) {
0456: id = this .getSyncNextObjectId();
0457: domainObject.setObjectId(id);
0458: } else {
0459: id = this .getNextObjectId();
0460: domainObject.setObjectId(id);
0461: }
0462: } else {
0463: if (domainObject.getObjectId() == 0) {
0464: if (isSynchronizedAccess()) {
0465: id = this .getSyncNextObjectId();
0466: domainObject.setObjectId(id);
0467: } else {
0468: id = this .getNextObjectId();
0469: domainObject.setObjectId(id);
0470: }
0471: }
0472: }
0473: this .objectList.add(domainObject);
0474: return this .objectList.size() - 1;
0475: }
0476:
0477: public DomainObject findObjectByObjectId(int objectId) {
0478: int idx = findIdxByObjectId(objectId);
0479: return (DomainObject) this .objectList.get(idx - 1);
0480: }
0481:
0482: /** This is NOT zero based index: idx of the first object is 1, the second is 2, etc...*/
0483: public int findIdxByObjectId(int objectId) {
0484: int id = 0;
0485: int idx = 0;
0486: Iterator it = this .objectList.iterator();
0487: while (it.hasNext()) {
0488: idx++;
0489: DomainObject domainObject = (DomainObject) it.next();
0490: id = domainObject.getObjectId();
0491: if (objectId == id) {
0492: break;
0493: }
0494: }
0495: return idx;
0496: }
0497:
0498: protected synchronized int getSyncNextObjectId() {
0499: this .objectId++;
0500: return this .objectId;
0501: }
0502:
0503: protected int getNextObjectId() {
0504: this .objectId++;
0505: return this .objectId;
0506: }
0507:
0508: /** Getter for property objectList.
0509: * @return Value of property objectList.
0510: *
0511: */
0512: public List getObjectList() {
0513: return objectList;
0514: }
0515:
0516: /** Setter for property objectList.
0517: * @param objectList New value of property objectList.
0518: *
0519: */
0520: public void setObjectList(List objectList) {
0521: this .objectList = objectList;
0522: }
0523:
0524: /* Does not delete from DB, just from objectList */
0525: public boolean discard(DomainObject domainObject) {
0526: int idx = findIdxByObjectId(domainObject.getObjectId());
0527: if (idx > 0) {
0528: this .objectList.remove(idx - 1);
0529: return true;
0530: }
0531: return false;
0532: }
0533:
0534: public boolean remove(DomainObject domainObject) {
0535: boolean success = false;
0536: int removedIdx = -1;
0537: if (domainObject.getDomainFactoryId() == domainFactoryId) {
0538: int idx = findIdxByObjectId(domainObject.getObjectId());
0539: if (!beforeRemove(domainObject)) {
0540: return success;
0541: }
0542: if (idx > 0) {
0543: if (domainObject.getPersistentState() == DomainObject.CREATED) {
0544: this .objectList.remove(idx - 1); // Does not delete from DB, just from objectList
0545: success = false;
0546: } else {
0547: if (domainObject.remove()) {
0548: this .removedObjects.add(domainObject);
0549: removedIdx = this .removedObjects.size() + 1;
0550: this .objectList.remove(idx - 1);
0551: success = true;
0552: } else { // discard?
0553: //this.objectList.remove(idx - 1);
0554: success = false;
0555: }
0556: }
0557: } else {
0558: if (isSynchronizedAccess()) {
0559: domainObject
0560: .setObjectId(this .getSyncNextObjectId());
0561: } else {
0562: domainObject.setObjectId(this .getNextObjectId());
0563: }
0564: if (domainObject.getPersistentState() == DomainObject.CREATED) {
0565: // Does not delete from DB, just from objectList
0566: success = false;
0567: } else {
0568: if (domainObject.remove()) {
0569: this .removedObjects.add(domainObject);
0570: success = true;
0571: }
0572: }
0573: }
0574: if (!afterRemove(removedIdx)) {
0575: return false;
0576: }
0577: } else {
0578: domainObject.setDomainFactoryId(domainFactoryId);
0579: if (!beforeRemove(domainObject)) {
0580: return false;
0581: }
0582: if (isSynchronizedAccess()) {
0583: domainObject.setObjectId(this .getSyncNextObjectId());
0584: } else {
0585: domainObject.setObjectId(this .getNextObjectId());
0586: }
0587:
0588: if (domainObject.getPersistentState() == DomainObject.CREATED) {
0589: this .removedObjects.add(domainObject); // Does not delete from DB, just from objectList
0590: success = false;
0591: } else {
0592: if (domainObject.remove()) {
0593: this .removedObjects.add(domainObject);
0594: success = true;
0595: }
0596: }
0597: if (!afterRemove(removedIdx)) {
0598: return false;
0599: }
0600: }
0601: return success;
0602: }
0603:
0604: // override as needed
0605: public boolean beforeRemove(DomainObject domainObject) {
0606: return true;
0607: }
0608:
0609: /** This is NOT zero based index: idx of the first object is 1, the second is 2, etc... override as needed */
0610: public boolean afterRemove(int idx) {
0611: return true;
0612: }
0613:
0614: public boolean store(DomainObject domainObject) {
0615: boolean success = false;
0616: int idx = -1;
0617: if (domainObject.getDomainFactoryId() == domainFactoryId) { // domainObject could be from another DomainObjectFactory or created manually or else...
0618: idx = findIdxByObjectId(domainObject.getObjectId());
0619: if (!beforeStore(domainObject)) {
0620: return false;
0621: }
0622: if (idx > 0) {
0623: if (domainObject.store()) {
0624: this .objectList.set(idx - 1, domainObject);
0625: success = true;
0626: }
0627: } else {
0628: if (isSynchronizedAccess()) {
0629: domainObject
0630: .setObjectId(this .getSyncNextObjectId());
0631: } else {
0632: domainObject.setObjectId(this .getNextObjectId());
0633: }
0634: if (domainObject.store()) {
0635: this .objectList.add(domainObject);
0636: idx = this .objectList.size() - 1;
0637: success = true;
0638: } else {
0639: success = false;
0640: }
0641: }
0642: if (!afterStore(idx)) {
0643: return false;
0644: }
0645: } else {
0646: domainObject.setDomainFactoryId(domainFactoryId);
0647: if (isSynchronizedAccess()) {
0648: domainObject.setObjectId(this .getSyncNextObjectId());
0649: } else {
0650: domainObject.setObjectId(this .getNextObjectId());
0651: }
0652: if (!beforeStore(domainObject)) {
0653: return false;
0654: }
0655: if (domainObject.store()) {
0656: this .objectList.add(domainObject);
0657: idx = this .objectList.size() - 1;
0658: success = true;
0659: } else {
0660: success = false;
0661: }
0662: if (!afterStore(idx)) {
0663: return false;
0664: }
0665: }
0666: return success;
0667: }
0668:
0669: // override as needed
0670: public boolean beforeStore(DomainObject domainObjectx) {
0671: return true;
0672: }
0673:
0674: /** This is NOT zero based index: idx of the first object is 1, the second is 2, etc... override as needed */
0675: public boolean afterStore(int idx) {
0676: return true;
0677: }
0678:
0679: public boolean create(DomainObject domainObject) {
0680: if (domainObject.getDomainFactoryId() != domainFactoryId) {
0681: domainObject.setDomainFactoryId(domainFactoryId);
0682: }
0683: int idx = -1;
0684: boolean success = false;
0685: if (!beforeCreate(domainObject)) {
0686: return false;
0687: }
0688: if (domainObject.create()) {
0689: idx = this .setObject(domainObject);
0690: success = true;
0691: }
0692: if (!afterCreate(idx)) {
0693: return false;
0694: }
0695: return success;
0696: }
0697:
0698: // override as needed
0699: public boolean beforeCreate(DomainObject domainObject) {
0700: return true;
0701: }
0702:
0703: /** This is NOT zero based index: idx of the first object is 1, the second is 2, etc... override as needed */
0704: public boolean afterCreate(int idx) {
0705: return true;
0706: }
0707:
0708: /** Getter for property removedObjects.
0709: * @return Value of property removedObjects.
0710: *
0711: */
0712: public List getRemovedObjects() {
0713: return removedObjects;
0714: }
0715:
0716: /** Setter for property removedObjects.
0717: * @param removedObjects New value of property removedObjects.
0718: *
0719: */
0720: public void setRemovedObjects(List removedObjects) {
0721: this .removedObjects = removedObjects;
0722: }
0723:
0724: /** Indexed getter for property dataModificationSequence.
0725: * @param index Index of the property.
0726: * @return Value of the property at <CODE>index</CODE>.
0727: *
0728: */
0729: public char getDataModificationSequence(int index) {
0730: return this .dataModificationSequence[index];
0731: }
0732:
0733: /** Getter for property dataModificationSequence.
0734: * @return Value of property dataModificationSequence.
0735: *
0736: */
0737: public char[] getDataModificationSequence() {
0738: return this .dataModificationSequence;
0739: }
0740:
0741: /** Setter for property dataModificationSequence.
0742: * @param dataModificationSequence New value of property dataModificationSequence.
0743: *
0744: */
0745: public void setDataModificationSequence(
0746: char[] dataModificationSequence) {
0747: this .dataModificationSequence = dataModificationSequence;
0748: }
0749:
0750: /** Getter for property discardUnmodifiedObjects.
0751: * @return Value of property discardUnmodifiedObjects.
0752: *
0753: */
0754: public boolean isDiscardUnmodifiedObjects() {
0755: return discardUnmodifiedObjects;
0756: }
0757:
0758: /** Setter for property discardUnmodifiedObjects.
0759: * @param discardUnmodifiedObjects New value of property discardUnmodifiedObjects.
0760: *
0761: */
0762: public void setDiscardUnmodifiedObjects(
0763: boolean discardUnmodifiedObjects) {
0764: ListIterator li = this .objectList.listIterator();
0765: while (li.hasNext()) {
0766: DomainObject domainObject = (DomainObject) li.next();
0767: if (domainObject.getPersistentState() == domainObject.ORIGINAL) {
0768: li.remove();
0769: }
0770: }
0771: this .discardUnmodifiedObjects = discardUnmodifiedObjects;
0772: }
0773:
0774: /** Getter for property optimisticLock.
0775: * @return Value of property optimisticLock.
0776: *
0777: */
0778: public char getOptimisticLock() {
0779: return optimisticLock;
0780: }
0781:
0782: /** Setter for property optimisticLock.
0783: * @param optimisticLock New value of property optimisticLock.
0784: *
0785: */
0786: public void setOptimisticLock(char optimisticLock) {
0787: this .optimisticLock = optimisticLock;
0788: }
0789:
0790: /** Getter for property readOnly.
0791: * @return Value of property readOnly.
0792: *
0793: */
0794: public boolean isReadOnly() {
0795: return readOnly;
0796: }
0797:
0798: /** Setter for property readOnly.
0799: * @param readOnly New value of property readOnly.
0800: * makes this non-updateable.
0801: */
0802: public void setReadOnly(boolean readOnly) {
0803: this .readOnly = readOnly;
0804: }
0805:
0806: public void setOriginal() {
0807: if (isReadOnly()) {
0808: throw new IllegalStateException(
0809: "Cannot setOriginal() for readOnly object");
0810: }
0811: objectList.add(this .removedObjects);
0812: ListIterator li = objectList.listIterator();
0813: while (li.hasNext()) {
0814: DomainObject domainObject = (DomainObject) li.next();
0815: if (domainObject.getPersistentState() == DomainObject.REMOVED
0816: && domainObject.getOriginalValues() != null
0817: && domainObject.getOriginalValues().getFieldCount() > 0) {
0818: domainObject.setPersistentState(DomainObject.ORIGINAL);
0819: } else if (domainObject.getPersistentState() == DomainObject.CREATED
0820: && domainObject.getOriginalValues() == null
0821: || domainObject.getOriginalValues().getFieldCount() < 1) {
0822: li.remove();
0823: } else if (domainObject.getPersistentState() == DomainObject.STORED
0824: && domainObject.getOriginalValues() != null
0825: && domainObject.getOriginalValues().getFieldCount() > 0) {
0826: domainObject.setPersistentState(DomainObject.ORIGINAL);
0827: } else {
0828: throw new IllegalArgumentException("Invalid SQL Status");
0829: }
0830: }
0831: removedObjects.clear();
0832: }
0833:
0834: /** Getter for property schema.
0835: * @return Value of property schema.
0836: *
0837: */
0838: public java.lang.String getSchema() {
0839: return schema;
0840: }
0841:
0842: /** Setter for property schema.
0843: * @param schema New value of property schema.
0844: *
0845: */
0846: public void setSchema(java.lang.String schema) {
0847: this .schema = schema;
0848: }
0849:
0850: /** Getter for property table.
0851: * @return Value of property table.
0852: *
0853: */
0854: public java.lang.String getTable() {
0855: return table;
0856: }
0857:
0858: /** Setter for property table.
0859: * @param table New value of property table.
0860: *
0861: */
0862: public void setTable(java.lang.String table) {
0863: this .table = table;
0864: }
0865:
0866: public boolean writeData() {
0867: if (!isValid()) {
0868: return false;
0869: }
0870: if (!beforeWriteData()) {
0871: return false;
0872: }
0873: if (this .dataWriter == null) {
0874: this .dataWriter = new DBDataWriter();
0875: }
0876: this .dataWriter
0877: .setExceptionOnEmptyObjectList(exceptionOnEmptyObjectList);
0878: boolean success = this .dataWriter.writeData(this );
0879: if (!afterWriteData()) {
0880: return false;
0881: }
0882: return success;
0883: }
0884:
0885: // override as needed
0886: public boolean beforeWriteData() {
0887: return true;
0888: }
0889:
0890: // override as needed
0891: public boolean afterWriteData() {
0892: return true;
0893: }
0894:
0895: /** Getter for property metaData.
0896: * @return Value of property metaData.
0897: *
0898: */
0899:
0900: public MetaData getMetaData() {
0901: if (createDefaultMetaData && this .metaData == null) {
0902: populateMetaData();
0903: }
0904: return this .metaData;
0905: }
0906:
0907: public void populateMetaData() {
0908: try {
0909: this .metaData = new MetaData();
0910: this .metaData
0911: .setThrowMissingFieldException(throwMissingFieldException);
0912: this .metaData.populate(getMapping(), this .requestor);
0913: Collection tables = (this .metaData.getTables()).values();
0914: if (debug)
0915: System.out.println("julp ============= "
0916: + new java.util.Date() + " " + this .getClass()
0917: + "::" + this + "::metaData.getTables(): "
0918: + this .metaData.getTables());
0919: if (!this .isReadOnly()) { // don't need PK if this is ReadOnly
0920: /* Get all distinct Table names for requestor (DomainObject) */
0921: Iterator iter = tables.iterator();
0922: while (iter.hasNext()) {
0923: String[] tableId = (String[]) iter.next();
0924: if (tableId[0] == null && overrideCatalogName) {
0925: tableId[0] = this .catalog;
0926: }
0927: List pk = getPrimaryKey(tableId[0], tableId[1],
0928: tableId[2]);
0929: if (debug)
0930: System.out.println("julp ============= "
0931: + new java.util.Date() + " "
0932: + this .getClass() + "::" + this
0933: + "::pk: " + pk);
0934: }
0935: }
0936: if (tables.size() == 1) {
0937: //there is only one table for this object, otherwise you must set catalog and/or schema and table to update/delete/insert each table
0938: if (this .metaData.getCatalogName(1) == null
0939: && !overrideCatalogName) {
0940: setCatalog(this .catalog);
0941: }
0942: setSchema(this .metaData.getSchemaName(1));
0943: setTable(this .metaData.getTableName(1));
0944: if (debug)
0945: System.out.println("julp ============= "
0946: + new java.util.Date() + " "
0947: + this .getClass() + "::" + this
0948: + "::this.catalog: " + this .catalog);
0949: if (debug)
0950: System.out.println("julp ============= "
0951: + new java.util.Date() + " "
0952: + this .getClass() + "::" + this
0953: + "::schema: " + getSchema());
0954: if (debug)
0955: System.out.println("julp ============= "
0956: + new java.util.Date() + " "
0957: + this .getClass() + "::" + this
0958: + "::tables: " + getTable());
0959: }
0960: } catch (Exception e) {
0961: e.printStackTrace();
0962: throw new RuntimeException(e);
0963: }
0964: }
0965:
0966: /** Setter for property metaData.
0967: * @param metaData New value of property metaData.
0968: *
0969: */
0970: public void setMetaData(MetaData metaData) {
0971: this .metaData = metaData;
0972: }
0973:
0974: /** Getter for property dbServices.
0975: * @return Value of property dbServices.
0976: *
0977: */
0978: public DBServices getDBServices() {
0979: if (this .dbServices == null) {
0980: this .dbServices = new DBServices();
0981: }
0982: return this .dbServices;
0983: }
0984:
0985: /** Setter for property dbServices.
0986: * @param dbServices New value of property dbServices.
0987: *
0988: */
0989: public void setDBServices(DBServices dbServices) {
0990: this .dbServices = dbServices;
0991: }
0992:
0993: /** Getter for property throwOptimisticLockDeleteException.
0994: * @return Value of property throwOptimisticLockDeleteException.
0995: *
0996: */
0997: public boolean isThrowOptimisticLockDeleteException() {
0998: return throwOptimisticLockDeleteException;
0999: }
1000:
1001: /** Setter for property throwOptimisticLockDeleteException.
1002: * @param throwOptimisticLockDeleteException New value of property throwOptimisticLockDeleteException.
1003: *
1004: */
1005: public void setThrowOptimisticLockDeleteException(
1006: boolean throwOptimisticLockDeleteException) {
1007: this .throwOptimisticLockDeleteException = throwOptimisticLockDeleteException;
1008: }
1009:
1010: /** Getter for property throwOptimisticLockUpdateException.
1011: * @return Value of property throwOptimisticLockUpdateException.
1012: *
1013: */
1014: public boolean isThrowOptimisticLockUpdateException() {
1015: return throwOptimisticLockUpdateException;
1016: }
1017:
1018: /** Setter for property throwOptimisticLockUpdateException.
1019: * @param throwOptimisticLockUpdateException New value of property throwOptimisticLockUpdateException.
1020: *
1021: */
1022: public void setThrowOptimisticLockUpdateException(
1023: boolean throwOptimisticLockUpdateException) {
1024: this .throwOptimisticLockUpdateException = throwOptimisticLockUpdateException;
1025: }
1026:
1027: public void setThrowFailedInsertException(
1028: boolean throwFailedInsertException) {
1029: this .throwFailedInsertException = throwFailedInsertException;
1030: }
1031:
1032: public boolean isThrowFailedInsertException() {
1033: return this .throwFailedInsertException;
1034: }
1035:
1036: /**
1037: * IMPORTANT! *************************************************************
1038: * Call this method after successeful COMMIT to sync original and current
1039: * values: copy current values to original
1040: * and set persistentState == ORIGINAL and discard Objects deleted from DB
1041: */
1042: public void synchronizePersistentState() {
1043: if (isReadOnly()) {
1044: throw new IllegalStateException(
1045: "Cannot call synchronizePersistentState() for readOnly object");
1046: }
1047: try {
1048: removedObjects.clear();
1049: ListIterator li = objectList.listIterator();
1050: while (li.hasNext()) {
1051: boolean copyValues = true;
1052: boolean created = false;
1053: DomainObject domainObject = (DomainObject) li.next();
1054: if (debug)
1055: System.out.println("julp ============= "
1056: + new java.util.Date() + " "
1057: + this .getClass() + "::" + this
1058: + "::syncSqlStatus()::DomainObject: "
1059: + domainObject + " \n");
1060: if (domainObject.getPersistentState() == DomainObject.REMOVED
1061: && domainObject.getOriginalValues() != null
1062: && domainObject.getOriginalValues()
1063: .getFieldCount() > 0) {
1064: li.remove();
1065: copyValues = false;
1066: } else if (domainObject.getPersistentState() == DomainObject.CREATED
1067: && (domainObject.getOriginalValues() == null || domainObject
1068: .getOriginalValues().getFieldCount() < 1)) {
1069: domainObject
1070: .setPersistentState(DomainObject.ORIGINAL);
1071: created = true;
1072: } else if (domainObject.getPersistentState() == DomainObject.STORED
1073: && domainObject.getOriginalValues() != null
1074: && domainObject.getOriginalValues()
1075: .getFieldCount() > 0) {
1076: domainObject
1077: .setPersistentState(DomainObject.ORIGINAL);
1078: } else if (domainObject.getPersistentState() == DomainObject.ORIGINAL) {
1079: // do nothing
1080: continue;
1081: } else {
1082: throw new IllegalArgumentException(
1083: "Invalid PersistentState");
1084: }
1085: if (copyValues) { // Sync values in Object and it's originalValues
1086: DataHolder originalValues = null;
1087: if (created) {
1088: originalValues = new DataHolder(mapping.size());
1089: } else {
1090: originalValues = domainObject
1091: .getOriginalValues();
1092: }
1093: Iterator iter = mapping.values().iterator();
1094: int fieldIndex = 0;
1095: if (debug)
1096: System.out.println("julp ============= "
1097: + new java.util.Date() + " "
1098: + this .getClass() + "::" + this
1099: + "::syncSqlStatus()::created: "
1100: + created + " \n");
1101: while (iter.hasNext()) {
1102: fieldIndex++;
1103: String fieldName = (String) iter.next();
1104: if (created) {
1105: Method readMethod = this .metaData
1106: .getReadMethod(this .metaData
1107: .getColumnIndexByFieldName(fieldName));
1108: Object value = readMethod.invoke(
1109: domainObject, EMPTY_READ_ARG);
1110: originalValues.setFieldNameAndValue(
1111: fieldIndex, fieldName, value);
1112: } else {
1113: if (originalValues
1114: .findFieldIndex(fieldName) != -1) {
1115: Method readMethod = this .metaData
1116: .getReadMethod(this .metaData
1117: .getColumnIndexByFieldName(fieldName));
1118: Object value = readMethod.invoke(
1119: domainObject, EMPTY_READ_ARG);
1120: domainObject.setOriginalValue(
1121: fieldName, value);
1122: }
1123: }
1124: }
1125: if (created) {
1126: domainObject.setOriginalValues(originalValues);
1127: created = false;
1128: }
1129: domainObject.setModified(false);
1130: }
1131: }
1132: if (this .dataWriter != null) {
1133: this .dataWriter.reset();
1134: }
1135: valid = true;
1136: } catch (Throwable t) {
1137: if (t instanceof InvocationTargetException) {
1138: throw new RuntimeException(
1139: ((InvocationTargetException) t)
1140: .getTargetException());
1141: } else {
1142: throw new RuntimeException(t);
1143: }
1144: }
1145: }
1146:
1147: /** Getter for property removedCount.
1148: * @return Value of property removedCount.
1149: *
1150: */
1151: public int getRemovedCount() {
1152: if (dataWriter == null) {
1153: throw new NullPointerException("DataWriter not initialized");
1154: }
1155: return dataWriter.getRemovedCount();
1156: }
1157:
1158: /** Getter for property createdCount.
1159: * @return Value of property createdCount.
1160: *
1161: */
1162: public int getCreatedCount() {
1163: if (dataWriter == null) {
1164: throw new NullPointerException("DataWriter not initialized");
1165: }
1166: return dataWriter.getCreatedCount();
1167: }
1168:
1169: /** Getter for property modifiedCount.
1170: * @return Value of property modifiedCount.
1171: *
1172: */
1173: public int getModifiedCount() {
1174: if (dataWriter == null) {
1175: throw new NullPointerException("DataWriter not initialized");
1176: }
1177: return dataWriter.getModifiedCount();
1178: }
1179:
1180: /** Getter for property dataWriter.
1181: * @return Value of property dataWriter.
1182: *
1183: */
1184: public DataWriter getDataWriter() {
1185: if (dataWriter == null) {
1186: dataWriter = new DBDataWriter();
1187: }
1188: return dataWriter;
1189: }
1190:
1191: /** Setter for property dataWriter.
1192: * @param dataWriter New value of property dataWriter.
1193: *
1194: */
1195: public void setDataWriter(DataWriter dataWriter) {
1196: this .dataWriter = dataWriter;
1197: }
1198:
1199: /** Getter for property synchronizedAccess.
1200: * @return Value of property synchronizedAccess.
1201: *
1202: */
1203: public boolean isSynchronizedAccess() {
1204: return synchronizedAccess;
1205: }
1206:
1207: /** Setter for property synchronizedAccess.
1208: * @param synchronizedAccess New value of property synchronizedAccess.
1209: *
1210: */
1211: public void setSynchronizedAccess(boolean synchronizedAccess) {
1212: if (synchronizedAccess) {
1213: this .removedObjects = Collections
1214: .synchronizedList(removedObjects);
1215: this .objectList = Collections.synchronizedList(objectList);
1216: this .synchronizedAccess = synchronizedAccess;
1217: }
1218: }
1219:
1220: /** Getter for property lazyLoading.
1221: * @return Value of property lazyLoading.
1222: *
1223: */
1224: public boolean isLazyLoading() {
1225: return lazyLoading;
1226: }
1227:
1228: /** Setter for property lazyLoading.
1229: * @param lazyLoading New value of property lazyLoading.
1230: *
1231: */
1232: public void setLazyLoading(boolean lazyLoading) {
1233: this .lazyLoading = lazyLoading;
1234: }
1235:
1236: /** Getter for property pageSize.
1237: * @return Value of property pageSize.
1238: *
1239: */
1240: public int getPageSize() {
1241: return pageSize;
1242: }
1243:
1244: /** Setter for property pageSize.
1245: * @param pageSize New value of property pageSize.
1246: *
1247: */
1248: public void setPageSize(int pageSize) {
1249: if (pageSize < 0) {
1250: throw new IllegalArgumentException("Invalid Page size: "
1251: + pageSize);
1252: }
1253: this .pageSize = pageSize;
1254: }
1255:
1256: /** This is NOT zero based index: idx of the first object is 1, the second is 2, etc... */
1257: public PageHolder getPage(int pageNumber) {
1258: PageHolder pageHolder = new PageHolder();
1259: pageHolder.setObjectsTotal(this .objectList.size());
1260: if (getPageSize() == 0) {
1261: pageHolder.setPageNumber(1);
1262: pageHolder.setPagesTotal(1);
1263: pageHolder.setPage(this .objectList);
1264: } else {
1265: List page = new ArrayList();
1266: if (this .objectList.isEmpty()) {
1267: pageHolder.setPageNumber(0);
1268: pageHolder.setPagesTotal(0);
1269: pageHolder.setPage(page);
1270: } else {
1271: double d1 = new Integer(this .objectList.size())
1272: .doubleValue();
1273: double d2 = new Integer(this .pageSize).doubleValue();
1274: double d3 = java.lang.Math.ceil(d1 / d2);
1275: int pagesTotal = (new Double(d3)).intValue();
1276: pageHolder.setPagesTotal(pagesTotal);
1277: if (pageNumber > pagesTotal) {
1278: pageNumber = pagesTotal;
1279: } else if (pageNumber < 1) {
1280: pageNumber = 1;
1281: } else {
1282: //
1283: }
1284: pageHolder.setPageNumber(pageNumber);
1285: ListIterator li = this .objectList
1286: .listIterator((pageNumber - 1) * getPageSize());
1287: int count = 0;
1288: while (li.hasNext() && count < getPageSize()) {
1289: Object obj = li.next();
1290: page.add(obj);
1291: count++;
1292: }
1293: pageHolder.setPage(page);
1294: }
1295: }
1296: return pageHolder;
1297: }
1298:
1299: /** Getter for property generateSQLOnly.
1300: * @return Value of property generateSQLOnly.
1301: *
1302: */
1303: public boolean isGenerateSQLOnly() {
1304: return generateSQLOnly;
1305: }
1306:
1307: /** Setter for property generateSQLOnly.
1308: * @param generateSQLOnly New value of property generateSQLOnly.
1309: *
1310: */
1311: public void setGenerateSQLOnly(boolean generateSQLOnly) {
1312: this .generateSQLOnly = generateSQLOnly;
1313: }
1314:
1315: public java.util.List getGeneratedSQL() {
1316: if (dataWriter == null) {
1317: throw new NullPointerException("DataWriter not initialized");
1318: }
1319: return this .dataWriter.getGeneratedSQL();
1320: }
1321:
1322: public java.lang.String getGeneratedSQLasXML() {
1323: if (dataWriter == null) {
1324: throw new NullPointerException("DataWriter not initialized");
1325: }
1326: return this .dataWriter.getGeneratedSQLasXML();
1327: }
1328:
1329: /** Getter for property append.
1330: * @return Value of property append.
1331: *
1332: */
1333: public boolean isAppend() {
1334: return append;
1335: }
1336:
1337: /** Setter for property append.
1338: * @param append New value of property append.
1339: *
1340: */
1341: public void setAppend(boolean append) {
1342: this .append = append;
1343: }
1344:
1345: public java.lang.Throwable getWhatIsWrong() {
1346: if (this .dataWriter == null) {
1347: return null;
1348: }
1349: return this .dataWriter.getWhatIsWrong();
1350: }
1351:
1352: /** Getter for property catalog.
1353: * @return Value of property catalog.
1354: *
1355: */
1356: public java.lang.String getCatalog() {
1357: return catalog;
1358: }
1359:
1360: /** Setter for property catalog.
1361: * @param catalog New value of property catalog.
1362: *
1363: */
1364: public void setCatalog(java.lang.String catalog) {
1365: this .catalog = catalog;
1366: }
1367:
1368: /** Getter for property noFullColumnName.
1369: * @return Value of property noFullColumnName.
1370: *
1371: */
1372: public boolean isNoFullColumnName() {
1373: return noFullColumnName;
1374: }
1375:
1376: /** Setter for property noFullColumnName.
1377: * @param noFullColumnName New value of property noFullColumnName.
1378: *
1379: */
1380: public void setNoFullColumnName(boolean noFullColumnName) {
1381: this .noFullColumnName = noFullColumnName;
1382: }
1383:
1384: /**
1385: * Getter for property debug.
1386: * @return Value of property debug.
1387: */
1388: public boolean isDebug() {
1389: return debug;
1390: }
1391:
1392: public void clearData() {
1393: if (this .objectList != null)
1394: this .objectList.clear();
1395: if (this .removedObjects != null)
1396: this .removedObjects.clear();
1397: valid = true;
1398: }
1399:
1400: /**
1401: * Setter for property debug.
1402: * @param debug New value of property debug.
1403: */
1404: public void setDebug(boolean debug) {
1405: this .debug = debug;
1406: }
1407:
1408: public boolean isOverrideCatalogName() {
1409: return overrideCatalogName;
1410: }
1411:
1412: public void setOverrideCatalogName(boolean overrideCatalogName) {
1413: this .overrideCatalogName = overrideCatalogName;
1414: }
1415:
1416: public void setExceptionHandler(ExceptionHandler exceptionHandler) {
1417: this .exceptionHandler = exceptionHandler;
1418: exceptionHandler.setDomainObjectFactory(this );
1419: }
1420:
1421: public ExceptionHandler getExceptionHandler() {
1422: return this .exceptionHandler;
1423: }
1424:
1425: // override as needed
1426: public boolean isValid() {
1427: return valid;
1428: }
1429:
1430: // create empty DataHolder from MetaData
1431: public DataHolder createOriginalValues() throws SQLException {
1432: DataHolder dataHolder = new DataHolder(this .metaData
1433: .getColumnCount());
1434: for (int i = 1; i <= this .metaData.getColumnCount(); i++) {
1435: dataHolder.setFieldName(i, this .metaData.getFieldName(i));
1436: }
1437: return dataHolder;
1438: }
1439:
1440: public void setDataSource(DataSource dataSource) {
1441: getDBServices().setDataSource(dataSource);
1442: }
1443:
1444: public DataSource getDataSource() throws SQLException {
1445: return getDBServices().getDataSource();
1446: }
1447:
1448: public void setDataSourceName(String dataSourceName) {
1449: getDBServices().setDataSourceName(dataSourceName);
1450: }
1451:
1452: public boolean isExceptionOnEmptyObjectList() {
1453: return exceptionOnEmptyObjectList;
1454: }
1455:
1456: public void setExceptionOnEmptyObjectList(
1457: boolean exceptionOnEmptyObjectList) {
1458: this .exceptionOnEmptyObjectList = exceptionOnEmptyObjectList;
1459: }
1460:
1461: public boolean isCreateDefaultMetaData() {
1462: return createDefaultMetaData;
1463: }
1464:
1465: public void setCreateDefaultMetaData(boolean createDefaultMetaData) {
1466: this .createDefaultMetaData = createDefaultMetaData;
1467: }
1468:
1469: public boolean isThrowMissingFieldException() {
1470: return throwMissingFieldException;
1471: }
1472:
1473: public void setThrowMissingFieldException(
1474: boolean throwMissingFieldException) {
1475: this .throwMissingFieldException = throwMissingFieldException;
1476: }
1477:
1478: public Converter getConverter() {
1479: return converter;
1480: }
1481:
1482: public void setConverter(Converter converter) {
1483: this .converter = converter;
1484: }
1485:
1486: public String toString() {
1487: StringBuffer sb = new StringBuffer();
1488: Object value = null;
1489: Method[] methods = getClass().getMethods();
1490: for (int i = 0; i < methods.length; i++) {
1491: String methodName = methods[i].getName();
1492: if (methodName.equals("getMetaData")
1493: || methodName.equals("getClass")) {
1494: continue;
1495: }
1496: if (methodName.equals("getDataModificationSequence")
1497: && methods[i].getParameterTypes().length == 0) {
1498: if (dataModificationSequence != null
1499: && dataModificationSequence.length > 0) {
1500: sb.append("dataModificationSequence=").append(
1501: new String(dataModificationSequence))
1502: .append("&");
1503: } else {
1504: sb.append("dataModificationSequence=").append("&");
1505: }
1506:
1507: } else if ((methodName.startsWith("get") || methodName
1508: .startsWith("is"))
1509: && methods[i].getParameterTypes().length == 0) {
1510: try {
1511: value = methods[i].invoke(this , EMPTY_READ_ARG);
1512: } catch (Throwable t) {
1513: continue;
1514: }
1515: String fieldFirstChar = "";
1516: if (methodName.startsWith("is")) {
1517: fieldFirstChar = methodName.substring(2, 3)
1518: .toLowerCase();
1519: sb.append(fieldFirstChar);
1520: sb.append(methodName.substring(3));
1521: } else if (methodName.startsWith("get")) {
1522: fieldFirstChar = methodName.substring(3, 4)
1523: .toLowerCase();
1524: sb.append(fieldFirstChar);
1525: sb.append(methodName.substring(4));
1526: }
1527: sb.append("=");
1528: sb.append((value == null) ? "" : value);
1529: sb.append("&");
1530: }
1531: }
1532: return sb.toString();
1533: }
1534: }
|