KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > versant > core > jdbc > sql > conv > TypeAsStringConverter


1
2 /*
3  * Copyright (c) 1998 - 2005 Versant Corporation
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  * Versant Corporation - initial API and implementation
11  */

12 package com.versant.core.jdbc.sql.conv;
13
14 import com.versant.core.jdbc.JdbcConverter;
15 import com.versant.core.jdbc.JdbcConverterFactory;
16 import com.versant.core.jdbc.JdbcTypeRegistry;
17 import com.versant.core.jdbc.metadata.JdbcColumn;
18 import com.versant.core.jdbc.metadata.JdbcTypes;
19
20 import java.sql.PreparedStatement JavaDoc;
21 import java.sql.SQLException JavaDoc;
22 import java.sql.ResultSet JavaDoc;
23 import java.lang.reflect.Constructor JavaDoc;
24 import java.lang.reflect.Method JavaDoc;
25
26 import javax.jdo.JDOFatalDataStoreException; //todo: appears only in throws-clause
27

28 import com.versant.core.common.BindingSupportImpl;
29
30 /**
31  * <p>This converter can convert any type to/from String. The type must have
32  * a constructor that accepts a String. If it has a method 'String
33  * toExternalString()' then this is used to convert it to a String. Otherwise
34  * its toString() method is used.</p>
35  */

36 public class TypeAsStringConverter implements JdbcConverter {
37
38     private Class JavaDoc type;
39     private Constructor JavaDoc constructor;
40     private Method JavaDoc toExternalString;
41     private JdbcConverter stringConverter;
42
43     /**
44      * This creates converters for different types.
45      */

46     public static class Factory extends NoArgJdbcConverterFactory {
47
48         /**
49          * Create a converter for col using props as parameters. Return null if
50          * no converter is required.
51          */

52         public JdbcConverter createJdbcConverter(JdbcColumn col, Object JavaDoc args,
53                 JdbcTypeRegistry jdbcTypeRegistry) {
54             Class JavaDoc type = col.javaType;
55             JdbcConverter stringConverter;
56             try {
57                 JdbcConverterFactory f = jdbcTypeRegistry.getJdbcConverterFactory(col.jdbcType);
58                 stringConverter = f.createJdbcConverter(col, args, jdbcTypeRegistry);
59             } catch (IllegalArgumentException JavaDoc e) {
60                 // no converter available
61
stringConverter = DummyStringConverter.INSTANCE;
62             }
63             if (stringConverter.getValueType() != String JavaDoc.class) {
64                 throw BindingSupportImpl.getInstance().illegalArgument("Invalid JDBC type: " +
65                     JdbcTypes.toString(col.jdbcType));
66             }
67             return new TypeAsStringConverter(type, stringConverter);
68         }
69
70     }
71
72     public TypeAsStringConverter(Class JavaDoc type, JdbcConverter stringConverter) {
73         this.type = type;
74         this.stringConverter = stringConverter;
75         try {
76             constructor = type.getConstructor(new Class JavaDoc[]{String JavaDoc.class});
77         } catch (NoSuchMethodException JavaDoc e) {
78             throw BindingSupportImpl.getInstance().runtime(type + " does not have a " +
79                 "constructor that accepts a String", e);
80         }
81         try {
82             toExternalString = type.getMethod("toExternalString", null);
83             if (toExternalString.getReturnType() != String JavaDoc.class) {
84                 throw BindingSupportImpl.getInstance().runtime(type + ".toExternalString() does not " +
85                     "return String");
86             }
87         } catch (NoSuchMethodException JavaDoc e) {
88             // no problem - we will use toString
89
}
90     }
91
92     /**
93      * Get the value of col from rs at position index.
94      */

95     public Object JavaDoc get(ResultSet JavaDoc rs, int index, JdbcColumn col)
96             throws SQLException JavaDoc, JDOFatalDataStoreException {
97         String JavaDoc s = (String JavaDoc)stringConverter.get(rs, index, col);
98         if (s == null) return null;
99         try {
100             return constructor.newInstance(new Object JavaDoc[]{s});
101         } catch (Throwable JavaDoc x) {
102             throw BindingSupportImpl.getInstance().fatalDatastore("Unable to create instance of " +
103                 type.getName() + " from '" + s + "': " + x, x);
104         }
105     }
106
107
108
109
110
111
112     /**
113      * Set parameter index on ps to value (for col).
114      */

115     public void set(PreparedStatement JavaDoc ps, int index, JdbcColumn col,
116             Object JavaDoc value) throws SQLException JavaDoc, JDOFatalDataStoreException {
117         stringConverter.set(ps, index, col, toString(value));
118     }
119
120     private String JavaDoc toString(Object JavaDoc value) {
121         String JavaDoc s;
122         if (value == null) {
123             s = null;
124         } else {
125             try {
126                 s = toExternalString == null
127                         ? value.toString()
128                         : (String JavaDoc)toExternalString.invoke(value, null);
129             } catch (Throwable JavaDoc x) {
130                 throw BindingSupportImpl.getInstance().fatalDatastore("Unable to convert instance of " +
131                     type.getName() + " using " +
132                     (toExternalString == null ? "toString()" : "toExternalString()") +
133                     ": " + x, x);
134             }
135         }
136         return s;
137     }
138
139     /**
140      * Get the type of our expected value objects (e.g. java.util.Locale
141      * for a converter for Locale's).
142      */

143     public Class JavaDoc getValueType() {
144         return type;
145     }
146
147     /**
148      * Is this converter for an Oracle style LOB column? Oracle LOBs require
149      * a hard coded a value into the insert/update statement instead of using
150      * a replaceable parameter and then select the value (if not null) and
151      * modify it.
152      */

153     public boolean isOracleStyleLOB() {
154         return stringConverter.isOracleStyleLOB();
155     }
156
157     /**
158      * This is only called if isOracleStyleLOB returns true. Get the String
159      * to be embedded in an SQL insert/update statement when the value for
160      * this column is not null (e.g. "empty_clob()");
161      */

162     public String JavaDoc getOracleStyleLOBNotNullString() {
163         return stringConverter.getOracleStyleLOBNotNullString();
164     }
165
166     /**
167      * Set parameter index on ps to value (for col). This special form is used
168      * when the value to be set is available as an int to avoid creating
169      * an wrapper instance.
170      *
171      * @throws java.sql.SQLException on SQL errors
172      * @throws javax.jdo.JDOFatalDataStoreException
173      * if value is invalid
174      */

175     public void set(PreparedStatement JavaDoc ps, int index, JdbcColumn col, int value)
176             throws SQLException JavaDoc, JDOFatalDataStoreException {
177         throw BindingSupportImpl.getInstance().fatalDatastore("set(..int) called");
178     }
179
180     /**
181      * This method is only called for converters that return true for
182      * isOracleStyleLOB. The LOB to be updated is at index in rs.
183      *
184      * @throws java.sql.SQLException on SQL errors
185      * @throws javax.jdo.JDOFatalDataStoreException
186      * if value is invalid
187      * @see #isOracleStyleLOB
188      */

189     public void set(ResultSet JavaDoc rs, int index, JdbcColumn col, Object JavaDoc value)
190             throws SQLException JavaDoc, JDOFatalDataStoreException {
191         stringConverter.set(rs, index, col, toString(value));
192     }
193
194 }
195
Popular Tags