001: /*
002:
003: Derby - Class org.apache.derby.iapi.types.JSQLType
004:
005: Licensed to the Apache Software Foundation (ASF) under one or more
006: contributor license agreements. See the NOTICE file distributed with
007: this work for additional information regarding copyright ownership.
008: The ASF licenses this file to you under the Apache License, Version 2.0
009: (the "License"); you may not use this file except in compliance with
010: the License. You may obtain a copy of the License at
011:
012: http://www.apache.org/licenses/LICENSE-2.0
013:
014: Unless required by applicable law or agreed to in writing, software
015: distributed under the License is distributed on an "AS IS" BASIS,
016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: See the License for the specific language governing permissions and
018: limitations under the License.
019:
020: */
021:
022: package org.apache.derby.iapi.types;
023:
024: import org.apache.derby.iapi.services.io.StoredFormatIds;
025: import org.apache.derby.iapi.services.io.Formatable;
026:
027: import java.io.IOException;
028: import java.io.ObjectInput;
029: import java.io.ObjectOutput;
030:
031: /**
032: * Type descriptor which wraps all 3 kinds of types supported in Cloudscape's
033: * JSQL language: SQL types, Java primitives, Java classes.
034: *
035: * This interface was originally added to support the serializing of WorkUnit
036: * signatures.
037: *
038: *
039: * @author Rick
040: */
041: public final class JSQLType implements Formatable {
042: ///////////////////////////////////////////////////////////////////////
043: //
044: // CONSTANTS
045: //
046: ///////////////////////////////////////////////////////////////////////
047:
048: public static final byte SQLTYPE = 0;
049: public static final byte JAVA_CLASS = 1;
050: public static final byte JAVA_PRIMITIVE = 2;
051:
052: public static final byte NOT_PRIMITIVE = -1;
053: public static final byte BOOLEAN = 0;
054: public static final byte CHAR = 1;
055: public static final byte BYTE = 2;
056: public static final byte SHORT = 3;
057: public static final byte INT = 4;
058: public static final byte LONG = 5;
059: public static final byte FLOAT = 6;
060: public static final byte DOUBLE = 7;
061:
062: // these two arrays are in the order of the primitive constants
063: static private final String[] wrapperClassNames = {
064: "java.lang.Boolean",
065: "java.lang.Integer", // we can't serialize char, so we convert it to int
066: "java.lang.Integer", "java.lang.Integer",
067: "java.lang.Integer", "java.lang.Long", "java.lang.Float",
068: "java.lang.Double" };
069:
070: static public final String[] primitiveNames = { "boolean", "char",
071: "byte", "short", "int", "long", "float", "double" };
072:
073: // here are the fields we serialize
074:
075: private byte category = JAVA_PRIMITIVE;
076: private DataTypeDescriptor sqlType;
077: private String javaClassName;
078: private byte primitiveKind;
079:
080: ///////////////////////////////////////////////////////////////////////
081: //
082: // CONSTRUCTORS
083: //
084: ///////////////////////////////////////////////////////////////////////
085:
086: /**
087: * Public 0-arg constructor for Formatable machinery.
088: */
089: public JSQLType() {
090: initialize(INT);
091: }
092:
093: /**
094: * Create a JSQLType from a SQL type.
095: *
096: * @param sqlType the SQL type to wrap
097: */
098: public JSQLType(DataTypeDescriptor sqlType) {
099: initialize(sqlType);
100: }
101:
102: /**
103: * Create a JSQLType given the name of a Java primitive or java class.
104: *
105: * @param javaName name of java primitive or class to wrap
106: */
107: public JSQLType(String javaName) {
108: byte primitiveID = getPrimitiveID(javaName);
109:
110: if (primitiveID != NOT_PRIMITIVE) {
111: initialize(primitiveID);
112: } else {
113: initialize(javaName);
114: }
115: }
116:
117: /**
118: * Create a JSQLType for a Java primitive.
119: *
120: * @param primitiveKind primitive to wrap
121: */
122: public JSQLType(byte primitiveKind) {
123: initialize(primitiveKind);
124: }
125:
126: /**
127: * What kind of type is this:
128: *
129: * @return one of the following: SQLTYPE, JAVA_PRIMITIVE, JAVA_CLASS
130: */
131: public byte getCategory() {
132: return category;
133: }
134:
135: /**
136: * If this is a JAVA_PRIMITIVE, what is its name?
137: *
138: * @return BOOLEAN, INT, ... if this is a JAVA_PRIMITIVE.
139: * NOT_PRIMITIVE if this is SQLTYPE or JAVA_CLASS.
140: */
141: public byte getPrimitiveKind() {
142: return primitiveKind;
143: }
144:
145: /**
146: * If this is a JAVA_CLASS, what is it's name?
147: *
148: * @return java class name if this is a JAVA_CLASS
149: * null if this is SQLTYPE or JAVA_PRIMITIVE
150: */
151: public String getJavaClassName() {
152: return javaClassName;
153: }
154:
155: /**
156: * What's our SQLTYPE?
157: *
158: * @return the DataTypeDescriptor corresponding to this type
159: *
160: */
161: public DataTypeDescriptor getSQLType() {
162: // might not be filled in if this is a JAVA_CLASS or JAVA_PRIMITIVE
163: if (sqlType == null) {
164: String className;
165:
166: if (category == JAVA_CLASS) {
167: className = javaClassName;
168: } else {
169: className = getWrapperClassName(primitiveKind);
170: }
171:
172: sqlType = DataTypeDescriptor
173: .getSQLDataTypeDescriptor(className);
174: }
175:
176: return sqlType;
177: }
178:
179: ///////////////////////////////////////////////////////////////////////
180: //
181: // Formatable BEHAVIOR
182: //
183: ///////////////////////////////////////////////////////////////////////
184:
185: /**
186: * Get the formatID which corresponds to this class.
187: *
188: * @return the formatID of this class
189: */
190: public int getTypeFormatId() {
191: return StoredFormatIds.JSQLTYPEIMPL_ID;
192: }
193:
194: /**
195: @see java.io.Externalizable#readExternal
196: @exception IOException thrown on error
197: @exception ClassNotFoundException thrown on error
198: */
199: public void readExternal(ObjectInput in) throws IOException,
200: ClassNotFoundException {
201: byte frozenCategory = in.readByte();
202:
203: switch (frozenCategory) {
204: case SQLTYPE:
205:
206: initialize((DataTypeDescriptor) in.readObject());
207: break;
208:
209: case JAVA_CLASS:
210:
211: initialize((String) in.readObject());
212: break;
213:
214: case JAVA_PRIMITIVE:
215:
216: initialize(in.readByte());
217: break;
218: }
219: }
220:
221: /**
222:
223: @exception IOException thrown on error
224: */
225: public void writeExternal(ObjectOutput out) throws IOException {
226: out.writeByte(category);
227:
228: switch (category) {
229: case SQLTYPE:
230:
231: out.writeObject(sqlType);
232: break;
233:
234: case JAVA_CLASS:
235:
236: out.writeObject(javaClassName);
237: break;
238:
239: case JAVA_PRIMITIVE:
240:
241: out.writeByte(primitiveKind);
242: break;
243:
244: }
245: }
246:
247: ///////////////////////////////////////////////////////////////////////
248: //
249: // INITIALIZATION MINIONS
250: //
251: ///////////////////////////////////////////////////////////////////////
252:
253: private void initialize(byte primitiveKind) {
254: initialize(JAVA_PRIMITIVE, null, null, primitiveKind);
255: }
256:
257: private void initialize(DataTypeDescriptor sqlType) {
258: initialize(SQLTYPE, sqlType, null, NOT_PRIMITIVE);
259: }
260:
261: private void initialize(String javaClassName) {
262: initialize(JAVA_CLASS, null, javaClassName, NOT_PRIMITIVE);
263: }
264:
265: /**
266: * Initialize this JSQL type. Minion of all constructors.
267: *
268: * @param category SQLTYPE, JAVA_CLASS, JAVA_PRIMITIVE
269: * @param sqlType corresponding SQL type if category=SQLTYPE
270: * @param javaClassName corresponding java class if category=JAVA_CLASS
271: * @param primitiveKind kind of primitive if category=JAVA_PRIMITIVE
272: */
273: private void initialize(byte category, DataTypeDescriptor sqlType,
274: String javaClassName, byte primitiveKind) {
275: this .category = category;
276: this .sqlType = sqlType;
277: this .javaClassName = javaClassName;
278: this .primitiveKind = primitiveKind;
279:
280: }
281:
282: ///////////////////////////////////////////////////////////////////////
283: //
284: // GENERAL MINIONS
285: //
286: ///////////////////////////////////////////////////////////////////////
287:
288: /**
289: * Gets the name of the java wrapper class corresponding to a primitive.
290: *
291: * @param primitive BOOLEAN, INT, ... etc.
292: *
293: * @return name of the java wrapper class corresponding to the primitive
294: */
295: private static String getWrapperClassName(byte primitive) {
296: if (primitive == NOT_PRIMITIVE) {
297: return "";
298: }
299: return wrapperClassNames[primitive];
300: }
301:
302: /**
303: * Translate the name of a java primitive to an id
304: *
305: * @param name name of primitive
306: *
307: * @return BOOLEAN, INT, ... etc if the name is that of a primitive.
308: * NOT_PRIMITIVE otherwise
309: */
310: private static byte getPrimitiveID(String name) {
311: for (byte ictr = BOOLEAN; ictr <= DOUBLE; ictr++) {
312: if (primitiveNames[ictr].equals(name)) {
313: return ictr;
314: }
315: }
316:
317: return NOT_PRIMITIVE;
318: }
319:
320: }
|