001: /*
002: * Copyright 2001-2007 Geert Bevin <gbevin[remove] at uwyn dot com>
003: * Distributed under the terms of either:
004: * - the common development and distribution license (CDDL), v1.0; or
005: * - the GNU Lesser General Public License, v2.1 or later
006: * $Id: Common.java 3695 2007-03-16 09:26:50Z gbevin $
007: */
008: package com.uwyn.rife.database.types.databasedrivers;
009:
010: import java.sql.*;
011:
012: import com.uwyn.rife.database.DbPreparedStatement;
013: import com.uwyn.rife.database.exceptions.DatabaseException;
014: import com.uwyn.rife.database.types.SqlConversion;
015: import com.uwyn.rife.site.Constrained;
016: import com.uwyn.rife.site.ConstrainedProperty;
017: import com.uwyn.rife.tools.FileUtils;
018: import com.uwyn.rife.tools.JavaSpecificationUtils;
019: import com.uwyn.rife.tools.StringUtils;
020: import java.io.InputStream;
021: import java.io.StringReader;
022: import java.math.BigDecimal;
023: import java.util.Calendar;
024: import java.util.Date;
025:
026: public abstract class Common implements SqlConversion {
027: protected abstract Object retrieveFieldObject(ResultSet resultSet,
028: int columnNumber, int type) throws SQLException;
029:
030: /*
031: * UNSUPPORTED SQL TYPES :
032: * DATALINK
033: * DISTINCT
034: * NULL
035: * STRUCT
036: */
037: public Object getTypedObject(ResultSet resultSet, int columnNumber,
038: int type, Class targetType) throws DatabaseException {
039: if (null == resultSet)
040: throw new IllegalArgumentException(
041: "resultSet can't be null.");
042: if (columnNumber < 1)
043: throw new IllegalArgumentException(
044: "columnNumber must be equal or bigger than 1.");
045: if (null == targetType)
046: throw new IllegalArgumentException(
047: "targetType can't be null.");
048:
049: try {
050: Object field = retrieveFieldObject(resultSet, columnNumber,
051: type);
052: if (null == field) {
053: return null;
054: }
055:
056: Object typed = getTypedObject(field, targetType);
057: if (null == typed) {
058: throw new DatabaseException(
059: "Impossible to return a compatible typed object. The target type is '"
060: + targetType.getName()
061: + "' and the result type is '"
062: + field.getClass().getName() + "'.");
063: }
064:
065: return typed;
066: } catch (SQLException e) {
067: throw new DatabaseException(
068: "Unexpected exception while obtaining a typed object for column '"
069: + columnNumber + "', type '" + type
070: + "' and target type '"
071: + targetType.getName() + "'", e);
072: }
073: }
074:
075: protected Object getTypedObject(Object result, Class targetType) {
076: try {
077: if (!targetType.isInstance(result)) {
078: Class result_class = result.getClass();
079: if (targetType == boolean.class
080: && result_class == Boolean.class
081: || targetType == byte.class
082: && result_class == Byte.class
083: || targetType == double.class
084: && result_class == Double.class
085: || targetType == float.class
086: && result_class == Float.class
087: || targetType == int.class
088: && result_class == Integer.class
089: || targetType == long.class
090: && result_class == Long.class
091: || targetType == short.class
092: && result_class == Short.class
093: || targetType == char.class
094: && result_class == Character.class) {
095: return result;
096: } else {
097: try {
098: if (targetType == boolean.class
099: || targetType == Boolean.class) {
100: return Boolean
101: .valueOf(StringUtils
102: .convertToBoolean(result
103: .toString()));
104: } else if (targetType == byte.class
105: || targetType == Byte.class) {
106: return new Byte(result.toString());
107: } else if (targetType == double.class
108: || targetType == Double.class) {
109: return new Double(result.toString());
110: } else if (targetType == float.class
111: || targetType == Float.class) {
112: return new Float(result.toString());
113: } else if (targetType == int.class
114: || targetType == Integer.class) {
115: return new Integer(result.toString());
116: } else if (targetType == long.class
117: || targetType == Long.class) {
118: return new Long(result.toString());
119: } else if (targetType == short.class
120: || targetType == Short.class) {
121: return new Short(result.toString());
122: } else if (targetType == BigDecimal.class) {
123: return new BigDecimal(result.toString());
124: } else if (targetType == char.class
125: || targetType == Character.class) {
126: return new Character(result.toString()
127: .charAt(0));
128: } else if (targetType == StringBuilder.class) {
129: return new StringBuilder(result.toString());
130: } else if (targetType == StringBuffer.class) {
131: return new StringBuffer(result.toString());
132: }
133: // convert the Timestamp type into other time / date types
134: else if (targetType == Calendar.class
135: && (result_class == Timestamp.class || result instanceof Timestamp)) {
136: Calendar cal = Calendar.getInstance();
137: cal.setTime((Timestamp) result);
138: return cal;
139: } else if (targetType == Date.class
140: && (result_class == Timestamp.class || result instanceof Timestamp)) {
141: return new Date(((Timestamp) result)
142: .getTime());
143: } else if (targetType == java.sql.Date.class
144: && (result_class == Timestamp.class || result instanceof Timestamp)) {
145: return new java.sql.Date(
146: ((Timestamp) result).getTime());
147: } else if (targetType == Time.class
148: && (result_class == Timestamp.class || result instanceof Timestamp)) {
149: return new Time(((Timestamp) result)
150: .getTime());
151: }
152: // convert the java.sql.Date type into other time / date types
153: else if (targetType == Calendar.class
154: && result_class == java.sql.Date.class) {
155: Calendar cal = Calendar.getInstance();
156: cal.setTime((java.sql.Date) result);
157: return cal;
158: } else if (targetType == Date.class
159: && result_class == java.sql.Date.class) {
160: return new Date(((java.sql.Date) result)
161: .getTime());
162: } else if (targetType == Time.class
163: && result_class == java.sql.Date.class) {
164: return new Time(((java.sql.Date) result)
165: .getTime());
166: } else if (targetType == Timestamp.class
167: && result_class == java.sql.Date.class) {
168: return new Timestamp(
169: ((java.sql.Date) result).getTime());
170: }
171: // convert the Time type into other time / date types
172: else if (targetType == Calendar.class
173: && result_class == Time.class) {
174: Calendar cal = Calendar.getInstance();
175: cal.setTime((Time) result);
176: return cal;
177: } else if (targetType == Date.class
178: && result_class == Time.class) {
179: return new Date(((Time) result).getTime());
180: } else if (targetType == java.sql.Date.class
181: && result_class == Time.class) {
182: return new java.sql.Date(((Time) result)
183: .getTime());
184: } else if (targetType == Timestamp.class
185: && result_class == Time.class) {
186: return new Timestamp(((Time) result)
187: .getTime());
188: } else if (targetType == byte[].class
189: && Blob.class
190: .isAssignableFrom(result_class)) {
191: Blob blob = (Blob) result;
192: return FileUtils.readBytes(blob
193: .getBinaryStream());
194: } else if (targetType == byte[].class
195: && InputStream.class
196: .isAssignableFrom(result_class)) {
197: return FileUtils
198: .readBytes((InputStream) result);
199: } else {
200: if (JavaSpecificationUtils.isAtLeastJdk15()) {
201: if (targetType.isEnum()) {
202: return Enum.valueOf(targetType,
203: result.toString());
204: } else {
205: return CommonJdk15.getTypedObject(
206: result, targetType);
207: }
208: }
209:
210: return null;
211: }
212: } catch (NumberFormatException e) {
213: throw new DatabaseException(
214: "Impossible to convert the result type '"
215: + result_class.getName()
216: + "' with value '"
217: + result.toString()
218: + "' to the target type '"
219: + targetType.getName() + "'.",
220: e);
221: }
222: }
223: } else {
224: return result;
225: }
226: } catch (Throwable e) {
227: throw new DatabaseException(
228: "Unexpected exception while obtaining a type object for object '"
229: + result + "' for target type '"
230: + targetType.getName() + "'", e);
231: }
232: }
233:
234: public void setTypedParameter(DbPreparedStatement statement,
235: int parameterIndex, Class targetType, String name,
236: Object value, Constrained constrained)
237: throws DatabaseException {
238: if (null == statement)
239: throw new IllegalArgumentException(
240: "statement can't be null.");
241: if (parameterIndex < 1)
242: throw new IllegalArgumentException(
243: "parameterIndex must be at least 1.");
244: if (null == targetType)
245: throw new IllegalArgumentException(
246: "targetType can't be null.");
247:
248: if (targetType == String.class
249: || targetType == StringBuffer.class) {
250: if (null == value) {
251: statement.setNull(parameterIndex, Types.VARCHAR);
252: } else {
253: if (constrained != null) {
254: ConstrainedProperty property = constrained
255: .getConstrainedProperty(name);
256: if (property != null && !property.hasMaxLength()) {
257: String string_value = value.toString();
258: statement.setCharacterStream(parameterIndex,
259: new StringReader(string_value),
260: string_value.length());
261: } else {
262: statement.setString(parameterIndex, value
263: .toString());
264: }
265: } else {
266: statement.setString(parameterIndex, value
267: .toString());
268: }
269: }
270: } else if (targetType == Character.class
271: || targetType == char.class) {
272: if (null == value) {
273: statement.setNull(parameterIndex, Types.CHAR);
274: } else {
275: statement.setString(parameterIndex, value.toString());
276: }
277: } else if (targetType == Time.class
278: || Time.class.isAssignableFrom(targetType)) {
279: if (null == value) {
280: statement.setNull(parameterIndex, Types.TIME);
281: } else {
282: statement.setTime(parameterIndex, (Time) value);
283: }
284: } else if (targetType == java.sql.Date.class
285: || java.sql.Date.class.isAssignableFrom(targetType)) {
286: if (null == value) {
287: statement.setNull(parameterIndex, Types.DATE);
288: } else {
289: statement
290: .setDate(parameterIndex, (java.sql.Date) value);
291: }
292: } else if (targetType == Date.class
293: || Date.class.isAssignableFrom(targetType)) {
294: if (null == value) {
295: statement.setNull(parameterIndex, Types.TIMESTAMP);
296: } else {
297: statement
298: .setTimestamp(parameterIndex,
299: new java.sql.Timestamp(((Date) value)
300: .getTime()));
301: }
302: } else if (targetType == Calendar.class
303: || Calendar.class.isAssignableFrom(targetType)) {
304: if (null == value) {
305: statement.setNull(parameterIndex, Types.TIMESTAMP);
306: } else {
307: statement.setTimestamp(parameterIndex,
308: new java.sql.Timestamp(((Calendar) value)
309: .getTime().getTime()));
310: }
311: } else if (targetType == Timestamp.class
312: || Timestamp.class.isAssignableFrom(targetType)) {
313: if (null == value) {
314: statement.setNull(parameterIndex, Types.TIMESTAMP);
315: } else {
316: statement.setTimestamp(parameterIndex,
317: (Timestamp) value);
318: }
319: }
320: // make sure that the Boolean type is correctly caught
321: else if (targetType == Boolean.class
322: || targetType == boolean.class) {
323: if (null == value) {
324: statement.setNull(parameterIndex, Types.BOOLEAN);
325: } else {
326: statement.setBoolean(parameterIndex, ((Boolean) value)
327: .booleanValue());
328: }
329: }
330: // make sure that the Integer types are correctly caught
331: else if (targetType == Byte.class || targetType == byte.class) {
332: if (null == value) {
333: statement.setNull(parameterIndex, Types.TINYINT);
334: } else {
335: statement.setByte(parameterIndex, ((Byte) value)
336: .byteValue());
337: }
338: } else if (targetType == Short.class
339: || targetType == short.class) {
340: if (null == value) {
341: statement.setNull(parameterIndex, Types.SMALLINT);
342: } else {
343: statement.setShort(parameterIndex, ((Short) value)
344: .shortValue());
345: }
346: } else if (targetType == Integer.class
347: || targetType == int.class) {
348: if (null == value) {
349: statement.setNull(parameterIndex, Types.INTEGER);
350: } else {
351: statement.setInt(parameterIndex, ((Integer) value)
352: .intValue());
353: }
354: } else if (targetType == Long.class || targetType == long.class) {
355: if (null == value) {
356: statement.setNull(parameterIndex, Types.BIGINT);
357: } else {
358: statement.setLong(parameterIndex, ((Long) value)
359: .longValue());
360: }
361: }
362: // make sure that the Float types are correctly caught
363: else if (targetType == Float.class || targetType == float.class) {
364: if (null == value) {
365: statement.setNull(parameterIndex, Types.FLOAT);
366: } else {
367: statement.setFloat(parameterIndex, ((Float) value)
368: .floatValue());
369: }
370: } else if (targetType == Double.class
371: || targetType == double.class) {
372: if (null == value) {
373: statement.setNull(parameterIndex, Types.DOUBLE);
374: } else {
375: statement.setDouble(parameterIndex, ((Double) value)
376: .doubleValue());
377: }
378: } else if (targetType == BigDecimal.class
379: || BigDecimal.class.isAssignableFrom(targetType)) {
380: if (null == value) {
381: statement.setNull(parameterIndex, Types.NUMERIC);
382: } else {
383: statement.setBigDecimal(parameterIndex,
384: (BigDecimal) value);
385: }
386: } else if (targetType == byte[].class) {
387: if (null == value) {
388: statement.setNull(parameterIndex, Types.ARRAY);
389: } else {
390: statement.setBytes(parameterIndex, (byte[]) value);
391: }
392: } else {
393: if (JavaSpecificationUtils.isAtLeastJdk15()) {
394: if (targetType.isEnum()) {
395: if (null == value) {
396: statement
397: .setNull(parameterIndex, Types.VARCHAR);
398: } else {
399: statement.setString(parameterIndex, value
400: .toString());
401: }
402: } else {
403: if (CommonJdk15.setTypedParameter(statement,
404: parameterIndex, targetType, name, value,
405: constrained)) {
406: return;
407: }
408:
409: throw new DatabaseException(
410: "Setting a typed parameter is not supported for index '"
411: + parameterIndex
412: + "', target type '"
413: + targetType.getName()
414: + " and value '" + value + "'.");
415: }
416: }
417: }
418: }
419:
420: public String handleCommonSqlType(Class type, int precision,
421: int scale) {
422: if (JavaSpecificationUtils.isAtLeastJdk15()) {
423: if (type.isEnum()) {
424: return "VARCHAR(255)";
425: } else {
426: return CommonJdk15.getSqlType(type, precision, scale);
427: }
428: }
429:
430: return null;
431: }
432: }
|