View Javadoc
1   /*
2    * This file is part of Waarp Project (named also Waarp or GG).
3    *
4    *  Copyright (c) 2019, Waarp SAS, and individual contributors by the @author
5    *  tags. See the COPYRIGHT.txt in the distribution for a full listing of
6    * individual contributors.
7    *
8    *  All Waarp Project is free software: you can redistribute it and/or
9    * modify it under the terms of the GNU General Public License as published by
10   * the Free Software Foundation, either version 3 of the License, or (at your
11   * option) any later version.
12   *
13   * Waarp is distributed in the hope that it will be useful, but WITHOUT ANY
14   * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
15   * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16   *
17   *  You should have received a copy of the GNU General Public License along with
18   * Waarp . If not, see <http://www.gnu.org/licenses/>.
19   */
20  package org.waarp.common.database.data;
21  
22  import org.waarp.common.database.exception.WaarpDatabaseSqlException;
23  import org.waarp.common.utility.WaarpStringUtils;
24  
25  import java.io.FileInputStream;
26  import java.io.FileNotFoundException;
27  import java.io.IOException;
28  import java.io.InputStream;
29  import java.io.InputStreamReader;
30  import java.io.Reader;
31  import java.sql.Date;
32  import java.sql.Timestamp;
33  import java.sql.Types;
34  import java.text.DateFormat;
35  import java.text.ParseException;
36  import java.text.SimpleDateFormat;
37  import java.util.TimeZone;
38  
39  /**
40   * Database Value to help getting and setting value from and to database
41   */
42  public class DbValue {
43    private static final String TYPE_UNKNOWN = "Type unknown: ";
44    /**
45     * Real value
46     */
47    private Object value;
48    /**
49     * Data Type
50     */
51    final int type;
52    /**
53     * Column name
54     */
55    private String column;
56  
57    public DbValue(final String value) {
58      setValue(value);
59      type = Types.VARCHAR;
60    }
61  
62    public DbValue(final String value, final boolean LONG) {
63      setValue(value);
64      type = Types.LONGVARCHAR;
65    }
66  
67    public DbValue(final boolean value) {
68      setValue(value);
69      type = Types.BIT;
70    }
71  
72    public DbValue(final byte value) {
73      setValue(value);
74      type = Types.TINYINT;
75    }
76  
77    public DbValue(final short value) {
78      setValue(value);
79      type = Types.SMALLINT;
80    }
81  
82    public DbValue(final int value) {
83      setValue(value);
84      type = Types.INTEGER;
85    }
86  
87    public DbValue(final long value) {
88      setValue(value);
89      type = Types.BIGINT;
90    }
91  
92    public DbValue(final float value) {
93      setValue(value);
94      type = Types.REAL;
95    }
96  
97    public DbValue(final double value) {
98      setValue(value);
99      type = Types.DOUBLE;
100   }
101 
102   public DbValue(final byte[] value) {
103     setValue(value);
104     type = Types.VARBINARY;
105   }
106 
107   public DbValue(final Date value) {
108     setValue(value);
109     type = Types.DATE;
110   }
111 
112   public DbValue(final Timestamp value) {
113     setValue(value);
114     type = Types.TIMESTAMP;
115   }
116 
117   public DbValue(final java.util.Date value) {
118     setValue(new Timestamp(value.getTime()));
119     type = Types.TIMESTAMP;
120   }
121 
122   public DbValue(final String value, final String name) {
123     setValue(value);
124     type = Types.VARCHAR;
125     setColumn(name);
126   }
127 
128   public DbValue(final String value, final String name,
129                  final boolean trueLongOrFalseKey) {
130     setValue(value);
131     if (trueLongOrFalseKey) {
132       type = Types.LONGVARCHAR;
133     } else {
134       type = Types.NVARCHAR;
135     }
136     setColumn(name);
137   }
138 
139   public DbValue(final boolean value, final String name) {
140     setValue(value);
141     type = Types.BIT;
142     setColumn(name);
143   }
144 
145   public DbValue(final byte value, final String name) {
146     setValue(value);
147     type = Types.TINYINT;
148     setColumn(name);
149   }
150 
151   public DbValue(final short value, final String name) {
152     setValue(value);
153     type = Types.SMALLINT;
154     setColumn(name);
155   }
156 
157   public DbValue(final int value, final String name) {
158     setValue(value);
159     type = Types.INTEGER;
160     setColumn(name);
161   }
162 
163   public DbValue(final long value, final String name) {
164     setValue(value);
165     type = Types.BIGINT;
166     setColumn(name);
167   }
168 
169   public DbValue(final float value, final String name) {
170     setValue(value);
171     type = Types.REAL;
172     setColumn(name);
173   }
174 
175   public DbValue(final double value, final String name) {
176     setValue(value);
177     type = Types.DOUBLE;
178     setColumn(name);
179   }
180 
181   public DbValue(final byte[] value, final String name) {
182     setValue(value);
183     type = Types.VARBINARY;
184     setColumn(name);
185   }
186 
187   public DbValue(final Date value, final String name) {
188     setValue(value);
189     type = Types.DATE;
190     setColumn(name);
191   }
192 
193   public DbValue(final Timestamp value, final String name) {
194     setValue(value);
195     type = Types.TIMESTAMP;
196     setColumn(name);
197   }
198 
199   public DbValue(final java.util.Date value, final String name) {
200     setValue(new Timestamp(value.getTime()));
201     type = Types.TIMESTAMP;
202     setColumn(name);
203   }
204 
205   public DbValue(final Reader value, final String name) {
206     setValue(value);
207     type = Types.CLOB;
208     setColumn(name);
209   }
210 
211   public DbValue(final InputStream value, final String name) {
212     setValue(value);
213     type = Types.BLOB;
214     setColumn(name);
215   }
216 
217   public final void setValue(final String value) {
218     this.value = value;
219   }
220 
221   public final void setValue(final boolean value) {
222     this.value = value;
223   }
224 
225   public final void setValue(final byte value) {
226     this.value = value;
227   }
228 
229   public final void setValue(final short value) {
230     this.value = value;
231   }
232 
233   public final void setValue(final int value) {
234     this.value = value;
235   }
236 
237   public final void setValue(final long value) {
238     this.value = value;
239   }
240 
241   public final void setValue(final float value) {
242     this.value = value;
243   }
244 
245   public final void setValue(final double value) {
246     this.value = value;
247   }
248 
249   public final void setValue(final byte[] value) {
250     this.value = value;
251   }
252 
253   public final void setValue(final Date value) {
254     this.value = value;
255   }
256 
257   public final void setValue(final Timestamp value) {
258     this.value = value;
259   }
260 
261   public final void setValue(final java.util.Date value) {
262     this.value = new Timestamp(value.getTime());
263   }
264 
265   public final void setValue(final Reader value) {
266     this.value = value;
267   }
268 
269   public final void setValue(final InputStream value) {
270     this.value = value;
271   }
272 
273   public final void setValue(final Object value) {
274     this.value = value;
275   }
276 
277   /**
278    * @return the type in full string format
279    */
280   public final String getType() {
281     switch (type) {
282       case Types.VARCHAR:
283         return "VARCHAR";
284       case Types.NVARCHAR:
285         return "NVARCHAR";
286       case Types.LONGVARCHAR:
287         return "LONGVARCHAR";
288       case Types.BIT:
289         return "BIT";
290       case Types.TINYINT:
291         return "TINYINT";
292       case Types.SMALLINT:
293         return "SMALLINT";
294       case Types.INTEGER:
295         return "INTEGER";
296       case Types.BIGINT:
297         return "BIGINT";
298       case Types.REAL:
299         return "REAL";
300       case Types.DOUBLE:
301         return "DOUBLE";
302       case Types.VARBINARY:
303         return "VARBINARY";
304       case Types.DATE:
305         return "DATE";
306       case Types.TIMESTAMP:
307         return "TIMESTAMP";
308       case Types.CLOB:
309         return "CLOB";
310       case Types.BLOB:
311         return "BLOB";
312       default:
313         return "UNKNOWN:" + type;
314     }
315   }
316 
317   public final Object getValue() throws IllegalAccessError {
318     switch (type) {
319       case Types.VARCHAR:
320       case Types.NVARCHAR:
321       case Types.LONGVARCHAR:
322       case Types.BIT:
323       case Types.TINYINT:
324       case Types.SMALLINT:
325       case Types.INTEGER:
326       case Types.BIGINT:
327       case Types.REAL:
328       case Types.DOUBLE:
329       case Types.VARBINARY:
330       case Types.DATE:
331       case Types.TIMESTAMP:
332       case Types.CLOB:
333       case Types.BLOB:
334         return value;
335       default:
336         throw new IllegalAccessError(TYPE_UNKNOWN + type);
337     }
338   }
339 
340   public final String getValueAsString() throws WaarpDatabaseSqlException {
341     switch (type) {
342       case Types.VARCHAR:
343       case Types.NVARCHAR:
344       case Types.LONGVARCHAR:
345         return (String) getValue();
346       case Types.BIT:
347         return ((Boolean) getValue()).toString();
348       case Types.TINYINT:
349         return ((Byte) getValue()).toString();
350       case Types.SMALLINT:
351         return ((Short) getValue()).toString();
352       case Types.INTEGER:
353         return ((Integer) getValue()).toString();
354       case Types.BIGINT:
355         return ((Long) getValue()).toString();
356       case Types.REAL:
357       case Types.DOUBLE:
358       case Types.DATE:
359       case Types.TIMESTAMP:
360         return getValue().toString();
361       case Types.VARBINARY:
362         return new String((byte[]) getValue(), WaarpStringUtils.UTF8);
363       case Types.CLOB:
364         return getClob();
365       case Types.BLOB:
366         return getBlob();
367       default:
368         throw new WaarpDatabaseSqlException(TYPE_UNKNOWN + type);
369     }
370   }
371 
372   private String getBlob() throws WaarpDatabaseSqlException {
373     final StringBuilder sBuilder = new StringBuilder();
374     final InputStream inputStream = (InputStream) getValue();
375     final byte[] cbuf = new byte[4096];
376     int len;
377     try {
378       len = inputStream.read(cbuf);
379       while (len > 0) {
380         sBuilder.append(new String(cbuf, 0, len));
381         len = inputStream.read(cbuf);
382       }
383     } catch (final IOException e) {
384       throw new WaarpDatabaseSqlException("Error while reading Blob as String",
385                                           e);
386     }
387     return sBuilder.toString();
388   }
389 
390   private String getClob() throws WaarpDatabaseSqlException {
391     final StringBuilder sBuilder = new StringBuilder();
392     final Reader reader = (Reader) getValue();
393     final char[] cbuf = new char[4096];
394     int len;
395     try {
396       len = reader.read(cbuf);
397       while (len > 0) {
398         sBuilder.append(cbuf, 0, len);
399         len = reader.read(cbuf);
400       }
401     } catch (final IOException e) {
402       throw new WaarpDatabaseSqlException("Error while reading Clob as String",
403                                           e);
404     }
405     return sBuilder.toString();
406   }
407 
408   public final void setValueFromString(final String svalue)
409       throws WaarpDatabaseSqlException {
410     switch (type) {
411       case Types.VARCHAR:
412       case Types.NVARCHAR:
413       case Types.LONGVARCHAR:
414         setValue(svalue);
415         break;
416       case Types.BIT:
417         setValue(Boolean.parseBoolean(svalue));
418         break;
419       case Types.TINYINT:
420         setValue(Byte.parseByte(svalue));
421         break;
422       case Types.SMALLINT:
423         setValue(Short.parseShort(svalue));
424         break;
425       case Types.INTEGER:
426         setValue(Integer.parseInt(svalue));
427         break;
428       case Types.BIGINT:
429         setValue(Long.parseLong(svalue));
430         break;
431       case Types.REAL:
432         setValue(Float.parseFloat(svalue));
433         break;
434       case Types.DOUBLE:
435         setValue(Double.parseDouble(svalue));
436         break;
437       case Types.VARBINARY:
438         setValue(svalue.getBytes(WaarpStringUtils.UTF8));
439         break;
440       case Types.DATE:
441         try {
442           final DateFormat format = WaarpStringUtils.getDateFormat();
443           setValue(format.parse(svalue));
444         } catch (final ParseException e) {
445           try {
446             final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
447             setValue(format.parse(svalue));
448           } catch (final ParseException e1) {
449             try {
450               setValue(DateFormat.getDateTimeInstance().parse(svalue));
451             } catch (final ParseException e2) {
452               throw new WaarpDatabaseSqlException("Error in Date: " + svalue,
453                                                   e);
454             }
455           }
456         }
457         break;
458       case Types.TIMESTAMP:
459         try {
460           final DateFormat format =
461               new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
462           format.setTimeZone(TimeZone.getTimeZone("GMT"));
463           setValue(new Timestamp(format.parse(svalue).getTime()));
464         } catch (final ParseException e) {
465           try {
466             final SimpleDateFormat format =
467                 new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
468             setValue(new Timestamp(format.parse(svalue).getTime()));
469           } catch (final ParseException e1) {
470             try {
471               setValue(new Timestamp(
472                   DateFormat.getDateTimeInstance().parse(svalue).getTime()));
473             } catch (final ParseException e2) {
474               throw new WaarpDatabaseSqlException(
475                   "Error in Timestamp: " + svalue, e);
476             }
477           }
478         }
479         break;
480       case Types.CLOB:
481         try {
482           setValue(new InputStreamReader(new FileInputStream(svalue),
483                                          WaarpStringUtils.UTF8));
484         } catch (final FileNotFoundException e) {
485           throw new WaarpDatabaseSqlException("Error in CLOB: " + svalue, e);
486         }
487         break;
488       case Types.BLOB:
489         try {
490           setValue(new FileInputStream(svalue));
491         } catch (final FileNotFoundException e) {
492           throw new WaarpDatabaseSqlException("Error in BLOB: " + svalue, e);
493         }
494         break;
495       default:
496         throw new WaarpDatabaseSqlException(TYPE_UNKNOWN + type);
497     }
498   }
499 
500   /**
501    * @return the column
502    */
503   public final String getColumn() {
504     return column;
505   }
506 
507   /**
508    * @param column the column to set
509    */
510   private void setColumn(final String column) {
511     this.column = column;
512   }
513 }