001: /**
002: * JOnAS: Java(TM) Open Application Server
003: * Copyright (C) 1999-2004 Bull S.A.
004: * Contact: jonas-team@objectweb.org
005: *
006: * This library 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.1 of the License, or any later version.
010: *
011: * This library 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
019: * USA
020: *
021: * --------------------------------------------------------------------------
022: * $Id: EntityCmp2Desc.java 7536 2005-10-19 22:08:18Z rhs $
023: * --------------------------------------------------------------------------
024: */package org.objectweb.jonas_ejb.deployment.api;
025:
026: import java.util.ArrayList;
027: import java.util.Collection;
028: import java.util.Iterator;
029: import java.lang.reflect.Field;
030: import java.lang.reflect.Method;
031: import org.objectweb.jonas_ejb.deployment.xml.AssemblyDescriptor;
032: import org.objectweb.jonas_ejb.deployment.xml.Entity;
033: import org.objectweb.jonas_ejb.deployment.xml.JonasEntity;
034: import org.objectweb.jonas_ejb.deployment.xml.Query;
035: import org.objectweb.jonas_ejb.deployment.ejbql.ParseException;
036: import org.objectweb.jonas_ejb.lib.BeanNaming;
037: import org.objectweb.jonas_lib.deployment.api.DeploymentDescException;
038: import org.objectweb.jonas_lib.deployment.xml.JLinkedList;
039: import org.objectweb.jorm.metainfo.api.MetaObject;
040:
041: /**
042: * Class to hold meta-information related to an entity of type CMP version 2.
043: * Created on Jun 24, 2002
044: * @author Christophe Ney [cney@batisseurs.com] : Initial developper
045: * @author Helene Joanin : code cleanup on May 2003
046: * @author Helene Joanin : complement for legacy first version on May 2003
047: */
048: public abstract class EntityCmp2Desc extends EntityCmpDesc {
049:
050: private ArrayList ejbRelationshipRoleDesc = new ArrayList();
051: private ArrayList jormMOList = new ArrayList();
052: protected String abstractSchemaName;
053:
054: private static final String JORM_PACKAGE = "jorm";
055:
056: private String jormClassName = null;
057: private String jormFQClassName = null;
058: private String jormAccessorClassName = null;
059: private String jormPKClassName = null;
060: private String jormPNameGetterClassName = null;
061: private String jormBinderClassName = null;
062:
063: protected String factoryClassName = null;
064: protected DeploymentDescEjb2 dc2d = null;
065:
066: /**
067: * constructor: called when the DeploymentDescriptor is read.
068: * Currently, called by both GenIC and createContainer.
069: */
070: public EntityCmp2Desc(ClassLoader classLoader, Entity ent,
071: AssemblyDescriptor asd, JonasEntity jEnt,
072: DeploymentDescEjb2 dc2d, JLinkedList jMDRList,
073: String fileName) throws DeploymentDescException {
074:
075: super (classLoader, ent, asd, jEnt, jMDRList, fileName);
076: this .dc2d = dc2d;
077:
078: // An abstract schema name is required
079: if ((ent.getAbstractSchemaName() == null)
080: || (ent.getAbstractSchemaName().length() == 0)) {
081: throw new DeploymentDescException(
082: "abstract-schema-name must be provided for bean "
083: + this .ejbName);
084: }
085: abstractSchemaName = ent.getAbstractSchemaName();
086:
087: // check if persistent fields exist
088: if (fieldDesc.isEmpty()) {
089: throw new DeploymentDescException(
090: "No cmp-field defined in bean " + this .ejbName);
091: }
092: // check if persistent fields map to getter and setter
093: for (Iterator i = fieldDesc.keySet().iterator(); i.hasNext();) {
094: String fn = (String) i.next();
095:
096: // field should not be defined
097: try {
098: Field f = ejbClass.getField(fn);
099: throw new DeploymentDescException(
100: "In cmp-version 2.x, field-name " + fn
101: + " should not be defined in bean "
102: + this .ejbName);
103: } catch (NoSuchFieldException e) {
104: // this is what we expect: nothing to do
105: } catch (SecurityException e) {
106: throw new DeploymentDescException(
107: "Cannot use java reflexion on "
108: + this .ejbClass.getName());
109: }
110:
111: try {
112: Method getter = null;
113: try {
114: getter = ejbClass.getMethod(FieldDesc
115: .getGetterName(fn), (Class[]) null);
116: ((FieldDesc) (fieldDesc.get(fn)))
117: .setFieldType(getter.getReturnType());
118: } catch (NoSuchMethodException e) {
119: throw new DeploymentDescException(
120: "Getter method not found for field-name "
121: + fn + " in bean " + this .ejbName,
122: e);
123: }
124: try {
125: ejbClass.getMethod(FieldDesc.getSetterName(fn),
126: new Class[] { getter.getReturnType() });
127: } catch (NoSuchMethodException e) {
128: throw new DeploymentDescException(
129: "Setter method not found for field-name "
130: + fn + " in bean " + this .ejbName,
131: e);
132: }
133: } catch (SecurityException e) {
134: throw new DeploymentDescException(
135: "Cannot use java reflexion on "
136: + this .ejbClass.getName());
137: }
138: }
139:
140: // isModifiedMethod deprecated for CMP 2.x
141: if (jEnt.getIsModifiedMethodName() != null) {
142: throw new DeploymentDescException(
143: "use of is-modified-method-name deprecated for CMP 2.x");
144: }
145:
146: // EJB-QL query
147: if (ent.getQueryList() != null) {
148: for (Iterator i = ent.getQueryList().iterator(); i
149: .hasNext();) {
150: Query q = (Query) i.next();
151: boolean foundMatch = false;
152: for (Iterator j = getMethodDescIterator(); j.hasNext();) {
153: MethodDesc methd = (MethodDesc) j.next();
154: String methName = q.getQueryMethod()
155: .getMethodName();
156: if (methd.matchPattern(null, methName, q
157: .getQueryMethod().getMethodParams()) != MethodDesc.APPLY_TO_NOTHING) {
158: foundMatch = true;
159: String query = q.getEjbQl();
160: if (!(methd instanceof MethodCmp2Desc)) {
161: throw new DeploymentDescException(
162: "ejbql query " + query
163: + " can't apply to method "
164: + methName + " in bean "
165: + ejbName);
166: }
167: try {
168: ((MethodCmp2Desc) methd).setQuery(query);
169: } catch (ParseException e) {
170: throw new DeploymentDescException(
171: "Invalid ejbql syntax for bean "
172: + ejbName + ":\n"
173: + e.getMessage(query));
174: }
175: if (q.getResultTypeMapping() != null) {
176: ((MethodCmp2Desc) methd)
177: .setResultTypeMapping(q
178: .getResultTypeMapping());
179: }
180: }
181: }
182: if (!foundMatch) {
183: throw new DeploymentDescException(
184: "invalid query-method definition for bean "
185: + ejbName
186: + "\nno such method as "
187: + MethodCmp2Desc
188: .queryMethodElementToString(q
189: .getQueryMethod())
190: + "\ncheck method name and method parameters");
191: }
192: }
193: }
194: // check that all finder/selecter methods but findByPrimaryKey have a non null query
195: for (Iterator j = getMethodDescIterator(); j.hasNext();) {
196: MethodDesc md = (MethodDesc) j.next();
197: if ((md.isFinder() || md.isEjbSelect())
198: && !md.isFindByPrimaryKey()) {
199: if (((MethodCmp2Desc) md).getQuery() == null) {
200: throw new DeploymentDescException(
201: "query not defined for method "
202: + MethodDesc.toString(md
203: .getMethod()) + " of bean"
204: + ejbName);
205:
206: }
207: }
208: }
209: if (isUndefinedPK()) {
210: FieldDesc fd = this .newFieldDescInstance();
211: fd.setName("JONASAUTOPKFIELD");
212: fd.setPrimaryKey(true);
213: fieldDesc.put("JONASAUTOPKFIELD", fd);
214: ((FieldDesc) (fieldDesc.get("JONASAUTOPKFIELD")))
215: .setFieldType(java.lang.Integer.class);
216: ((FieldJdbcDesc) (fieldDesc.get("JONASAUTOPKFIELD")))
217: .setJdbcFieldName(this
218: .getJdbcAutomaticPkFieldName());
219: }
220: }
221:
222: public DeploymentDescEjb2 getDeploymentDescEjb2() {
223: return dc2d;
224: }
225:
226: /**
227: * getter for field abstractSchemaName
228: */
229: public String getAbstractSchemaName() {
230: return abstractSchemaName;
231: }
232:
233: /**
234: * Get the Jorm Class name in JOrm Meta Info
235: * It is built from the Abstract Shema Name.
236: * @return the Jorm Class Name
237: */
238: private String getJormCName() {
239: if (jormClassName == null) {
240: jormClassName = BeanNaming
241: .firstToUpperCase(abstractSchemaName);
242: }
243: return jormClassName;
244: }
245:
246: /**
247: * Get the Jorm Fully Qualified Class name in JOrm Meta Info
248: * It is built from the Abstract Shema Name.
249: * @return the Jorm Class Name
250: */
251: public String getJormClassName() {
252: if (jormFQClassName == null) {
253: jormFQClassName = BeanNaming.getClassName(JORM_PACKAGE,
254: getJormCName());
255: }
256: return jormFQClassName;
257: }
258:
259: /**
260: * Get the list of Jorm MetaObjects to be generated
261: * @return a Collection of Jorm Meta Objects
262: */
263: public Collection getJormList() {
264: return jormMOList;
265: }
266:
267: /**
268: * add a Jorm MetaObject in the list of Jorm Meta Objects to generate
269: * @param jobject the Jorm MetaObject to add in the list
270: */
271: public void addToJormList(MetaObject jobject) {
272: jormMOList.add(jobject);
273: }
274:
275: /**
276: * Add meta-info of a relationship in which the bean is involved
277: */
278: public void addEjbRelationshipRoleDesc(EjbRelationshipRoleDesc ersrd) {
279: ejbRelationshipRoleDesc.add(ersrd);
280: }
281:
282: /**
283: * Get Iterator on meta-info for all relationships for which the bean
284: * is involved in.
285: */
286: public Iterator getEjbRelationshipRoleDescIterator() {
287: return ejbRelationshipRoleDesc.iterator();
288: }
289:
290: /**
291: * Get the EjbRelationshipRoleDesc corresponding to the given cmr field name.
292: * Return null if it doesn't exist.
293: */
294: public EjbRelationshipRoleDesc getEjbRelationshipRoleDesc(String cmr) {
295: for (Iterator i = ejbRelationshipRoleDesc.iterator(); i
296: .hasNext();) {
297: EjbRelationshipRoleDesc rsr = (EjbRelationshipRoleDesc) i
298: .next();
299: if (rsr.hasCmrField() && cmr.equals(rsr.getCmrFieldName())) {
300: return rsr;
301: }
302: }
303: return null;
304: }
305:
306: /**
307: * Factory method for MethodDesc.
308: * Only method with EJBQL queries are of type <code>MethodCmp2Desc</code>
309: */
310: protected MethodDesc newMethodDescInstance(Method meth,
311: Class classDef, int index) {
312: return new MethodCmp2Desc(this , meth, classDef, index);
313: }
314:
315: /**
316: * It retrieves the class name of the generated Jorm accessor interface.
317: * Used in the templates
318: * @return the fully qualified class name
319: */
320: public String getJormAccessorClassName() {
321: if (jormAccessorClassName == null) {
322: jormAccessorClassName = BeanNaming.getClassName(
323: JORM_PACKAGE, getJormCName() + "Accessor");
324: }
325: return jormAccessorClassName;
326: }
327:
328: /**
329: * It retrieves the class name of the generated Jorm binding.
330: * Used by the JormFactory
331: * @return the fully qualified class name
332: */
333: public String getJormBindingClassName() {
334: return BeanNaming.getClassName(JORM_PACKAGE, getJormCName()
335: + "Binding");
336: }
337:
338: /**
339: * Return the class name of the generated Jorm state class.
340: * @return the fully qualified class name
341: */
342: public String getJormStateClassName() {
343: return BeanNaming.getClassName(JORM_PACKAGE, getJormCName()
344: + "State");
345: }
346:
347: /**
348: * It retrieves the class name of the generated Jorm mapping.
349: * Used in the JContainer to instanciate the JEntityFactory
350: * @return the fully qualified class name
351: */
352: public String getFactoryClassName() {
353: return BeanNaming.getClassName(JORM_PACKAGE, "rdb."
354: + getJormCName() + "Mapping");
355: }
356:
357: /**
358: * Retrieves the Jorm PK Class, in case of composite PK
359: * Used by Jorm to generate PNameGetter and Binder classes
360: * @return the fully qualified class name
361: */
362: public String getJormPKClassName() {
363: if (!hasPrimaryKeyField() && jormPKClassName == null) {
364: jormPKClassName = BeanNaming.getClassName(JORM_PACKAGE,
365: BeanNaming.getBaseName(getPrimaryKeyClass()
366: .getName()));
367: }
368: return jormPKClassName;
369: }
370:
371: /**
372: * It retrieves the class name of the generated Jorm PNameGetter interface.
373: * Used in the templates to generate CMP2 classes.
374: * @return the fully qualified class name
375: */
376: public String getJormPNameGetterClassName() {
377: if (!hasPrimaryKeyField() && jormPNameGetterClassName == null) {
378: jormPNameGetterClassName = getJormPKClassName() + "PNG";
379: }
380: return jormPNameGetterClassName;
381: }
382:
383: /**
384: * It retrieves the class name of the generated Jorm Binder.
385: * Used in the Jorm Factory
386: * @return the fully qualified class name
387: */
388: public String getJormBinderClassName() {
389: if (jormBinderClassName == null) {
390: if (hasPrimaryKeyField()) {
391: jormBinderClassName = "org.objectweb.jorm.facility.naming.basidir.BasidBinder";
392: } else {
393: jormBinderClassName = getJormPKClassName() + "Binder";
394: }
395: }
396: return jormBinderClassName;
397: }
398:
399: /**
400: * @return true if at least one relation
401: */
402: public boolean needJormCoherenceHelper() {
403: return ejbRelationshipRoleDesc.iterator().hasNext();
404: }
405:
406: public String getJormCoherenceHelperItfName() {
407: return "JOnAS" + ejbName + "CoherenceHelper";
408: }
409:
410: public String getJormCoherenceHelperPackageName() {
411: return BeanNaming.getPackageName(getFullDerivedBeanName());
412: }
413:
414: public String getJormCoherenceHelperFQItfName() {
415: String pn = getJormCoherenceHelperPackageName();
416: return (pn != null && pn.length() > 0 ? pn + "."
417: + getJormCoherenceHelperItfName()
418: : getJormCoherenceHelperItfName());
419: }
420:
421: /**
422: * String representation of the object for test and debug purpose
423: * @return String representation of this object
424: */
425: public String toString() {
426: StringBuffer ret = new StringBuffer();
427: ret.append(super .toString());
428: for (Iterator i = ejbRelationshipRoleDesc.iterator(); i
429: .hasNext();) {
430: ret.append("\nejbRelationshipRoleDesc[]=" + i.next());
431: }
432: ret.append("\ngetAbstractSchemaName()="
433: + getAbstractSchemaName());
434: ret.append("\ngetJormAccessorClassName() = "
435: + getJormAccessorClassName());
436: ret.append("\nneedJormCoherenceHelper() = "
437: + needJormCoherenceHelper());
438: return ret.toString();
439: }
440:
441: }
|