001: /* ====================================================================
002: * The Jcorporate Apache Style Software License, Version 1.2 05-07-2002
003: *
004: * Copyright (c) 1995-2002 Jcorporate Ltd. All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: *
010: * 1. Redistributions of source code must retain the above copyright
011: * notice, this list of conditions and the following disclaimer.
012: *
013: * 2. Redistributions in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in
015: * the documentation and/or other materials provided with the
016: * distribution.
017: *
018: * 3. The end-user documentation included with the redistribution,
019: * if any, must include the following acknowledgment:
020: * "This product includes software developed by Jcorporate Ltd.
021: * (http://www.jcorporate.com/)."
022: * Alternately, this acknowledgment may appear in the software itself,
023: * if and wherever such third-party acknowledgments normally appear.
024: *
025: * 4. "Jcorporate" and product names such as "Expresso" must
026: * not be used to endorse or promote products derived from this
027: * software without prior written permission. For written permission,
028: * please contact info@jcorporate.com.
029: *
030: * 5. Products derived from this software may not be called "Expresso",
031: * or other Jcorporate product names; nor may "Expresso" or other
032: * Jcorporate product names appear in their name, without prior
033: * written permission of Jcorporate Ltd.
034: *
035: * 6. No product derived from this software may compete in the same
036: * market space, i.e. framework, without prior written permission
037: * of Jcorporate Ltd. For written permission, please contact
038: * partners@jcorporate.com.
039: *
040: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
041: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
042: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
043: * DISCLAIMED. IN NO EVENT SHALL JCORPORATE LTD OR ITS CONTRIBUTORS
044: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
045: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
046: * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
047: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
048: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
049: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
050: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
051: * SUCH DAMAGE.
052: * ====================================================================
053: *
054: * This software consists of voluntary contributions made by many
055: * individuals on behalf of the Jcorporate Ltd. Contributions back
056: * to the project(s) are encouraged when you make modifications.
057: * Please send them to support@jcorporate.com. For more information
058: * on Jcorporate Ltd. and its products, please see
059: * <http://www.jcorporate.com/>.
060: *
061: * Portions of this software are based upon other open source
062: * products and are subject to their respective licenses.
063: */
064:
065: package com.jcorporate.expresso.core.dbobj;
066:
067: import com.jcorporate.expresso.core.dataobjects.DataException;
068: import com.jcorporate.expresso.core.dataobjects.jdbc.JDBCObjectMetaData;
069: import com.jcorporate.expresso.core.db.DBConnection;
070: import com.jcorporate.expresso.core.db.DBException;
071: import com.jcorporate.expresso.core.misc.ConfigManager;
072: import com.jcorporate.expresso.core.misc.ConfigurationException;
073: import com.jcorporate.expresso.core.misc.StringUtil;
074:
075: import java.sql.DatabaseMetaData;
076: import java.sql.ResultSet;
077: import java.sql.SQLException;
078:
079: /**
080: * This class provides convenience methods by querying the database table it is
081: * set to and automatically setting up it's own fields that way.
082: * Creation date: (10/3/00 11:07:02 AM)
083: *
084: * @author Michael Nash
085: */
086: public class AutoDBObject extends SecuredDBObject {
087: private static final String THIS_CLASS = "com.jcorporate.expreso.core.dbobj.AutoDBObject.";
088:
089: /**
090: * AutoDBObject constructor comment.
091: *
092: * @throws com.jcorporate.expresso.core.db.DBException
093: * The exception description.
094: */
095: public AutoDBObject()
096: throws com.jcorporate.expresso.core.db.DBException {
097: super ();
098: } /* AutoDBObject() */
099:
100: /**
101: * AutoDBObject constructor comment.
102: *
103: * @param newConnection com.jcorporate.expresso.core.db.DBConnection
104: * @throws com.jcorporate.expresso.core.db.DBException
105: * The exception description.
106: */
107: public AutoDBObject(
108: com.jcorporate.expresso.core.db.DBConnection newConnection)
109: throws com.jcorporate.expresso.core.db.DBException {
110: super (newConnection);
111: } /* AutoDBObject(com.jcorporate.expresso.core.db.DBConnection) */
112:
113: /**
114: * Initialize an AutoDBObject with a uid.
115: *
116: * @param uid the user ID or -1 if System privileges
117: * @throws DBException upon error
118: */
119: public AutoDBObject(int uid) throws DBException {
120: super (uid);
121: }
122:
123: /**
124: * getThisDBObj method comment.
125: *
126: * @return a fully instantiated DBObject
127: */
128: public DBObject getThisDBObj()
129: throws com.jcorporate.expresso.core.db.DBException {
130: AutoDBObject returnObj = new AutoDBObject();
131: returnObj.setTargetTable(this .getDefinitionName());
132:
133: return returnObj;
134: } /* getThisDBObj() */
135:
136: /**
137: * Set the target table for this AutoDBObject - this causes the object to
138: * set itself up with the fields from the database as it's fields. All existing
139: * fields are cleared.
140: *
141: * @param theTable Table for this object
142: */
143: public synchronized void setTargetTable(String theTable)
144: throws DBException {
145: clear();
146: DBObjectDef myDef = new DBObjectDef();
147: myDef.setName(getClass().getName());
148: sMetadataMap.put(getClass().getName(), myDef);
149: super .setTargetTable(theTable);
150: setupFields();
151: } /* setTargetTable(String) */
152:
153: /**
154: * Use this method to set the key to the definition name for the Defineable
155: * database object. The actual meaning of the definitionName may be different.
156: * For example, AutoDBObject's definition name is the database table name.
157: * JoinedDataObject's definition name is the classpath URL location to the
158: * definition XML file.
159: *
160: * @param definitionName java.lang.String, the actual definition of the
161: * dataobject.
162: * @throws DataException if the DataObject is unable to initialize itself
163: * with the given definition name.
164: */
165: public void setDefinitionName(String definitionName)
166: throws DataException {
167: try {
168: this .setTargetTable(definitionName);
169: } catch (DBException ex) {
170: throw new DataException(
171: "Unable to set definition name for AutoDBObject",
172: ex);
173: }
174: }
175:
176: /**
177: * Retrieve the key to the definition name for the given DBObject.
178: *
179: * @return the definition name.
180: */
181: public String getDefinitionName() {
182: try {
183: return ((JDBCObjectMetaData) this .getMetaData())
184: .getTargetTable();
185: } catch (DataException ex) {
186: return null;
187: }
188: }
189:
190: /**
191: * setupFields method. avoids superclass usage with test
192: * at top of method. called for real as a side-effect of setTargetTable()
193: */
194: protected void setupFields() throws DBException {
195:
196: if (StringUtil.notNull(this .getDefinitionName()).equals("")) {
197: return;
198: }
199:
200: DBConnection myConnection = null;
201:
202: try {
203: if (localConnection != null) {
204: myConnection = localConnection;
205: } else {
206: String myName = (THIS_CLASS + "setupFields()");
207: myConnection = this .getConnectionPool().getConnection(
208: myName);
209: }
210:
211: DatabaseMetaData dm = myConnection.getDBMetaData();
212: String tableName = getDefinitionName().toUpperCase();
213: setDescription("Automatic Object for " + tableName);
214: try {
215: // hsqldb bug - can't figure out a way in hsqldb 1.6.1 to get keys - getPrimaryKeys returns SYSTEM_ID
216: // as the column name. So, just return exception.
217: if (ConfigManager
218: .getJdbcRequired(this .getDataContext())
219: .getDriver().equals("org.hsqldb.jdbcDriver")) {
220: throw new DBException(this .getClass()
221: + " does not support hsqldb.");
222: }
223:
224: //Postgresql JDBC 7.2 driver bug. Tablename must be lower case
225: //which doesn't apply to other databases such as Oracle
226: if (ConfigManager
227: .getJdbcRequired(this .getDataContext())
228: .getDriver().equals("org.postgresql.Driver")) {
229:
230: tableName = tableName.toLowerCase();
231: }
232: } catch (ConfigurationException ce) {
233: ce.printStackTrace();
234: throw new DBException(ce);
235: }
236: setDescription("Automatic Object for " + tableName);
237:
238: ResultSet rs = dm.getColumns(null, "%", tableName, "%");
239: String fieldName = null;
240: String fieldType;
241: int fieldSize;
242: int nullField = 0;
243: boolean nullable;
244: String fieldDescrip = null;
245:
246: while (rs.next()) {
247: fieldName = rs.getString(4);
248: fieldSize = rs.getInt(7);
249: fieldDescrip = rs.getString(12);
250:
251: if (fieldDescrip == null) {
252: fieldDescrip = fieldName;
253: }
254:
255: fieldType = rs.getString(5);
256: nullField = rs.getInt(11);
257:
258: if (nullField == DatabaseMetaData.columnNoNulls) {
259: nullable = false;
260: } else {
261: nullable = true;
262: }
263: if (nullable) {
264: addField(fieldName, fieldType, fieldSize, true,
265: fieldDescrip);
266: } else {
267: addField(fieldName, fieldType, fieldSize, false,
268: fieldDescrip);
269: }
270: }
271:
272: /* for each field */
273: ResultSet rspk = dm.getPrimaryKeys(null, "%", tableName);
274:
275: while (rspk.next()) {
276: addKey(rspk.getString(4));
277: }
278: } catch (SQLException se) {
279: throw new DBException(se);
280: } finally {
281: if (localConnection == null) {
282: myConnection.release();
283: }
284: }
285: } /* setupFields() */
286:
287: }
288:
289: /* AutoDBObject */
|