001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.ejb.plugins.cmp.jdbc;
023:
024: import java.lang.reflect.Method;
025: import java.sql.PreparedStatement;
026: import java.util.ArrayList;
027: import java.util.List;
028: import java.util.StringTokenizer;
029: import java.util.Collections;
030: import javax.ejb.EJBLocalObject;
031: import javax.ejb.EJBObject;
032:
033: import org.jboss.ejb.plugins.cmp.ejbql.Catalog;
034: import org.jboss.ejb.plugins.cmp.jdbc.bridge.JDBCFieldBridge;
035: import org.jboss.ejb.plugins.cmp.jdbc.bridge.JDBCAbstractEntityBridge;
036:
037: /**
038: * @author <a href="mailto:alex@jboss.org">Alex Loubyansky and others</a>
039: */
040: import org.jboss.logging.Logger;
041:
042: public final class QueryParameter {
043: public static List createParameters(int argNum,
044: JDBCFieldBridge field) {
045: List parameters;
046: JDBCType type = field.getJDBCType();
047: if (type instanceof JDBCTypeComplex) {
048: JDBCTypeComplexProperty[] props = ((JDBCTypeComplex) type)
049: .getProperties();
050: parameters = new ArrayList(props.length);
051: for (int i = 0; i < props.length; i++) {
052: QueryParameter param = new QueryParameter(argNum,
053: false, null, props[i], props[i].getJDBCType());
054: parameters.add(param);
055: }
056: } else {
057: QueryParameter param = new QueryParameter(argNum, type);
058: parameters = Collections.singletonList(param);
059: }
060: return parameters;
061: }
062:
063: public static List createParameters(int argNum,
064: JDBCAbstractEntityBridge entity) {
065: List parameters = new ArrayList();
066: JDBCFieldBridge[] pkFields = entity.getPrimaryKeyFields();
067: for (int i = 0; i < pkFields.length; ++i) {
068: JDBCFieldBridge pkField = pkFields[i];
069:
070: JDBCType type = pkField.getJDBCType();
071: if (type instanceof JDBCTypeComplex) {
072: JDBCTypeComplexProperty[] props = ((JDBCTypeComplex) type)
073: .getProperties();
074: for (int j = 0; j < props.length; j++) {
075: QueryParameter param = new QueryParameter(argNum,
076: false, pkField, props[j], props[j]
077: .getJDBCType());
078: parameters.add(param);
079: }
080: } else {
081: QueryParameter param = new QueryParameter(argNum,
082: false, pkField, null, type.getJDBCTypes()[0]);
083: param.type = type;
084: parameters.add(param);
085: }
086: }
087: return parameters;
088: }
089:
090: public static List createPrimaryKeyParameters(int argNum,
091: JDBCAbstractEntityBridge entity) {
092: List parameters = new ArrayList();
093: JDBCFieldBridge[] pkFields = entity.getPrimaryKeyFields();
094: for (int i = 0; i < pkFields.length; ++i) {
095: JDBCFieldBridge pkField = pkFields[i];
096:
097: JDBCType type = pkField.getJDBCType();
098: if (type instanceof JDBCTypeComplex) {
099: JDBCTypeComplexProperty[] props = ((JDBCTypeComplex) type)
100: .getProperties();
101: for (int j = 0; j < props.length; j++) {
102: QueryParameter param = new QueryParameter(argNum,
103: true, pkField, props[j], props[j]
104: .getJDBCType());
105: parameters.add(param);
106: }
107: } else {
108: QueryParameter param = new QueryParameter(argNum, true,
109: pkField, null, type.getJDBCTypes()[0]);
110: param.type = type;
111: parameters.add(param);
112: }
113: }
114: return parameters;
115: }
116:
117: private int argNum;
118: private final boolean isPrimaryKeyParameter;
119: private JDBCFieldBridge field;
120: private JDBCTypeComplexProperty property;
121: private String parameterString;
122:
123: private int jdbcType;
124: private JDBCType type;
125:
126: public QueryParameter(JDBCEntityPersistenceStore manager,
127: Method method, String parameterString) {
128:
129: // Method parameter will never be a primary key object, but always
130: // a complete entity.
131: this .isPrimaryKeyParameter = false;
132:
133: this .parameterString = parameterString;
134:
135: if (parameterString == null || parameterString.length() == 0) {
136: throw new IllegalArgumentException(
137: "Parameter string is empty");
138: }
139:
140: StringTokenizer tok = new StringTokenizer(parameterString, ".");
141:
142: // get the argument number
143: try {
144: argNum = Integer.parseInt(tok.nextToken());
145: } catch (NumberFormatException e) {
146: throw new IllegalArgumentException(
147: "The parameter must begin with a number");
148: }
149:
150: // get the argument type
151: if (argNum > method.getParameterTypes().length) {
152: throw new IllegalArgumentException(
153: "The parameter index is " + argNum
154: + " but the query method only has "
155: + method.getParameterTypes().length
156: + "parameter(s)");
157: }
158: Class argType = method.getParameterTypes()[argNum];
159:
160: // get the jdbc type object
161: JDBCType type;
162:
163: // if this is an entity parameter
164: if (EJBObject.class.isAssignableFrom(argType)
165: || EJBLocalObject.class.isAssignableFrom(argType)) {
166: // get the field name
167: // check more tokens
168: if (!tok.hasMoreTokens()) {
169: throw new IllegalArgumentException(
170: "When the parameter is an ejb a field name must be supplied.");
171: }
172: String fieldName = tok.nextToken();
173:
174: // get the field from the entity
175: field = getCMPField(manager, argType, fieldName);
176: if (!field.isPrimaryKeyMember()) {
177: throw new IllegalArgumentException(
178: "The specified field must be a primay key field");
179: }
180:
181: // get the jdbc type object
182: type = field.getJDBCType();
183: } else {
184: // get jdbc type from type manager
185: type = manager.getJDBCTypeFactory().getJDBCType(argType);
186: }
187:
188: if (type instanceof JDBCTypeSimple) {
189: if (tok.hasMoreTokens()) {
190: throw new IllegalArgumentException(
191: "Parameter is NOT a known "
192: + "dependent value class, so a properties cannot supplied.");
193: }
194: jdbcType = type.getJDBCTypes()[0];
195: this .type = type;
196: } else {
197: if (!tok.hasMoreTokens()) {
198: throw new IllegalArgumentException(
199: "Parmeter is a known "
200: + "dependent value class, so a property must be supplied");
201: }
202:
203: // build the propertyName
204: StringBuffer propertyName = new StringBuffer(
205: parameterString.length());
206: propertyName.append(tok.nextToken());
207: while (tok.hasMoreTokens()) {
208: propertyName.append('.').append(tok.nextToken());
209: }
210: property = ((JDBCTypeComplex) type)
211: .getProperty(propertyName.toString());
212: jdbcType = property.getJDBCType();
213: }
214: }
215:
216: public QueryParameter(int argNum, JDBCType type) {
217: this .argNum = argNum;
218: this .type = type;
219: this .jdbcType = type.getJDBCTypes()[0];
220: this .isPrimaryKeyParameter = false;
221: initToString();
222: }
223:
224: public QueryParameter(int argNum, boolean isPrimaryKeyParameter,
225: JDBCFieldBridge field, JDBCTypeComplexProperty property,
226: int jdbcType) {
227:
228: this .argNum = argNum;
229: this .isPrimaryKeyParameter = isPrimaryKeyParameter;
230: this .field = field;
231: this .property = property;
232: this .jdbcType = jdbcType;
233:
234: initToString();
235: }
236:
237: private void initToString() {
238: StringBuffer parameterBuf = new StringBuffer();
239: parameterBuf.append(argNum);
240: if (field != null) {
241: parameterBuf.append('.').append(field.getFieldName());
242: }
243: if (property != null) {
244: parameterBuf.append('.').append(property.getPropertyName());
245: }
246: parameterString = parameterBuf.toString();
247: }
248:
249: public void set(Logger log, PreparedStatement ps, int index,
250: Object[] args) throws Exception {
251: Object arg = args[argNum];
252: JDBCParameterSetter param;
253: if (field != null) {
254: if (!isPrimaryKeyParameter) {
255: if (arg instanceof EJBObject) {
256: arg = ((EJBObject) arg).getPrimaryKey();
257: } else if (arg instanceof EJBLocalObject) {
258: arg = ((EJBLocalObject) arg).getPrimaryKey();
259: } else {
260: throw new IllegalArgumentException(
261: "Expected an instanc of "
262: + "EJBObject or EJBLocalObject, but got an instance of "
263: + arg.getClass().getName());
264: }
265: }
266: arg = field.getPrimaryKeyValue(arg);
267:
268: // use mapper
269: final JDBCType jdbcType = field.getJDBCType();
270: arg = jdbcType.getColumnValue(0, arg);
271: param = jdbcType.getParameterSetter()[0];
272: } else if (property != null) {
273: arg = property.getColumnValue(arg);
274: param = property.getParameterSetter();
275: } else {
276: if (type != null) {
277: arg = type.getColumnValue(0, arg);
278: param = type.getParameterSetter()[0];
279: } else {
280: param = JDBCUtil.getParameterSetter(jdbcType,
281: arg == null ? null : arg.getClass());
282: }
283: }
284:
285: param.set(ps, index, jdbcType, arg, log);
286: //JDBCUtil.setParameter(log, ps, index, jdbcType, arg);
287: }
288:
289: private static JDBCFieldBridge getCMPField(
290: JDBCEntityPersistenceStore manager, Class intf,
291: String fieldName) {
292: Catalog catalog = manager.getCatalog();
293: JDBCAbstractEntityBridge entityBridge = (JDBCAbstractEntityBridge) catalog
294: .getEntityByInterface(intf);
295: if (entityBridge == null) {
296: throw new IllegalArgumentException(
297: "Entity not found in application "
298: + "catalog with interface="
299: + intf.getName());
300: }
301:
302: JDBCFieldBridge cmpField = (JDBCFieldBridge) entityBridge
303: .getFieldByName(fieldName);
304: if (cmpField == null) {
305: throw new IllegalArgumentException("cmpField not found:"
306: + " cmpFieldName=" + fieldName + " entityName="
307: + entityBridge.getEntityName());
308: }
309: return cmpField;
310: }
311:
312: public String toString() {
313: return parameterString;
314: }
315: }
|