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: package com.jcorporate.expresso.core.db;
065:
066: import com.jcorporate.expresso.core.db.config.TypeMappingConfig;
067: import com.jcorporate.expresso.core.dbobj.DBField;
068: import com.jcorporate.expresso.core.misc.ConfigContext;
069: import com.jcorporate.expresso.core.misc.ConfigManager;
070: import com.jcorporate.expresso.core.misc.StringUtil;
071: import com.jcorporate.expresso.kernel.ComponentLifecycle;
072: import com.jcorporate.expresso.kernel.Configuration;
073: import com.jcorporate.expresso.kernel.exception.ConfigurationException;
074: import com.jcorporate.expresso.kernel.util.LocatorUtils;
075: import org.apache.log4j.Logger;
076:
077: import java.util.Enumeration;
078: import java.util.HashMap;
079: import java.util.Hashtable;
080: import java.util.Iterator;
081: import java.util.Map;
082:
083: /**
084: * Type Mapper takes care of the job of mapping various Java types to SQL
085: * types. This, in turn, is used by items like DBCreate, Database Verifier,
086: * etc. The type mapper is embedded within the PersistenceManager.
087: *
088: * @author Michael Rimov
089: * @see com.jcorporate.expresso.core.dataobjects.PersistenceManager
090: */
091: public class TypeMapper extends
092: com.jcorporate.expresso.kernel.EmbeddedComponent implements
093: ComponentLifecycle {
094: /**
095: * Logger instance
096: */
097: private static Logger log = Logger.getLogger(TypeMapper.class);
098:
099: /**
100: * Data context to TypeMapper map... will be removed once Componentization
101: * is truly complete
102: */
103: private static Map mapInstances = new HashMap();
104:
105: /**
106: * SQL to Expresso Type Map
107: */
108: private Map expressoFromSQL = new HashMap(30);
109:
110: /**
111: * Expresso type to Java type map
112: */
113: private Map expressoToJava = new HashMap(30);
114:
115: /**
116: * Expresso to SQL type map
117: */
118: private Map expressoToSQL = new HashMap(30);
119:
120: /**
121: * SQL to DB Type Map
122: */
123: private Map sqlToDB = new HashMap(30);
124:
125: /**
126: * Mapping of SQL types to sql type names
127: */
128: private Map sqlTypeNames = new HashMap(30);
129:
130: /**
131: * Type to String Map
132: */
133: private Map typeToString = new HashMap(30);
134:
135: /**
136: * Name for the current data context
137: */
138: private String dataContext = null;
139:
140: /**
141: * Set to true if we're in the component configuration system.
142: */
143: private boolean componentConfiguration = false;
144:
145: /**
146: * Default constructor. Required for componentization.
147: */
148: public TypeMapper() {
149: }
150:
151: /**
152: * Constructor that initializes the type mapper based upon the data context
153: *
154: * @param thedataContext the dataContext to load the Type Mapping for
155: */
156: protected TypeMapper(String thedataContext) {
157: this .dataContext = thedataContext;
158: }
159:
160: /**
161: * Retrieve a DBField to java.sql.Types mapping value.
162: *
163: * @param dbFieldType the DBField data type
164: * @return an integer corresponding to the java.sql.Types or -1 if no
165: * mapping is found
166: */
167: public Integer getExpressoToJava(String dbFieldType) {
168: return (Integer) expressoToJava.get(dbFieldType);
169: }
170:
171: /**
172: * Get the ExpressoToSQL Map
173: *
174: * @return A Map getting this context's ExpressoToSQL maps.
175: */
176: public Map getExpressoToSQLMap() {
177: return expressoToSQL;
178: }
179:
180: /* getExpressoToSQLMap(String) */
181:
182: /**
183: * Retrieves an instance of the type mapper.
184: * <p/>
185: * To be deprecated soon. use the Component System with
186: * PersistenceManager to retrieve an instance of the type
187: * mapper instead.
188: *
189: * @param dataContext the data context to retrieve it for.
190: * @return a fully initialized TypeMapper instance
191: * @throws DBException upon error getting or initializing the TypeMapper
192: * for that context
193: */
194: public static synchronized TypeMapper getInstance(String dataContext)
195: throws DBException {
196: if (dataContext == null) {
197: throw new IllegalArgumentException(
198: "Parameter data context cannot be null");
199: }
200:
201: TypeMapper theInstance = (TypeMapper) mapInstances
202: .get(dataContext);
203:
204: synchronized (TypeMapper.class) {
205: if (theInstance == null) {
206: theInstance = new TypeMapper();
207: theInstance.dataContext = dataContext;
208: theInstance.initializeTypes(dataContext);
209: mapInstances.put(dataContext, theInstance);
210: }
211: }
212:
213: return theInstance;
214: }
215:
216: /**
217: * Return a java.sql.Types integer that maps to the field type listed
218: *
219: * @param fieldType the type of the field to map.
220: * @return a DoubleOrderedMap containing all the type mappings for this
221: * context
222: * @throws DBException if there was an error initializing the ExpressoToSQL
223: * maps.
224: */
225: public int getJavaSQLType(String fieldType) throws DBException {
226: Integer i = (Integer) expressoToJava.get(fieldType);
227:
228: if (i == null) {
229: throw new DBException(
230: "Unable to locate java.sql.Types mapping for field type: "
231: + fieldType);
232: }
233:
234: return i.intValue();
235: }
236:
237: /**
238: * Because we look up our metadata in the parent component, we have to
239: * somehow know WHAT component's metadata is ours. Sub classes need to
240: * override this one-liner and return the name of the metadata we're
241: * looking for.
242: *
243: * @return java.lang.String
244: */
245: public String getMetadataName() {
246: return "TypeMapper";
247: }
248:
249: /**
250: * Get the actual java.sql.Type in a friendly String name
251: *
252: * @param sqlType java.sql.Type integer
253: * @return the corresponding string
254: */
255: public String getNameForSQL(int sqlType) {
256: return (String) sqlTypeNames.get(new Integer(sqlType));
257: }
258:
259: /**
260: * Get the SQL to Database type Map
261: *
262: * @return A hashtable getting this context's SqlToDB map.
263: */
264: public Map getSQLToDBMap() {
265: return sqlToDB;
266: }
267:
268: /* getSQLToDBMap(String) */
269:
270: /**
271: * Map a type used in Expresso to an appropriate database-specific type,
272: * utilizing the default type mapping followed by the custom type
273: * mapping(s) for this context (if any)
274: *
275: * @param expressoType The java.sql datatype to check against.
276: * @return The appropriate datatype for this database context.
277: * @throws DBException If there's an getting the datatype.
278: */
279: public String getTypeForDB(String expressoType) throws DBException {
280: /* First map the expresso type to the java.sql.Types type */
281: String sqlType = (String) expressoToSQL.get(expressoType);
282:
283: if (sqlType == null) {
284: throw new DBException(
285: "There was no mapping of types from the"
286: + " expresso type '"
287: + expressoType
288: + "' to a java.sql.Types String "
289: + "type - perhaps there should be a type mapping "
290: + "entry in expresso-config.xml?");
291: }
292:
293: /* Now map the java.sql.Type to a database type */
294: String dbType = (String) sqlToDB.get(sqlType);
295:
296: if (dbType == null) {
297: Integer javaIntType = (Integer) expressoToJava.get(sqlType
298: .toLowerCase());
299:
300: if (javaIntType == null) {
301: throw new DBException(
302: "There was no mapping of types from the"
303: + " expresso type '"
304: + expressoType
305: + "' to a java.sql.Types "
306: + "type integer - perhaps there should be a type mapping "
307: + "entry in expresso-config.xml?");
308: }
309:
310: dbType = (String) sqlToDB.get(javaIntType);
311:
312: if (dbType == null) {
313: throw new DBException(
314: "There was no mapping of the java.sql.Type."
315: + sqlType
316: + " type to a specific database type. Either this "
317: + "type is not supported by the specified JDBC driver, or "
318: + "there should be an type mapping entry in "
319: + "expresso-config.xml");
320: }
321: }
322:
323: return dbType;
324: }
325:
326: /* typeForDB(String, String) */
327:
328: /**
329: * Map a type used in SQL to an appropriate expresso-specific type
330: *
331: * @param sqlType The java.sql datatype to check against.
332: * @return The appropriate datatype from this database context.
333: * @throws DBException If there's an getting the datatype.
334: */
335: public String getTypeForExpresso(int sqlType) throws DBException {
336: /* First get the string name from the type */
337: Integer sqlInt = new Integer(sqlType);
338: String sqlStr = (String) typeToString.get(sqlInt);
339:
340: if (sqlStr == null) {
341: throw new DBException("There was no mapping for type "
342: + sqlType + " to a string type ");
343: }
344:
345: String expressoType = (String) expressoFromSQL.get(sqlStr
346: .toLowerCase());
347:
348: if (expressoType == null) {
349: throw new DBException(
350: "There was no mapping of types from the"
351: + " sql type '" + sqlStr
352: + "' to a expresso Type ");
353: }
354:
355: return expressoType;
356: }
357:
358: /* typeForExpresso(String, int) */
359:
360: /**
361: * Retrieve a 'friendly' name for a java.sql.Type integer
362: *
363: * @param sqlType the java.sql.Types integer value
364: * @return a String corresponding to that integer value.
365: */
366: public String getTypeForSQL(int sqlType) {
367: return (String) typeToString.get(new Integer(sqlType));
368: }
369:
370: /**
371: * Sets up all the types now that we know the parent's data context.
372: *
373: * @param newConfig Configuration settings.
374: * @throws ConfigurationException upon error
375: */
376: public synchronized void configure(Configuration newConfig)
377: throws ConfigurationException {
378: synchronized (TypeMapper.class) {
379: LocatorUtils lc = new LocatorUtils(this );
380: dataContext = lc.getDataContextName(this );
381:
382: try {
383: if (dataContext != null) {
384: this .initializeTypes(dataContext);
385: mapInstances.put(dataContext, this );
386: } else {
387: throw new ConfigurationException(
388: "Unable to find parent data context!");
389: }
390: } catch (DBException ex) {
391: log.error("Error configuring TypeMapper", ex);
392: throw new ConfigurationException(
393: "Error Configuring TypeMapper", ex);
394: } catch (Throwable t) {
395: log.error("Error configuring TypeMapper", t);
396: throw new ConfigurationException(
397: "Error Configuring TypeMapper", t);
398: }
399: }
400: }
401:
402: /**
403: * Destroys the component. Removes the mapinstances and deallocates all
404: * the HashMaps that were allocated
405: */
406: public void destroy() {
407: synchronized (TypeMapper.class) {
408: if (mapInstances != null) {
409: mapInstances.remove(dataContext);
410: expressoToSQL = null;
411: }
412:
413: expressoToSQL = null;
414: expressoFromSQL = null;
415: sqlToDB = null;
416: typeToString = null;
417: expressoToJava = null;
418: sqlTypeNames = null;
419: }
420: }
421:
422: /**
423: * Any quick initializations here.
424: */
425: public void initialize() {
426: componentConfiguration = true;
427: }
428:
429: /**
430: * Reconfigures the TypeMapper. Resets all the HashMaps and reinitializes
431: * all the type mappings.
432: *
433: * @param newConfig the new Configuration bean.
434: * @throws ConfigurationException upon reconfiguration error.
435: */
436: public synchronized void reconfigure(Configuration newConfig)
437: throws ConfigurationException {
438: synchronized (TypeMapper.class) {
439: LocatorUtils lc = new LocatorUtils(this );
440: dataContext = lc.getDataContextName(this );
441: mapInstances.remove(dataContext);
442:
443: try {
444: expressoToSQL = new HashMap(30);
445: expressoFromSQL = new HashMap(30);
446: sqlToDB = new HashMap(30);
447: typeToString = new HashMap(30);
448: expressoToJava = new HashMap(30);
449: sqlTypeNames = new HashMap(30);
450: this .initializeTypes(dataContext);
451: } catch (DBException ex) {
452: throw new ConfigurationException(
453: "Error Configuring TypeMapper", ex);
454: }
455:
456: mapInstances.put(dataContext, this );
457: }
458: }
459:
460: /**
461: * Initialize the mappings between java types, expresso types, and SQL
462: * types.
463: *
464: * @param dataContext the data context to map for
465: * @throws DBException upon error
466: */
467: protected void initializeTypes(String dataContext)
468: throws DBException {
469: if (log.isInfoEnabled()) {
470: log.info("Initializing Type Mapping for context: "
471: + dataContext);
472: }
473:
474: buildTypeToString();
475: buildSqlTypeNames();
476: buildExpressoToSQL();
477:
478: /* get the expresso type from an SQL type
479: we use the reverse mapping of the
480: expressoToSQL table */
481: for (Iterator i = expressoToSQL.keySet().iterator(); i
482: .hasNext();) {
483: String oneKey = (String) i.next();
484: String oneValue = (String) expressoToSQL.get(oneKey);
485: expressoFromSQL.put(oneValue.toLowerCase(), oneKey);
486: }
487:
488: /**
489: * Now initialize the java.sql.Type to database-specific type mappings
490: */
491: DBConnection myConnection = null;
492: DBConnectionPool myPool = null;
493:
494: buildSqlToDB();
495:
496: //
497: //We fill the Expresso to java.sql.Types map with the reverse
498: //so we can peform reverse lookups
499: //
500: for (Iterator i = typeToString.keySet().iterator(); i.hasNext();) {
501: Integer aKey = (Integer) i.next();
502: String aValue = (String) typeToString.get(aKey);
503: expressoToJava.put(aValue.toLowerCase(), aKey);
504: }
505:
506: //Add aliases
507: expressoToJava.put(DBField.INTEGER_TYPE, new Integer(
508: java.sql.Types.INTEGER));
509: expressoToJava.put(DBField.BOOLEAN_TYPE, new Integer(
510: java.sql.Types.BIT));
511: expressoToJava.put(DBField.LONG_TYPE, new Integer(
512: java.sql.Types.BIGINT));
513: expressoToJava.put(DBField.DATETIME_TYPE, new Integer(
514: java.sql.Types.TIMESTAMP));
515: expressoToJava.put(DBField.TEXT_TYPE, new Integer(
516: java.sql.Types.LONGVARCHAR));
517: expressoToJava.put(DBField.AUTOINC_TYPE, new Integer(
518: java.sql.Types.INTEGER));
519:
520: try {
521: myPool = DBConnectionPool.getInstance(dataContext);
522: myConnection = myPool.getConnection("Schema");
523:
524: /* Add any mappings specified by the SQL connection itself, */
525: /* overridding the default if appropriate */
526: Hashtable dbMap = myConnection.getTypeMap();
527: myPool.release(myConnection);
528:
529: Integer oneIntValue = null;
530:
531: for (Enumeration ex = dbMap.keys(); ex.hasMoreElements();) {
532: String oneKey = (String) ex.nextElement();
533: oneIntValue = (Integer) dbMap.get(oneKey);
534:
535: String oneValue = (String) typeToString
536: .get(oneIntValue);
537:
538: if (oneValue == null) {
539: log
540: .warn("Unable to map java.sql.Types value "
541: + oneIntValue.toString()
542: + " to a string. The database "
543: + " may have returned an invalid type map. New type being added...");
544: typeToString.put(oneIntValue, oneKey);
545: oneValue = (String) typeToString.get(oneIntValue);
546: } else {
547: sqlToDB.put(oneIntValue, StringUtil.notNull(oneKey)
548: .toLowerCase());
549: expressoToJava.put(StringUtil.notNull(oneKey)
550: .toLowerCase(), oneIntValue);
551: }
552: }
553: } catch (DBException de) {
554: log.error("Error initializing types", de);
555: throw new DBException(de);
556: } catch (Throwable t) {
557: log.error("Error initializing types", t);
558: throw new DBException(t);
559: } finally {
560: if (myPool != null) {
561: myPool.release(myConnection);
562: }
563: }
564:
565: mergeTypeMappings();
566: }
567:
568: private void buildExpressoToSQL() throws DBException {
569: /* First initialize the expresso to java.sql.Type mappings */
570: expressoToSQL.put(DBField.ARRAY_TYPE, "ARRAY");
571: expressoToSQL.put(DBField.BIGINT_TYPE, "BIGINT");
572:
573: // long is a synonym for bigint
574: expressoToSQL.put(DBField.LONG_TYPE, "BIGINT");
575: expressoToSQL.put(DBField.BINARY_TYPE, "BINARY");
576: expressoToSQL.put(DBField.BIT_TYPE, "BIT");
577:
578: // boolean is synonym
579: expressoToSQL.put(DBField.BOOLEAN_TYPE, "BIT");
580: expressoToSQL.put(DBField.BLOB_TYPE, "BLOB");
581: expressoToSQL.put(DBField.CHAR_TYPE, "CHAR");
582: expressoToSQL.put(DBField.CLOB_TYPE, "CLOB");
583: expressoToSQL.put(DBField.DATE_TYPE, "DATE");
584: expressoToSQL.put(DBField.DECIMAL_TYPE, "DECIMAL");
585: expressoToSQL.put("distinct", "DISTINCT");
586: expressoToSQL.put(DBField.DOUBLE_TYPE, "DOUBLE");
587: expressoToSQL.put(DBField.FLOAT_TYPE, "FLOAT");
588: expressoToSQL.put(DBField.INTEGER_TYPE, "INTEGER");
589:
590: // int is a synonym
591: expressoToSQL.put(DBField.INT_TYPE, "INTEGER");
592: expressoToSQL.put(DBField.JAVA_OBJECT, "JAVA_OBJECT");
593: expressoToSQL.put(DBField.LONGVARBINARY, "LONGVARBINARY");
594: expressoToSQL.put(DBField.LONGVARCHAR_TYPE, "LONGVARCHAR");
595: expressoToSQL.put(DBField.NUMERIC_TYPE, "NUMERIC");
596: expressoToSQL.put(DBField.OTHER_TYPE, "OTHER");
597: expressoToSQL.put(DBField.REAL_TYPE, "REAL");
598: expressoToSQL.put(DBField.REF_TYPE, "REF");
599: expressoToSQL.put(DBField.SMALLINT_TYPE, "SMALLINT");
600: expressoToSQL.put(DBField.STRUCT_TYPE, "STRUCT");
601: expressoToSQL.put(DBField.TIME_TYPE, "TIME");
602: expressoToSQL.put(DBField.TIMESTAMP_TYPE, "TIMESTAMP");
603:
604: // datetime is synonym
605: expressoToSQL.put(DBField.DATETIME_TYPE, "TIMESTAMP");
606: expressoToSQL.put(DBField.TINYINT_TYPE, "TINYINT");
607: expressoToSQL.put(DBField.VARBINARY_TYPE, "VARBINARY");
608: expressoToSQL.put(DBField.VARCHAR_TYPE, "VARCHAR");
609:
610: // TEXT_TYPE synonym for longvarchar
611: expressoToSQL.put(DBField.TEXT_TYPE, "LONGVARCHAR");
612:
613: // auto-inc is unique to expresso
614: expressoToSQL.put(DBField.AUTOINC_TYPE, "INTEGER");
615:
616: /* The user can specify in the properties file for each db/context mappings to
617: * specify new expresso types and which java.sql.Type they correspond to.
618: * These mappings take the form:
619: * <type-mapping>
620: * <expresso-type>foo</expresso-type>
621: * <java-type>CHAR</java-type>
622: * </type-mapping>
623: * This would allow use of the type "foo" in an "addField" statement for a
624: * db object, and would map it to the java.sql.Type.CHAR data type
625: */
626: TypeMappingConfig oneMap = null;
627:
628: for (Enumeration e = this .getTypeMappings().elements(); e
629: .hasMoreElements();) {
630: oneMap = (TypeMappingConfig) e.nextElement();
631:
632: if ((oneMap.getExpressoType() != null)
633: && (oneMap.getJavaType() != null)) {
634: expressoToSQL.put(oneMap.getExpressoType(), oneMap
635: .getJavaType());
636: }
637: }
638: }
639:
640: /**
641: * Builds the SQL to DB Map. The SQL to DB map is keyed by the
642: * java.sql.Types
643: */
644: private void buildSqlToDB() {
645: /**
646: * default mapping of java.sql.Types to actual database types
647: */
648: sqlToDB.put(new Integer(java.sql.Types.INTEGER),
649: DBField.INT_TYPE);
650: sqlToDB.put(new Integer(java.sql.Types.VARCHAR),
651: DBField.VARCHAR_TYPE);
652: sqlToDB
653: .put(new Integer(java.sql.Types.CHAR),
654: DBField.CHAR_TYPE);
655: sqlToDB
656: .put(new Integer(java.sql.Types.DATE),
657: DBField.DATE_TYPE);
658: sqlToDB.put(new Integer(java.sql.Types.TIMESTAMP),
659: DBField.DATETIME_TYPE);
660: sqlToDB
661: .put(new Integer(java.sql.Types.TIME),
662: DBField.TIME_TYPE);
663: sqlToDB.put(new Integer(java.sql.Types.FLOAT),
664: DBField.FLOAT_TYPE);
665: sqlToDB.put(new Integer(java.sql.Types.DOUBLE),
666: DBField.DOUBLE_TYPE);
667: sqlToDB.put(new Integer(java.sql.Types.LONGVARCHAR),
668: DBField.LONGVARCHAR_TYPE);
669: sqlToDB
670: .put(new Integer(java.sql.Types.REAL),
671: DBField.REAL_TYPE);
672: sqlToDB.put(new Integer(java.sql.Types.SMALLINT),
673: DBField.SMALLINT_TYPE);
674: sqlToDB.put(new Integer(java.sql.Types.TINYINT),
675: DBField.TINYINT_TYPE);
676: sqlToDB.put(new Integer(java.sql.Types.NUMERIC),
677: DBField.NUMERIC_TYPE);
678: sqlToDB.put(new Integer(java.sql.Types.DECIMAL),
679: DBField.DECIMAL_TYPE);
680: sqlToDB.put(new Integer(java.sql.Types.BIGINT),
681: DBField.LONG_TYPE);
682: sqlToDB.put(new Integer(java.sql.Types.ARRAY),
683: DBField.ARRAY_TYPE);
684: sqlToDB.put(new Integer(java.sql.Types.BINARY),
685: DBField.BINARY_TYPE);
686: sqlToDB.put(new Integer(java.sql.Types.BIT), DBField.BIT_TYPE);
687: sqlToDB
688: .put(new Integer(java.sql.Types.BLOB),
689: DBField.BLOB_TYPE);
690: sqlToDB
691: .put(new Integer(java.sql.Types.CLOB),
692: DBField.CLOB_TYPE);
693: sqlToDB.put(new Integer(java.sql.Types.DISTINCT), "distinct");
694: sqlToDB.put(new Integer(java.sql.Types.JAVA_OBJECT),
695: DBField.JAVA_OBJECT);
696: sqlToDB.put(new Integer(java.sql.Types.LONGVARBINARY),
697: DBField.LONGVARBINARY);
698: sqlToDB
699: .put(new Integer(java.sql.Types.NULL),
700: DBField.NULL_TYPE);
701: sqlToDB.put(new Integer(java.sql.Types.OTHER),
702: DBField.OTHER_TYPE);
703: sqlToDB.put(new Integer(java.sql.Types.REF), DBField.REF_TYPE);
704: sqlToDB.put(new Integer(java.sql.Types.STRUCT), "struct");
705: sqlToDB.put(new Integer(java.sql.Types.VARBINARY),
706: DBField.VARBINARY_TYPE);
707: }
708:
709: /**
710: * Builds the sqlTypeNames
711: */
712: private void buildSqlTypeNames() {
713: //
714: //Java integer to a friendly string
715: //
716: sqlTypeNames.put(new Integer(java.sql.Types.LONGVARCHAR),
717: "java.sql.Types.LONGVARCHAR");
718: sqlTypeNames.put(new Integer(java.sql.Types.ARRAY),
719: "java.sql.Types.ARRAY");
720: sqlTypeNames.put(new Integer(java.sql.Types.BIGINT),
721: "java.sql.Types.BIGINT");
722: sqlTypeNames.put(new Integer(java.sql.Types.BINARY),
723: "java.sql.Types.BINARY");
724: sqlTypeNames.put(new Integer(java.sql.Types.BIT),
725: "java.sql.Types.BIT");
726: sqlTypeNames.put(new Integer(java.sql.Types.BLOB),
727: "java.sql.Types.BLOB");
728: sqlTypeNames.put(new Integer(java.sql.Types.CHAR),
729: "java.sql.Types.CHAR");
730: sqlTypeNames.put(new Integer(java.sql.Types.CLOB),
731: "java.sql.Types.CLOB");
732: sqlTypeNames.put(new Integer(java.sql.Types.DATE),
733: "java.sql.Types.DATE");
734: sqlTypeNames.put(new Integer(java.sql.Types.DECIMAL),
735: "java.sql.Types.DECIMAL");
736: sqlTypeNames.put(new Integer(java.sql.Types.DISTINCT),
737: "java.sql.Types.DISTINCT");
738: sqlTypeNames.put(new Integer(java.sql.Types.DOUBLE),
739: "java.sql.Types.DOUBLE");
740: sqlTypeNames.put(new Integer(java.sql.Types.FLOAT),
741: "java.sql.Types.FLOAT");
742: sqlTypeNames.put(new Integer(java.sql.Types.INTEGER),
743: "java.sql.Types.INTEGER");
744: sqlTypeNames.put(new Integer(java.sql.Types.JAVA_OBJECT),
745: "java.sql.Types.JAVA_OBJECT");
746: sqlTypeNames.put(new Integer(java.sql.Types.LONGVARBINARY),
747: "java.sql.Types.LONGVARBINARY");
748: sqlTypeNames.put(new Integer(java.sql.Types.LONGVARCHAR),
749: "java.sql.Types.LONGVARCHAR");
750: sqlTypeNames.put(new Integer(java.sql.Types.NUMERIC),
751: "java.sql.Types.NUMERIC");
752: sqlTypeNames.put(new Integer(java.sql.Types.OTHER),
753: "java.sql.Types.OTHER");
754: sqlTypeNames.put(new Integer(java.sql.Types.REAL),
755: "java.sql.Types.REAL");
756: sqlTypeNames.put(new Integer(java.sql.Types.REF),
757: "java.sql.Types.REF");
758: sqlTypeNames.put(new Integer(java.sql.Types.SMALLINT),
759: "java.sql.Types.SMALLINT");
760: sqlTypeNames.put(new Integer(java.sql.Types.STRUCT),
761: "java.sql.Types.STRUCT");
762: sqlTypeNames.put(new Integer(java.sql.Types.TIME),
763: "java.sql.Types.TIME");
764: sqlTypeNames.put(new Integer(java.sql.Types.TIMESTAMP),
765: "java.sql.Types.TIMESTAMP");
766: sqlTypeNames.put(new Integer(java.sql.Types.TINYINT),
767: "java.sql.Types.TINYINT");
768: sqlTypeNames.put(new Integer(java.sql.Types.VARBINARY),
769: "java.sql.Types.VARBINARY");
770: sqlTypeNames.put(new Integer(java.sql.Types.VARCHAR),
771: "java.sql.Types.VARCHAR");
772: }
773:
774: /**
775: * Builds the type to string HashMap.
776: */
777: private void buildTypeToString() {
778: typeToString.put(new Integer(java.sql.Types.LONGVARCHAR),
779: "LONGVARCHAR");
780: typeToString.put(new Integer(java.sql.Types.ARRAY), "ARRAY");
781: typeToString.put(new Integer(java.sql.Types.BIGINT), "BIGINT");
782: typeToString.put(new Integer(java.sql.Types.BINARY), "BINARY");
783: typeToString.put(new Integer(java.sql.Types.BIT), "BIT");
784: typeToString.put(new Integer(java.sql.Types.BLOB), "BLOB");
785: typeToString.put(new Integer(java.sql.Types.CHAR), "CHAR");
786: typeToString.put(new Integer(java.sql.Types.CLOB), "CLOB");
787: typeToString.put(new Integer(java.sql.Types.DATE), "DATE");
788: typeToString
789: .put(new Integer(java.sql.Types.DECIMAL), "DECIMAL");
790: typeToString.put(new Integer(java.sql.Types.DISTINCT),
791: "DISTINCT");
792: typeToString.put(new Integer(java.sql.Types.DOUBLE), "DOUBLE");
793: typeToString.put(new Integer(java.sql.Types.FLOAT), "FLOAT");
794: typeToString
795: .put(new Integer(java.sql.Types.INTEGER), "INTEGER");
796: typeToString.put(new Integer(java.sql.Types.JAVA_OBJECT),
797: "JAVA_OBJECT");
798: typeToString.put(new Integer(java.sql.Types.LONGVARBINARY),
799: "LONGVARBINARY");
800: typeToString.put(new Integer(java.sql.Types.LONGVARCHAR),
801: "LONGVARCHAR");
802: typeToString
803: .put(new Integer(java.sql.Types.NUMERIC), "NUMERIC");
804: typeToString.put(new Integer(java.sql.Types.OTHER), "OTHER");
805: typeToString.put(new Integer(java.sql.Types.REAL), "REAL");
806: typeToString.put(new Integer(java.sql.Types.REF), "REF");
807: typeToString.put(new Integer(java.sql.Types.SMALLINT),
808: "SMALLINT");
809: typeToString.put(new Integer(java.sql.Types.STRUCT), "STRUCT");
810: typeToString.put(new Integer(java.sql.Types.TIME), "TIME");
811: typeToString.put(new Integer(java.sql.Types.TIMESTAMP),
812: "TIMESTAMP");
813: typeToString
814: .put(new Integer(java.sql.Types.TINYINT), "TINYINT");
815: typeToString.put(new Integer(java.sql.Types.VARBINARY),
816: "VARBINARY");
817: typeToString
818: .put(new Integer(java.sql.Types.VARCHAR), "VARCHAR");
819: }
820:
821: private void mergeTypeMappings() throws DBException {
822: /* The user can specify in their properties file mappings to force a
823: * specific java.sql.Type to be mapped to a particular database type.
824: * These mappings take the form:
825: <type-mapping>
826: <java-type>INTEGER</java-type>
827: <db-type>smallint</db-type>
828: </type-mapping>
829: * This would force the database to use the "smallint" string when creating
830: * fields in a table that use the java.sql.Type.INTEGER data type
831: */
832: TypeMappingConfig oneMapping = null;
833:
834: for (Enumeration e = this .getTypeMappings().elements(); e
835: .hasMoreElements();) {
836: oneMapping = (TypeMappingConfig) e.nextElement();
837:
838: if ((oneMapping.getDBType() != null)
839: && (oneMapping.getJavaType() != null)) {
840: String value = oneMapping.getJavaType().toLowerCase();
841: Integer key = (Integer) expressoToJava.get(value);
842:
843: if (key == null) {
844: log.warn("Unable to map "
845: + oneMapping.getJavaType()
846: + " to java.SQL.Types data type");
847: } else {
848: sqlToDB.put(key, ((String) oneMapping.getDBType()
849: .toLowerCase()));
850: expressoToJava.put(value, key);
851: }
852: }
853: }
854: }
855:
856: /**
857: * Private method that uses either the old ConfigManager way of initialization
858: * or the new Configuration Methods.
859: *
860: * @return Vector of TypeMapping objects
861: * @throws DBException upon error getting the configuration mappings [Old way
862: * only]
863: * @todo Change return value to ArrayList
864: */
865: private java.util.Vector getTypeMappings() throws DBException {
866: if (componentConfiguration) {
867: //Get the Type Mappings from the Persistence Manager
868: DBConfig config = (DBConfig) this .getParent()
869: .locateComponent("DBConfig");
870: return new java.util.Vector(config.getCurrentConfig()
871: .getTypeMappings());
872: } else {
873: /* Mapping from the java.sql.Types to equivilant strings */
874: ConfigContext myContext = null;
875:
876: try {
877: myContext = ConfigManager.getContext(dataContext);
878: return myContext.getTypeMappings();
879: } catch (com.jcorporate.expresso.core.misc.ConfigurationException ce) {
880: throw new DBException(ce);
881: }
882: }
883:
884: }
885: }
|