KickJava   Java API By Example, From Geeks To Geeks.

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


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 import com.versant.core.common.Utils;
20
21 import java.sql.PreparedStatement JavaDoc;
22 import java.sql.SQLException JavaDoc;
23 import java.sql.ResultSet JavaDoc;
24 import java.lang.reflect.Constructor JavaDoc;
25 import java.lang.reflect.Method JavaDoc;
26
27 import javax.jdo.JDOFatalDataStoreException; //todo: appears only in throws-clause
28

29 import com.versant.core.common.BindingSupportImpl;
30 import com.versant.core.common.Utils;
31
32 /**
33  * This converter can convert any type to/from byte[]. The type must have
34  * a constructor that accepts a byte[] and a method called toBytes that
35  * will provide a byte[].
36  */

37 public class TypeAsBytesConverter implements JdbcConverter {
38
39     private Class JavaDoc type;
40     private Constructor JavaDoc constructor;
41     private Method JavaDoc toBytes;
42     private JdbcConverter bytesConverter;
43
44     /**
45      * This creates converters for different types.
46      */

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

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

91     public Object JavaDoc get(ResultSet JavaDoc rs, int index, JdbcColumn col)
92             throws SQLException JavaDoc, JDOFatalDataStoreException {
93         byte[] a = (byte[])bytesConverter.get(rs, index, col);
94         if (a == null) return null;
95         try {
96             return constructor.newInstance(new Object JavaDoc[]{a});
97         } catch (Throwable JavaDoc x) {
98             throw BindingSupportImpl.getInstance().fatalDatastore("Unable to create instance of " +
99                 type.getName() + " from " + Utils.toString(a) + ": " + x, x);
100         }
101     }
102
103
104
105
106
107     private byte[] toBytes(Object JavaDoc value) {
108         byte[] a;
109         if (value == null) {
110             a = null;
111         } else {
112             try {
113                 a = (byte[])toBytes.invoke(value, null);
114             } catch (Throwable JavaDoc x) {
115                 throw BindingSupportImpl.getInstance().fatalDatastore("Unable to convert instance of " +
116                     type.getName() + " '" + Utils.toString(value) + "' to byte[]: " + x, x);
117             }
118         }
119         return a;
120     }
121
122     /**
123      * Set parameter index on ps to value (for col).
124      */

125     public void set(PreparedStatement JavaDoc ps, int index, JdbcColumn col,
126             Object JavaDoc value) throws SQLException JavaDoc, JDOFatalDataStoreException {
127         bytesConverter.set(ps, index, col, toBytes(value));
128     }
129
130     /**
131      * Get the type of our expected value objects (e.g. java.util.Locale
132      * for a converter for Locale's).
133      */

134     public Class JavaDoc getValueType() {
135         return type;
136     }
137
138     /**
139      * Is this converter for an Oracle style LOB column? Oracle LOBs require
140      * a hard coded a value into the insert/update statement instead of using
141      * a replaceable parameter and then select the value (if not null) and
142      * modify it.
143      */

144     public boolean isOracleStyleLOB() {
145         return bytesConverter.isOracleStyleLOB();
146     }
147
148     /**
149      * This is only called if isOracleStyleLOB returns true. Get the String
150      * to be embedded in an SQL insert/update statement when the value for
151      * this column is not null (e.g. "empty_clob()");
152      */

153     public String JavaDoc getOracleStyleLOBNotNullString() {
154         return bytesConverter.getOracleStyleLOBNotNullString();
155     }
156
157     /**
158      * Set parameter index on ps to value (for col). This special form is used
159      * when the value to be set is available as an int to avoid creating
160      * an wrapper instance.
161      *
162      * @throws java.sql.SQLException on SQL errors
163      * @throws javax.jdo.JDOFatalDataStoreException
164      * if value is invalid
165      */

166     public void set(PreparedStatement JavaDoc ps, int index, JdbcColumn col, int value)
167             throws SQLException JavaDoc, JDOFatalDataStoreException {
168         throw BindingSupportImpl.getInstance().fatalDatastore("set(..int) called");
169     }
170
171     /**
172      * This method is only called for converters that return true for
173      * isOracleStyleLOB. The LOB to be updated is at index in rs.
174      *
175      * @throws java.sql.SQLException on SQL errors
176      * @throws javax.jdo.JDOFatalDataStoreException
177      * if value is invalid
178      * @see #isOracleStyleLOB
179      */

180     public void set(ResultSet JavaDoc rs, int index, JdbcColumn col, Object JavaDoc value)
181             throws SQLException JavaDoc, JDOFatalDataStoreException {
182         bytesConverter.set(rs, index, col, toBytes(value));
183     }
184
185 }
186
Popular Tags