KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > mckoi > database > global > CastHelper


1 /**
2  * com.mckoi.database.global.CastHelper 11 Oct 2001
3  *
4  * Mckoi SQL Database ( http://www.mckoi.com/database )
5  * Copyright (C) 2000, 2001, 2002 Diehl and Associates, Inc.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * Version 2 as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License Version 2 for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * Version 2 along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19  *
20  * Change Log:
21  *
22  *
23  */

24
25 package com.mckoi.database.global;
26
27 import java.text.SimpleDateFormat JavaDoc;
28 import java.text.ParseException JavaDoc;
29 import java.text.DateFormat JavaDoc;
30 import com.mckoi.util.BigNumber;
31 import java.util.Date JavaDoc;
32
33 /**
34  * Various utility methods for helping to cast a Java object to a type that
35  * is conformant to an SQL type.
36  *
37  * @author Tobias Downer
38  */

39
40 public class CastHelper {
41
42   /**
43    * A couple of standard BigNumber statics.
44    */

45   private static BigNumber BD_ZERO = BigNumber.fromLong(0);
46   private static BigNumber BD_ONE = BigNumber.fromLong(1);
47
48   /**
49    * Date, Time and Timestamp parser/formatters
50    */

51   private static DateFormat JavaDoc[] date_format_sql;
52   private static DateFormat JavaDoc[] time_format_sql;
53   private static DateFormat JavaDoc[] ts_format_sql;
54
55   static {
56     // The SQL time/date formatters
57
date_format_sql = new DateFormat JavaDoc[1];
58     date_format_sql[0] = new SimpleDateFormat JavaDoc("yyyy-MM-dd");
59
60     time_format_sql = new DateFormat JavaDoc[4];
61     time_format_sql[0] = new SimpleDateFormat JavaDoc("HH:mm:ss.S z");
62     time_format_sql[1] = new SimpleDateFormat JavaDoc("HH:mm:ss.S");
63     time_format_sql[2] = new SimpleDateFormat JavaDoc("HH:mm:ss z");
64     time_format_sql[3] = new SimpleDateFormat JavaDoc("HH:mm:ss");
65
66     ts_format_sql = new DateFormat JavaDoc[4];
67     ts_format_sql[0] = new SimpleDateFormat JavaDoc("yyyy-MM-dd HH:mm:ss.S z");
68     ts_format_sql[1] = new SimpleDateFormat JavaDoc("yyyy-MM-dd HH:mm:ss.S");
69     ts_format_sql[2] = new SimpleDateFormat JavaDoc("yyyy-MM-dd HH:mm:ss z");
70     ts_format_sql[3] = new SimpleDateFormat JavaDoc("yyyy-MM-dd HH:mm:ss");
71   }
72
73
74
75   /**
76    * Converts the given object to an SQL JAVA_OBJECT type by serializing
77    * the object.
78    */

79   private static Object JavaDoc toJavaObject(Object JavaDoc ob) {
80     try {
81       return ObjectTranslator.serialize(ob);
82     }
83     catch (Throwable JavaDoc e) {
84       throw new Error JavaDoc("Can't serialize object " + ob.getClass());
85     }
86   }
87
88   /**
89    * Formats the date object as a standard SQL string.
90    */

91   private static String JavaDoc formatDateAsString(Date JavaDoc d) {
92     synchronized (ts_format_sql) {
93       // ISSUE: We have to assume the date is a time stamp because we don't
94
// know if the date object represents an SQL DATE, TIMESTAMP or TIME.
95
return ts_format_sql[1].format(d);
96     }
97   }
98
99   /**
100    * Returns the given string padded or truncated to the given size. If size
101    * is -1 then the size doesn't matter.
102    */

103   private static String JavaDoc paddedString(String JavaDoc str, int size) {
104     if (size == -1) {
105       return str;
106     }
107     int dif = size - str.length();
108     if (dif > 0) {
109       StringBuffer JavaDoc buf = new StringBuffer JavaDoc(str);
110       for (int n = 0; n < dif; ++n) {
111         buf.append(' ');
112       }
113       return new String JavaDoc(buf);
114     }
115     else if (dif < 0) {
116       return str.substring(0, size);
117     }
118     return str;
119   }
120
121   /**
122    * Returns the given long value as a date object.
123    */

124   private static Date JavaDoc toDate(long time) {
125     return new Date JavaDoc(time);
126   }
127
128   /**
129    * Converts the given string to a BigNumber. Returns 0 if the cast fails.
130    */

131   private static BigNumber toBigNumber(String JavaDoc str) {
132     try {
133       return BigNumber.fromString(str);
134     }
135     catch (Throwable JavaDoc e) {
136       return BD_ZERO;
137     }
138   }
139
140   /**
141    * Helper that generates an appropriate error message for a date format error.
142    */

143   private static String JavaDoc dateErrorString(String JavaDoc msg, DateFormat JavaDoc[] df) {
144     String JavaDoc pattern = "";
145     if (df[0] instanceof SimpleDateFormat JavaDoc) {
146       SimpleDateFormat JavaDoc sdf = (SimpleDateFormat JavaDoc) df[0];
147       pattern = "(" + sdf.toPattern() + ")";
148     }
149     return msg + pattern;
150   }
151   
152   /**
153    * Parses a String as an SQL date.
154    */

155   public static Date JavaDoc toDate(String JavaDoc str) {
156     synchronized(date_format_sql) {
157       for (int i = 0; i < date_format_sql.length; ++i) {
158         try {
159           return date_format_sql[i].parse(str);
160         }
161         catch (ParseException JavaDoc e) {}
162       }
163       throw new RuntimeException JavaDoc(
164             dateErrorString("Unable to parse string as a date ",
165                             date_format_sql));
166     }
167   }
168
169   /**
170    * Parses a String as an SQL time.
171    */

172   public static Date JavaDoc toTime(String JavaDoc str) {
173     synchronized(time_format_sql) {
174       for (int i = 0; i < time_format_sql.length; ++i) {
175         try {
176           return time_format_sql[i].parse(str);
177         }
178         catch (ParseException JavaDoc e) {}
179       }
180       throw new RuntimeException JavaDoc(
181             dateErrorString("Unable to parse string as a time ",
182                             time_format_sql));
183     }
184   }
185
186   /**
187    * Parses a String as an SQL timestamp.
188    */

189   public static Date JavaDoc toTimeStamp(String JavaDoc str) {
190     synchronized(ts_format_sql) {
191       for (int i = 0; i < ts_format_sql.length; ++i) {
192         try {
193           return ts_format_sql[i].parse(str);
194         }
195         catch (ParseException JavaDoc e) {}
196       }
197       throw new RuntimeException JavaDoc(
198             dateErrorString("Unable to parse string as a timestamp ",
199                             ts_format_sql));
200     }
201   }
202
203
204
205
206
207
208   /**
209    * Casts a Java object to the SQL type specified by the given
210    * DataTableColumnDef object. This is used for the following engine
211    * functions;
212    * <ol>
213    * <li> To prepare a value for insertion into the data store. For example,
214    * the table column may be STRING but the value here is a BigNumber.
215    * <li> To cast an object to a specific type in an SQL function such as
216    * CAST.
217    * </ol>
218    * Given any supported object, this will return the internal database
219    * representation of the object as either NullObject, BigNumber, String,
220    * Date, Boolean or ByteLongObject.
221    *
222    * @param ob the Object to cast to the given type
223    * @param sql_type the enumerated sql type, eg. SQLTypes.LONGVARCHAR
224    * @param sql_size the size of the type. For example, CHAR(20)
225    * @param sql_scale the scale of the numerical type.
226    * @param sql_type_string 'sql_type' as a human understandable string,
227    * eg. "LONGVARCHAR"
228    */

229   public static Object JavaDoc castObjectToSQLType(Object JavaDoc ob,
230           int sql_type, int sql_size, int sql_scale, String JavaDoc sql_type_string) {
231
232 // if (ob == null) {
233
// ob = NullObject.NULL_OBJ;
234
// }
235

236 // int sql_type = col_def.getSQLType();
237
// int sql_size = col_def.getSize();
238
// int sql_scale = col_def.getScale();
239
// String sql_type_string = col_def.getSQLTypeString();
240

241     // If the input object is a ByteLongObject and the output type is not a
242
// binary SQL type then we need to attempt to deserialize the object.
243
if (ob instanceof ByteLongObject) {
244       if ( sql_type != SQLTypes.JAVA_OBJECT &&
245            sql_type != SQLTypes.BLOB &&
246            sql_type != SQLTypes.BINARY &&
247            sql_type != SQLTypes.VARBINARY &&
248            sql_type != SQLTypes.LONGVARBINARY ) {
249         // Attempt to deserialize it
250
try {
251           ob = ObjectTranslator.deserialize((ByteLongObject) ob);
252         }
253         catch (Throwable JavaDoc e) {
254           // Couldn't deserialize so it must be a standard blob which means
255
// we are in error.
256
throw new Error JavaDoc("Can't cast a BLOB to " + sql_type_string);
257         }
258       }
259       else {
260         // This is a ByteLongObject that is being cast to a binary type so
261
// no further processing is necessary.
262
return ob;
263       }
264     }
265
266     // BlobRef can be BINARY, JAVA_OBJECT, VARBINARY or LONGVARBINARY
267
if (ob instanceof BlobRef) {
268       if (sql_type == SQLTypes.BINARY ||
269           sql_type == SQLTypes.BLOB ||
270           sql_type == SQLTypes.JAVA_OBJECT ||
271           sql_type == SQLTypes.VARBINARY ||
272           sql_type == SQLTypes.LONGVARBINARY) {
273         return ob;
274       }
275     }
276     
277     // ClobRef can be VARCHAR, LONGVARCHAR, or CLOB
278
if (ob instanceof ClobRef) {
279       if (sql_type == SQLTypes.VARCHAR ||
280           sql_type == SQLTypes.LONGVARCHAR ||
281           sql_type == SQLTypes.CLOB) {
282         return ob;
283       }
284     }
285     
286     // Cast from NULL
287
if (ob == null) {
288       switch (sql_type) {
289         case(SQLTypes.BIT):
290           // fall through
291
case(SQLTypes.TINYINT):
292           // fall through
293
case(SQLTypes.SMALLINT):
294           // fall through
295
case(SQLTypes.INTEGER):
296           // fall through
297
case(SQLTypes.BIGINT):
298           // fall through
299
case(SQLTypes.FLOAT):
300           // fall through
301
case(SQLTypes.REAL):
302           // fall through
303
case(SQLTypes.DOUBLE):
304           // fall through
305
case(SQLTypes.NUMERIC):
306           // fall through
307
case(SQLTypes.DECIMAL):
308           // fall through
309
case(SQLTypes.CHAR):
310           // fall through
311
case(SQLTypes.VARCHAR):
312           // fall through
313
case(SQLTypes.LONGVARCHAR):
314           // fall through
315
case(SQLTypes.CLOB):
316           // fall through
317
case(SQLTypes.DATE):
318           // fall through
319
case(SQLTypes.TIME):
320           // fall through
321
case(SQLTypes.TIMESTAMP):
322           // fall through
323
case(SQLTypes.NULL):
324           // fall through
325

326         case(SQLTypes.BINARY):
327           // fall through
328
case(SQLTypes.VARBINARY):
329           // fall through
330
case(SQLTypes.LONGVARBINARY):
331           // fall through
332
case(SQLTypes.BLOB):
333           // fall through
334

335
336         case(SQLTypes.JAVA_OBJECT):
337           // fall through
338

339         case(SQLTypes.BOOLEAN):
340           return null;
341         default:
342           throw new Error JavaDoc("Can't cast NULL to " + sql_type_string);
343       }
344     }
345
346     // Cast from a number
347
if (ob instanceof Number JavaDoc) {
348       Number JavaDoc n = (Number JavaDoc) ob;
349       switch (sql_type) {
350         case(SQLTypes.BIT):
351           return n.intValue() == 0 ? Boolean.FALSE : Boolean.TRUE;
352         case(SQLTypes.TINYINT):
353           // fall through
354
case(SQLTypes.SMALLINT):
355           // fall through
356
case(SQLTypes.INTEGER):
357 // return new BigDecimal(n.intValue());
358
return BigNumber.fromLong(n.intValue());
359         case(SQLTypes.BIGINT):
360 // return new BigDecimal(n.longValue());
361
return BigNumber.fromLong(n.longValue());
362         case(SQLTypes.FLOAT):
363           return BigNumber.fromString(Double.toString(n.doubleValue()));
364         case(SQLTypes.REAL):
365           return BigNumber.fromString(n.toString());
366         case(SQLTypes.DOUBLE):
367           return BigNumber.fromString(Double.toString(n.doubleValue()));
368         case(SQLTypes.NUMERIC):
369           // fall through
370
case(SQLTypes.DECIMAL):
371           return BigNumber.fromString(n.toString());
372         case(SQLTypes.CHAR):
373           return StringObject.fromString(paddedString(n.toString(), sql_size));
374         case(SQLTypes.VARCHAR):
375           return StringObject.fromString(n.toString());
376         case(SQLTypes.LONGVARCHAR):
377           return StringObject.fromString(n.toString());
378         case(SQLTypes.DATE):
379           return toDate(n.longValue());
380         case(SQLTypes.TIME):
381           return toDate(n.longValue());
382         case(SQLTypes.TIMESTAMP):
383           return toDate(n.longValue());
384         case(SQLTypes.BLOB):
385           // fall through
386
case(SQLTypes.BINARY):
387           // fall through
388
case(SQLTypes.VARBINARY):
389           // fall through
390
case(SQLTypes.LONGVARBINARY):
391           return new ByteLongObject(n.toString().getBytes());
392         case(SQLTypes.NULL):
393           return null;
394         case(SQLTypes.JAVA_OBJECT):
395           return toJavaObject(ob);
396         case(SQLTypes.BOOLEAN):
397           return n.intValue() == 0 ? Boolean.FALSE : Boolean.TRUE;
398         default:
399           throw new Error JavaDoc("Can't cast number to " + sql_type_string);
400       }
401     } // if (ob instanceof Number)
402

403     // Cast from a string
404
if (ob instanceof StringObject || ob instanceof String JavaDoc) {
405       String JavaDoc str = ob.toString();
406       switch (sql_type) {
407         case(SQLTypes.BIT):
408           return str.equalsIgnoreCase("true") ? Boolean.TRUE : Boolean.FALSE;
409         case(SQLTypes.TINYINT):
410           // fall through
411
case(SQLTypes.SMALLINT):
412           // fall through
413
case(SQLTypes.INTEGER):
414 // return new BigDecimal(toBigDecimal(str).intValue());
415
return BigNumber.fromLong(toBigNumber(str).intValue());
416         case(SQLTypes.BIGINT):
417 // return new BigDecimal(toBigDecimal(str).longValue());
418
return BigNumber.fromLong(toBigNumber(str).longValue());
419         case(SQLTypes.FLOAT):
420           return BigNumber.fromString(
421                         Double.toString(toBigNumber(str).doubleValue()));
422         case(SQLTypes.REAL):
423           return toBigNumber(str);
424         case(SQLTypes.DOUBLE):
425           return BigNumber.fromString(
426                         Double.toString(toBigNumber(str).doubleValue()));
427         case(SQLTypes.NUMERIC):
428           // fall through
429
case(SQLTypes.DECIMAL):
430           return toBigNumber(str);
431         case(SQLTypes.CHAR):
432           return StringObject.fromString(paddedString(str, sql_size));
433         case(SQLTypes.VARCHAR):
434           return StringObject.fromString(str);
435         case(SQLTypes.LONGVARCHAR):
436           return StringObject.fromString(str);
437         case(SQLTypes.DATE):
438           return toDate(str);
439         case(SQLTypes.TIME):
440           return toTime(str);
441         case(SQLTypes.TIMESTAMP):
442           return toTimeStamp(str);
443         case(SQLTypes.BLOB):
444           // fall through
445
case(SQLTypes.BINARY):
446           // fall through
447
case(SQLTypes.VARBINARY):
448           // fall through
449
case(SQLTypes.LONGVARBINARY):
450           return new ByteLongObject(str.getBytes());
451         case(SQLTypes.NULL):
452           return null;
453         case(SQLTypes.JAVA_OBJECT):
454           return toJavaObject(str);
455         case(SQLTypes.BOOLEAN):
456           return str.equalsIgnoreCase("true") ? Boolean.TRUE : Boolean.FALSE;
457         case(SQLTypes.CLOB):
458           return StringObject.fromString(str);
459         default:
460           throw new Error JavaDoc("Can't cast string to " + sql_type_string);
461       }
462     } // if (ob instanceof String)
463

464     // Cast from a boolean
465
if (ob instanceof Boolean JavaDoc) {
466       Boolean JavaDoc b = (Boolean JavaDoc) ob;
467       switch (sql_type) {
468         case(SQLTypes.BIT):
469           return b;
470         case(SQLTypes.TINYINT):
471           // fall through
472
case(SQLTypes.SMALLINT):
473           // fall through
474
case(SQLTypes.INTEGER):
475           // fall through
476
case(SQLTypes.BIGINT):
477           // fall through
478
case(SQLTypes.FLOAT):
479           // fall through
480
case(SQLTypes.REAL):
481           // fall through
482
case(SQLTypes.DOUBLE):
483           // fall through
484
case(SQLTypes.NUMERIC):
485           // fall through
486
case(SQLTypes.DECIMAL):
487           return b.equals(Boolean.TRUE) ? BD_ONE : BD_ZERO;
488         case(SQLTypes.CHAR):
489           return StringObject.fromString(paddedString(b.toString(), sql_size));
490         case(SQLTypes.VARCHAR):
491           return StringObject.fromString(b.toString());
492         case(SQLTypes.LONGVARCHAR):
493           return StringObject.fromString(b.toString());
494         case(SQLTypes.NULL):
495           return null;
496         case(SQLTypes.JAVA_OBJECT):
497           return toJavaObject(ob);
498         case(SQLTypes.BOOLEAN):
499           return b;
500         default:
501           throw new Error JavaDoc("Can't cast boolean to " + sql_type_string);
502       }
503     } // if (ob instanceof Boolean)
504

505     // Cast from a date
506
if (ob instanceof Date JavaDoc) {
507       Date JavaDoc d = (Date JavaDoc) ob;
508       switch (sql_type) {
509         case(SQLTypes.TINYINT):
510           // fall through
511
case(SQLTypes.SMALLINT):
512           // fall through
513
case(SQLTypes.INTEGER):
514           // fall through
515
case(SQLTypes.BIGINT):
516           // fall through
517
case(SQLTypes.FLOAT):
518           // fall through
519
case(SQLTypes.REAL):
520           // fall through
521
case(SQLTypes.DOUBLE):
522           // fall through
523
case(SQLTypes.NUMERIC):
524           // fall through
525
case(SQLTypes.DECIMAL):
526           return BigNumber.fromLong(d.getTime());
527         case(SQLTypes.CHAR):
528           return StringObject.fromString(paddedString(formatDateAsString(d), sql_size));
529         case(SQLTypes.VARCHAR):
530           return StringObject.fromString(formatDateAsString(d));
531         case(SQLTypes.LONGVARCHAR):
532           return StringObject.fromString(formatDateAsString(d));
533         case(SQLTypes.DATE):
534           return d;
535         case(SQLTypes.TIME):
536           return d;
537         case(SQLTypes.TIMESTAMP):
538           return d;
539         case(SQLTypes.NULL):
540           return null;
541         case(SQLTypes.JAVA_OBJECT):
542           return toJavaObject(ob);
543         default:
544           throw new Error JavaDoc("Can't cast date to " + sql_type_string);
545       }
546     } // if (ob instanceof Date)
547

548     // Some obscure types
549
if (ob instanceof byte[]) {
550       switch (sql_type) {
551         case(SQLTypes.BLOB):
552           // fall through
553
case(SQLTypes.BINARY):
554           // fall through
555
case(SQLTypes.VARBINARY):
556           // fall through
557
case(SQLTypes.LONGVARBINARY):
558           return new ByteLongObject((byte[]) ob);
559         default:
560           throw new Error JavaDoc("Can't cast byte[] to " + sql_type_string);
561       }
562     }
563
564     // Finally, the object can only be something that we can cast to a
565
// JAVA_OBJECT.
566
if (sql_type == SQLTypes.JAVA_OBJECT) {
567       return toJavaObject(ob);
568     }
569
570     throw new RuntimeException JavaDoc("Can't cast object " + ob.getClass() + " to " +
571                                sql_type_string);
572
573   }
574
575 }
576
Popular Tags