001: /*
002: * sqlc 1
003: * SQL Compiler
004: * Copyright (C) 2003 Hammurapi Group
005: *
006: * This program is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2 of the License, or (at your option) any later version.
010: *
011: * This program is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: *
020: * URL: http://www.hammurapi.biz/products/sqlc/index.html
021: * e-Mail: support@hammurapi.biz
022: */
023: package biz.hammurapi.sql.metadata;
024:
025: import java.io.Serializable;
026: import java.lang.reflect.Method;
027: import java.sql.PreparedStatement;
028: import java.sql.ResultSet;
029: import java.util.Collection;
030: import java.util.HashMap;
031: import java.util.Iterator;
032: import java.util.LinkedList;
033: import java.util.Map;
034:
035: import org.apache.bcel.classfile.Utility;
036: import org.apache.bcel.generic.Type;
037:
038: import biz.hammurapi.codegen.GenerationException;
039:
040: public class ParameterDescriptor implements Serializable, DbParameter {
041: public static final String SET_OBJECT_SIGNATURE_WITH_TYPE = "void setObject(int,java.lang.Object,int)";
042: public static final String SET_OBJECT_SIGNATURE = "void setObject(int,java.lang.Object)";
043:
044: /**
045: * Comment for <code>serialVersionUID</code>
046: */
047: private static final long serialVersionUID = -7190026509141539596L;
048: private boolean isNullable;
049: private int dbType;
050: private String className;
051: private String javaType;
052: private String javaName;
053:
054: /**
055: *
056: */
057: public ParameterDescriptor() {
058:
059: // TODO Auto-generated constructor stub
060: }
061:
062: /**
063: *
064: */
065: public String getType() {
066: return isNullable() ? javaType : ParameterDescriptor
067: .toPrimitive(javaType);
068: }
069:
070: /**
071: *
072: * @return Object type. Same as getType() for object types, wrapper classes for primitives.
073: */
074: public String getObjectType() {
075: return javaType;
076: }
077:
078: /**
079: * @param isNullable The isNullable to set.
080: */
081: public void setNullable(boolean isNullable) {
082: this .isNullable = isNullable;
083: }
084:
085: /**
086: * @return Returns the isNullable.
087: */
088: public boolean isNullable() {
089: return isNullable;
090: }
091:
092: /**
093: * @param dbType The dbType to set.
094: */
095: public void setDbType(int dbType) {
096: this .dbType = dbType;
097: }
098:
099: /**
100: * @return Returns the dbType.
101: */
102: public int getDbType() {
103: return dbType;
104: }
105:
106: /**
107: * @param className The className to set.
108: */
109: public void setClassName(String className) {
110: this .className = className;
111: }
112:
113: /**
114: * @return Returns the className.
115: */
116: public String getClassName() {
117: return className;
118: }
119:
120: /**
121: * @param javaType The javaType to set.
122: */
123: public void setJavaType(String javaType) {
124: this .javaType = javaType;
125: }
126:
127: /**
128: * @param name The name to set.
129: */
130: public void setName(String name) {
131: this .javaName = name;
132: }
133:
134: /**
135: * @return Returns the name.
136: */
137: public String getName() {
138: return javaName;
139: }
140:
141: public String toParameterDefinition() {
142: return getType() + " " + getName();
143: }
144:
145: public Type getBcelType() {
146: return Type.getType(Utility.getSignature(getType()));
147: }
148:
149: private static Map primitivesMap = new HashMap();
150:
151: static {
152: primitivesMap.put("java.lang.Integer", "int");
153: primitivesMap.put("java.lang.Boolean", "boolean");
154: primitivesMap.put("java.lang.Byte", "byte");
155: primitivesMap.put("java.lang.Character", "char");
156: primitivesMap.put("java.lang.Double", "double");
157: primitivesMap.put("java.lang.Float", "float");
158: primitivesMap.put("java.lang.Long", "long");
159: primitivesMap.put("java.lang.Short", "short");
160: }
161:
162: public static String toPrimitive(String typeName) {
163: String ret = (String) primitivesMap.get(typeName);
164: return ret == null ? typeName : ret;
165: }
166:
167: public static boolean isPrimitive(String typeName) {
168: return primitivesMap.containsValue(typeName);
169: }
170:
171: public static boolean mapsToPrimitive(String typeName) {
172: return primitivesMap.containsKey(typeName);
173: }
174:
175: // public String getSetterName() throws GenerationException {
176: // return getSetterName(getType());
177: // }
178:
179: /**
180: * Finds appropriate setter in prepared statement
181: * @param typeName
182: * @return
183: * @throws GenerationException
184: */
185: public static String findSetterSignature(String typeName)
186: throws GenerationException {
187: if ("byte[]".equals(typeName)) {
188: return "void setBytes(int,byte[])";
189: } else if (typeName.endsWith("[]")) {
190: return SET_OBJECT_SIGNATURE;
191: } else {
192: Collection allSetters = new LinkedList();
193: for (int i = 0, mc = PreparedStatement.class.getMethods().length; i < mc; i++) {
194: Method m = PreparedStatement.class.getMethods()[i];
195: if (m.getParameterTypes().length == 2
196: && m.getParameterTypes()[0].equals(int.class)
197: && m.getName().startsWith("set")) {
198: allSetters.add(m);
199: }
200: }
201:
202: int idx = typeName.lastIndexOf('.');
203: String shortName = typeName.substring(idx + 1, idx + 2)
204: .toUpperCase()
205: + typeName.substring(idx + 2);
206:
207: // Name match
208: Iterator it = allSetters.iterator();
209: while (it.hasNext()) {
210: Method m = (Method) it.next();
211: if (m.getName().equals("set" + shortName)
212: && m.getParameterTypes()[1].getName().equals(
213: typeName)) {
214: return getSignature(m);
215: }
216: }
217:
218: try {
219: Method candidate = null;
220: Class type = loadClass(typeName);
221: // Parameter match
222: it = allSetters.iterator();
223: while (it.hasNext()) {
224: Method m = (Method) it.next();
225: if (m.getParameterTypes()[1].isAssignableFrom(type)) {
226: if (candidate == null
227: || candidate.getParameterTypes()[1]
228: .isAssignableFrom(m
229: .getParameterTypes()[1])) {
230: candidate = m;
231: }
232: }
233: }
234: if (candidate != null) {
235: return getSignature(candidate);
236: }
237: } catch (ClassNotFoundException e) {
238: throw new GenerationException("Class not found: "
239: + typeName, e);
240: }
241:
242: // setObject
243: if (!isPrimitive(typeName)) {
244: return SET_OBJECT_SIGNATURE;
245: }
246:
247: throw new GenerationException("Setter not found for "
248: + typeName);
249: }
250: }
251:
252: private static Map primitiveMap = new HashMap();
253:
254: static {
255: putPrimitive(boolean.class);
256: putPrimitive(byte.class);
257: putPrimitive(double.class);
258: putPrimitive(float.class);
259: putPrimitive(int.class);
260: putPrimitive(long.class);
261: putPrimitive(short.class);
262: putPrimitive(char.class);
263: putPrimitive(void.class);
264: }
265:
266: /**
267: *
268: */
269: private static void putPrimitive(Class clazz) {
270: primitiveMap.put(clazz.getName(), clazz);
271: }
272:
273: /**
274: * Finds appropriate setter in ResultSet
275: * @param typeName
276: * @return
277: * @throws GenerationException
278: */
279: public static String findGetterSignature(String typeName)
280: throws GenerationException {
281: if ("byte[]".equals(typeName)) {
282: return "byte[] getBytes(java.lang.String)";
283: } else if (typeName.endsWith("[]")) {
284: return "java.lang.Object getObject(java.lang.String)";
285: } else {
286:
287: Collection allGetters = new LinkedList();
288: Class theClass = ResultSet.class;
289: for (int i = 0, mc = theClass.getMethods().length; i < mc; i++) {
290: Method m = theClass.getMethods()[i];
291: if (m.getParameterTypes().length == 1
292: && m.getParameterTypes()[0]
293: .equals(String.class)
294: && m.getName().startsWith("get")) {
295: allGetters.add(m);
296: // System.out.println(getSignature(m));
297: }
298: }
299:
300: int idx = typeName.lastIndexOf('.');
301: String shortName = typeName.substring(idx + 1, idx + 2)
302: .toUpperCase()
303: + typeName.substring(idx + 2);
304:
305: // Name match
306: Iterator it = allGetters.iterator();
307: while (it.hasNext()) {
308: Method m = (Method) it.next();
309: if (m.getName().equals("get" + shortName)
310: && m.getReturnType().getName().equals(typeName)) {
311: return getSignature(m);
312: }
313: }
314:
315: try {
316: Method candidate = null;
317: Class type = loadClass(typeName);
318: // Return type match
319: Iterator iit = allGetters.iterator();
320: while (iit.hasNext()) {
321: Method m = (Method) iit.next();
322: if (m.getReturnType().isAssignableFrom(type)) {
323: if (candidate == null
324: || candidate.getReturnType()
325: .isAssignableFrom(
326: m.getReturnType())) {
327: candidate = m;
328: }
329: }
330: }
331: if (candidate != null) {
332: return getSignature(candidate);
333: }
334: } catch (ClassNotFoundException e) {
335: throw new GenerationException("Class not found: "
336: + typeName, e);
337: }
338:
339: // getObject
340: if (!isPrimitive(typeName)) {
341: return "java.lang.Object getObject(java.lang.String)";
342: }
343:
344: throw new GenerationException("Getter not found for "
345: + typeName);
346: }
347: }
348:
349: /**
350: * @param typeName
351: * @return
352: * @throws ClassNotFoundException
353: */
354: private static Class loadClass(String typeName)
355: throws ClassNotFoundException {
356: Class ret = (Class) primitiveMap.get(typeName);
357: return ret == null ? Class.forName(typeName) : ret;
358: }
359:
360: /**
361: * @param m
362: * @return
363: */
364: private static String getSignature(Method m) {
365: StringBuffer sb = new StringBuffer(m.getReturnType().getName());
366: sb.append(" ");
367: sb.append(m.getName());
368: sb.append("(");
369: for (int i = 0, j = m.getParameterTypes().length; i < j; i++) {
370: sb.append(m.getParameterTypes()[i].getName());
371: if (i != j - 1) {
372: sb.append(",");
373: }
374: }
375: sb.append(")");
376: return sb.toString();
377: }
378:
379: private String label;
380:
381: /**
382: * @return
383: */
384: public String getLabel() {
385: return label;
386: }
387:
388: public void setLabel(String label) {
389: this.label = label;
390: }
391: }
|