KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectstyle > cayenne > access > types > CharType


1 /* ====================================================================
2  *
3  * The ObjectStyle Group Software License, version 1.1
4  * ObjectStyle Group - http://objectstyle.org/
5  *
6  * Copyright (c) 2002-2005, Andrei (Andrus) Adamchik and individual authors
7  * of the software. All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  *
16  * 2. Redistributions in binary form must reproduce the above copyright
17  * notice, this list of conditions and the following disclaimer in
18  * the documentation and/or other materials provided with the
19  * distribution.
20  *
21  * 3. The end-user documentation included with the redistribution, if any,
22  * must include the following acknowlegement:
23  * "This product includes software developed by independent contributors
24  * and hosted on ObjectStyle Group web site (http://objectstyle.org/)."
25  * Alternately, this acknowlegement may appear in the software itself,
26  * if and wherever such third-party acknowlegements normally appear.
27  *
28  * 4. The names "ObjectStyle Group" and "Cayenne" must not be used to endorse
29  * or promote products derived from this software without prior written
30  * permission. For written permission, email
31  * "andrus at objectstyle dot org".
32  *
33  * 5. Products derived from this software may not be called "ObjectStyle"
34  * or "Cayenne", nor may "ObjectStyle" or "Cayenne" appear in their
35  * names without prior written permission.
36  *
37  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40  * DISCLAIMED. IN NO EVENT SHALL THE OBJECTSTYLE GROUP OR
41  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
44  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
46  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
47  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48  * SUCH DAMAGE.
49  * ====================================================================
50  *
51  * This software consists of voluntary contributions made by many
52  * individuals and hosted on ObjectStyle Group web site. For more
53  * information on the ObjectStyle Group, please see
54  * <http://objectstyle.org/>.
55  */

56
57 package org.objectstyle.cayenne.access.types;
58
59 import java.io.BufferedReader JavaDoc;
60 import java.io.IOException JavaDoc;
61 import java.io.Reader JavaDoc;
62 import java.io.StringWriter JavaDoc;
63 import java.sql.CallableStatement JavaDoc;
64 import java.sql.Clob JavaDoc;
65 import java.sql.PreparedStatement JavaDoc;
66 import java.sql.ResultSet JavaDoc;
67 import java.sql.SQLException JavaDoc;
68 import java.sql.Types JavaDoc;
69
70 import org.objectstyle.cayenne.CayenneException;
71 import org.objectstyle.cayenne.map.DbAttribute;
72 import org.objectstyle.cayenne.validation.BeanValidationFailure;
73 import org.objectstyle.cayenne.validation.ValidationResult;
74
75 /**
76  * Handles CHAR type for JDBC drivers that don't trim trailing spaces.
77  */

78 public class CharType extends AbstractType {
79
80     private static final int BUF_SIZE = 8 * 1024;
81
82     protected boolean trimmingChars;
83     protected boolean usingClobs;
84
85     public CharType(boolean trimingChars, boolean usingClobs) {
86         this.trimmingChars = trimingChars;
87         this.usingClobs = usingClobs;
88     }
89
90     /**
91      * Returns String as a class name.
92      */

93     public String JavaDoc getClassName() {
94         return String JavaDoc.class.getName();
95     }
96     
97     /**
98      * Validates string property.
99      *
100      * @since 1.1
101      */

102     public boolean validateProperty(
103         Object JavaDoc source,
104         String JavaDoc property,
105         Object JavaDoc value,
106         DbAttribute dbAttribute,
107         ValidationResult validationResult) {
108
109         if (!(value instanceof String JavaDoc)) {
110             return true;
111         }
112         
113         if(dbAttribute.getMaxLength() <= 0) {
114             return true;
115         }
116
117         String JavaDoc string = (String JavaDoc) value;
118         if (string.length() > dbAttribute.getMaxLength()) {
119             String JavaDoc message =
120                 "\""
121                     + property
122                     + "\" exceeds maximum allowed length ("
123                     + dbAttribute.getMaxLength()
124                     + " chars): "
125                     + string.length();
126             validationResult.addFailure(
127                 new BeanValidationFailure(source, property, message));
128
129             return false;
130         }
131
132         return true;
133     }
134     
135
136     /** Return trimmed string. */
137     public Object JavaDoc materializeObject(ResultSet JavaDoc rs, int index, int type) throws Exception JavaDoc {
138
139         String JavaDoc val = null;
140
141         // CLOB handling
142
if (type == Types.CLOB) {
143             val =
144                 (isUsingClobs())
145                     ? readClob(rs.getClob(index))
146                     : readCharStream(rs, index);
147         }
148         else {
149
150             val = rs.getString(index);
151
152             // trim CHAR type
153
if (val != null && type == Types.CHAR && isTrimmingChars()) {
154                 val = val.trim();
155             }
156         }
157
158         return val;
159     }
160
161     /** Return trimmed string. */
162     public Object JavaDoc materializeObject(CallableStatement JavaDoc cs, int index, int type)
163         throws Exception JavaDoc {
164
165         String JavaDoc val = null;
166
167         // CLOB handling
168
if (type == Types.CLOB) {
169             if (!isUsingClobs()) {
170                 throw new CayenneException("Character streams are not supported in stored procedure parameters.");
171             }
172
173             val = readClob(cs.getClob(index));
174         }
175         else {
176
177             val = cs.getString(index);
178
179             // trim CHAR type
180
if (val != null && type == Types.CHAR && isTrimmingChars()) {
181                 val = val.trim();
182             }
183         }
184
185         return val;
186     }
187
188     public void setJdbcObject(
189         PreparedStatement JavaDoc st,
190         Object JavaDoc val,
191         int pos,
192         int type,
193         int precision)
194         throws Exception JavaDoc {
195
196         // if this is a CLOB column, set the value as "String"
197
// instead. This should work with most drivers
198
if (type == Types.CLOB) {
199             st.setString(pos, (String JavaDoc) val);
200         }
201         else {
202             super.setJdbcObject(st, val, pos, type, precision);
203         }
204     }
205
206     protected String JavaDoc readClob(Clob JavaDoc clob) throws IOException JavaDoc, SQLException JavaDoc {
207         if (clob == null) {
208             return null;
209         }
210
211         // sanity check on size
212
if (clob.length() > Integer.MAX_VALUE) {
213             throw new IllegalArgumentException JavaDoc(
214                 "CLOB is too big to be read as String in memory: " + clob.length());
215         }
216
217         int size = (int) clob.length();
218         if (size == 0) {
219             return "";
220         }
221
222         int bufSize = (size < BUF_SIZE) ? size : BUF_SIZE;
223
224         Reader JavaDoc in = clob.getCharacterStream();
225         return (in != null)
226             ? readValueStream(new BufferedReader JavaDoc(in, bufSize), size, bufSize)
227             : null;
228     }
229
230     protected String JavaDoc readCharStream(ResultSet JavaDoc rs, int index)
231         throws IOException JavaDoc, SQLException JavaDoc {
232         Reader JavaDoc in = rs.getCharacterStream(index);
233
234         return (in != null) ? readValueStream(in, -1, BUF_SIZE) : null;
235     }
236
237     protected String JavaDoc readValueStream(Reader JavaDoc in, int streamSize, int bufSize)
238         throws IOException JavaDoc {
239         char[] buf = new char[bufSize];
240         int read;
241         StringWriter JavaDoc out =
242             (streamSize > 0) ? new StringWriter JavaDoc(streamSize) : new StringWriter JavaDoc();
243
244         try {
245             while ((read = in.read(buf, 0, bufSize)) >= 0) {
246                 out.write(buf, 0, read);
247             }
248             return out.toString();
249         }
250         finally {
251             in.close();
252         }
253     }
254
255     /**
256      * Returns <code>true</code> if 'materializeObject' method should trim
257      * trailing spaces from the CHAR columns. This addresses an issue with some
258      * JDBC drivers (e.g. Oracle), that return Strings for CHAR columsn padded
259      * with spaces.
260      */

261     public boolean isTrimmingChars() {
262         return trimmingChars;
263     }
264
265     public void setTrimmingChars(boolean trimingChars) {
266         this.trimmingChars = trimingChars;
267     }
268
269     public boolean isUsingClobs() {
270         return usingClobs;
271     }
272
273     public void setUsingClobs(boolean usingClobs) {
274         this.usingClobs = usingClobs;
275     }
276 }
Popular Tags