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: RdbMappingBuilder.java 6673 2005-04-28 16:53:00Z benoitf $
023: * --------------------------------------------------------------------------
024: */package org.objectweb.jonas_ejb.lib;
025:
026: import java.util.Iterator;
027: import org.objectweb.jonas.common.Log;
028: import org.objectweb.jonas_ejb.deployment.api.BeanDesc;
029: import org.objectweb.jonas_ejb.deployment.api.DeploymentDescEjb2;
030: import org.objectweb.jonas_ejb.deployment.api.EjbRelationDesc;
031: import org.objectweb.jonas_ejb.deployment.api.EjbRelationshipRoleDesc;
032: import org.objectweb.jonas_ejb.deployment.api.EntityJdbcCmp2Desc;
033: import org.objectweb.jonas_ejb.deployment.api.FieldJdbcDesc;
034: import org.objectweb.jonas_lib.deployment.api.DeploymentDescException;
035: import org.objectweb.jorm.api.PException;
036: import org.objectweb.jorm.metainfo.api.Class;
037: import org.objectweb.jorm.metainfo.api.ClassProject;
038: import org.objectweb.jorm.metainfo.api.ClassRef;
039: import org.objectweb.jorm.metainfo.api.CompositeName;
040: import org.objectweb.jorm.metainfo.api.GenClassRef;
041: import org.objectweb.jorm.metainfo.api.Manager;
042: import org.objectweb.jorm.metainfo.api.NameDef;
043: import org.objectweb.jorm.metainfo.api.NameRef;
044: import org.objectweb.jorm.metainfo.api.PrimitiveElement;
045: import org.objectweb.jorm.metainfo.api.ScalarField;
046: import org.objectweb.jorm.metainfo.api.PrimitiveElementMapping;
047: import org.objectweb.jorm.metainfo.lib.JormManager;
048: import org.objectweb.jorm.metainfo.lib.MetaInfoPrinter;
049: import org.objectweb.jorm.type.api.PType;
050: import org.objectweb.jorm.mapper.rdb.metainfo.RdbMappingPrinter;
051: import org.objectweb.jorm.mapper.rdb.metainfo.RdbMappingFactory;
052: import org.objectweb.jorm.mapper.rdb.metainfo.RdbMapping;
053: import org.objectweb.jorm.mapper.rdb.metainfo.RdbClassMultiMapping;
054: import org.objectweb.jorm.mapper.rdb.metainfo.RdbTable;
055: import org.objectweb.jorm.mapper.rdb.metainfo.RdbGenClassMapping;
056: import org.objectweb.jorm.mapper.rdb.metainfo.RdbExternalTable;
057: import org.objectweb.jorm.mapper.rdb.metainfo.RdbJoin;
058: import org.objectweb.util.monolog.api.Logger;
059: import org.objectweb.util.monolog.api.BasicLevel;
060: import org.objectweb.util.monolog.wrapper.printwriter.PrintStreamImpl;
061:
062: /**
063: * Class to hold meta-information for Jorm
064: * @author Sebastien Chassande-Barrioz for INRIA : Initial developper
065: * @author Philippe Durieux
066: */
067: public class RdbMappingBuilder {
068:
069: /**
070: * Logger for tracing
071: */
072: private Logger logger = null;
073:
074: /**
075: * The JORM meta-information manager
076: */
077: private JormManager manager = null;
078:
079: /**
080: * JOnAS map Entity beans on relational Databases :
081: * The JORM mapper is "rdb".
082: * It could be a good idea to put all the mapping information in another Class
083: */
084: public static final String MAPPER_NAME = "rdb";
085:
086: /**
087: * Jorm need a project name to store the mapping information (Jorm Meta Information)
088: */
089: public static final String PROJECT_NAME = "jonas";
090:
091: /**
092: * MetaInfo printer (debug)
093: */
094: private PrintStreamImpl pstream;
095: private MetaInfoPrinter mip;
096:
097: /**
098: * Constructor
099: * @param dd Deployment Descriptor for the ejb-jar
100: * @param logger the Logger to be used for tracing.
101: * @throws DeploymentDescException Cannot build Jorm Meta Information
102: */
103: public RdbMappingBuilder(DeploymentDescEjb2 dd, Logger logger)
104: throws DeploymentDescException {
105: this .logger = Log.getLogger("org.objectweb.jonas_ejb.mijorm");
106: pstream = new PrintStreamImpl(this .logger);
107: mip = new MetaInfoPrinter();
108: mip.addMappingPrinter(new RdbMappingPrinter());
109:
110: // Init a Jorm manager mapped on Rdb. Rdb is the only mapping
111: // supported by JOnAS today.
112: manager = new JormManager();
113: manager.setLogger(logger);
114: manager.init();
115: manager.addMappingFactory("rdb", new RdbMappingFactory());
116:
117: try {
118: // Create the jorm meta information for entity beans CMP2
119: for (Iterator i = dd.getBeanDescIterator(); i.hasNext();) {
120: BeanDesc bd = (BeanDesc) i.next();
121: if (bd instanceof EntityJdbcCmp2Desc) {
122: createJormEntityMI((EntityJdbcCmp2Desc) bd);
123: }
124: }
125:
126: // Create the jorm meta information for Relations
127: for (Iterator i = dd.getEjbRelationDescIterator(); i
128: .hasNext();) {
129: EjbRelationDesc relation = (EjbRelationDesc) i.next();
130: createJormRelationMI(relation);
131: }
132: } catch (PException e) {
133: logger.log(BasicLevel.ERROR, "Jorm Exception raised: " + e);
134: throw new DeploymentDescException(e);
135: }
136: }
137:
138: /**
139: * @return the Jorm MetaInfo Manager
140: */
141: public Manager getJormMIManager() {
142: return manager;
143: }
144:
145: /**
146: * @return the Jorm Project Name
147: */
148: public static String getProjectName() {
149: return PROJECT_NAME;
150: }
151:
152: /**
153: * Creates the Jorm Meta Information for an entity bean (CMP2)
154: * @param bean the Bean Descriptor
155: * @throws PException Jorm Manager reported an exception
156: */
157: private void createJormEntityMI(EntityJdbcCmp2Desc bean)
158: throws PException {
159:
160: String asn = bean.getJormClassName();
161: if (logger.isLoggable(BasicLevel.DEBUG)) {
162: logger.log(BasicLevel.DEBUG,
163: "Create Jorm MI for the bean: " + asn);
164: }
165:
166: // --------------------------------------------------------------------
167: // create persistent class and add it to the list for Jorm Compiler
168: // --------------------------------------------------------------------
169: Class myejb = manager.createClass(asn);
170: bean.addToJormList(myejb);
171: ClassProject acp = myejb.createClassProject(PROJECT_NAME);
172: RdbMapping mapping = (RdbMapping) acp
173: .createMapping(MAPPER_NAME);
174: RdbClassMultiMapping classmapping = mapping
175: .createClassMultiMapping("to-table");
176: String tablename = bean.getJdbcTableName();
177: RdbTable mytable = classmapping.createRdbTable(tablename);
178:
179: // --------------------------------------------------------------------
180: // CMP fields
181: // --------------------------------------------------------------------
182: for (Iterator i = bean.getCmpFieldDescIterator(); i.hasNext();) {
183: FieldJdbcDesc fd = (FieldJdbcDesc) i.next();
184: String fieldname = fd.getName();
185: if (logger.isLoggable(BasicLevel.DEBUG)) {
186: logger.log(BasicLevel.DEBUG,
187: "Create PrimitiveElement for the CMP field: "
188: + fieldname);
189: }
190: PType pt = JormType.getPType(fd.getFieldType(), fd
191: .isPrimaryKey());
192: PrimitiveElement pe = myejb.createPrimitiveElement(
193: fieldname, pt, PType.NOSIZE, PType.NOSIZE);
194: mytable.createPrimitiveElementMapping(pe, fd
195: .getJdbcFieldName(), fd.getSqlType(), fd
196: .isPrimaryKey());
197: }
198:
199: // --------------------------------------------------------------------
200: // Primary Key
201: // --------------------------------------------------------------------
202: NameDef nds = myejb.createNameDef();
203: if (bean.hasSimplePkField()) {
204: // PK is a single field
205: nds.setFieldName(bean.getSimplePkField().getName());
206: } else {
207: // Define a Composite Name (name = PK Class Name) and a NameRef
208: // Sometimes, the CompositeName already exists, for example if 2 beans
209: // have the same PK Class.
210: boolean newcn = false;
211: CompositeName cn = manager.getCompositeName(bean
212: .getJormPKClassName());
213: if (cn == null) {
214: cn = manager.createCompositeName(bean
215: .getJormPKClassName());
216: bean.addToJormList(cn);
217: newcn = true;
218: }
219: // Use the CompositeName into the NameDef
220: NameRef nrs = nds.createNameRef(cn);
221: // fill the composite name with pk fields and link these fields to the class fields
222: for (Iterator it = bean.getCmpFieldDescIterator(); it
223: .hasNext();) {
224: FieldJdbcDesc fd = (FieldJdbcDesc) it.next();
225: if (fd.isPrimaryKey()) {
226: String fieldName = fd.getName();
227: if (newcn) {
228: cn.createCompositeNameField(fieldName, JormType
229: .getPType(fd.getFieldType(), fd
230: .isPrimaryKey()), PType.NOSIZE,
231: PType.NOSIZE);
232: }
233: nrs.addProjection(fieldName, fieldName);
234: }
235: }
236: }
237: classmapping.createIdentifierMapping(nds);
238:
239: mip.print("Jorm MI for " + asn + ": ", myejb, pstream);
240: mip.print("JORM MI Mapping for " + asn + ": ", classmapping,
241: pstream);
242: }
243:
244: /**
245: * Creates the Jorm Meta Information for a relation between CMP2 entity beans
246: * @param relation the Relation Descriptor
247: * @throws PException Jorm Manager reported an exception
248: */
249: private void createJormRelationMI(EjbRelationDesc relation)
250: throws PException {
251: if (logger.isLoggable(BasicLevel.DEBUG)) {
252: logger.log(BasicLevel.DEBUG,
253: "Create Jorm MI for the relation: "
254: + relation.getName());
255: }
256: EjbRelationshipRoleDesc role1 = relation.getRelationshipRole1();
257: EjbRelationshipRoleDesc role2 = relation.getRelationshipRole2();
258: // role1
259: if (role1.isTargetMultiple())
260: createJormRoleMIMulti(role1, role2);
261: else
262: createJormRoleMIOne(role1, role2);
263: // role2
264: if (role2.isTargetMultiple())
265: createJormRoleMIMulti(role2, role1);
266: else
267: createJormRoleMIOne(role2, role1);
268: }
269:
270: /**
271: * Creates the Jorm Meta Information for a relationship role (CMR field)
272: * when the target is mono.
273: * @param sRole source EjbRelationship Role Descriptor
274: * @param tRole target EjbRelationship Role Descriptor
275: * @throws PException Jorm Manager reported an exception
276: */
277: private void createJormRoleMIOne(EjbRelationshipRoleDesc sRole,
278: EjbRelationshipRoleDesc tRole) throws PException {
279:
280: if (logger.isLoggable(BasicLevel.DEBUG)) {
281: logger.log(BasicLevel.DEBUG, sRole.getName());
282: }
283:
284: // source bean in the relation
285: EntityJdbcCmp2Desc sEntity = (EntityJdbcCmp2Desc) sRole
286: .getSourceBean();
287: String sAsn = sEntity.getJormClassName();
288: Class sClass = manager.getClass(sAsn);
289:
290: // target bean in the relation.
291: EntityJdbcCmp2Desc tEntity = (EntityJdbcCmp2Desc) sRole
292: .getTargetBean();
293: String tAsn = tEntity.getJormClassName();
294: Class tClass = manager.getClass(tAsn);
295:
296: ClassProject cpro = sClass.getClassProject(PROJECT_NAME);
297: RdbMapping rdbmapping = (RdbMapping) cpro
298: .getMapping(MAPPER_NAME);
299: RdbClassMultiMapping classmapping = (RdbClassMultiMapping) rdbmapping
300: .getClassMapping();
301: RdbTable rdbtable = classmapping.getRdbTable();
302:
303: // There is always a cmr-field, sometimes added by JOnAS, because we
304: // only deal with bidirectional relations.
305: String sCmr = sRole.getCmrFieldName();
306:
307: // In case we have the same cmr field used in both roles, nothing to do
308: if (tClass == sClass && sClass.getTypedElement(sCmr) != null) {
309: if (logger.isLoggable(BasicLevel.DEBUG)) {
310: logger.log(BasicLevel.DEBUG,
311: "Nothing to do, same CMR field.");
312: }
313: return;
314: }
315:
316: // add Dependencies between beans (= same cluster of beans)
317: // avoids dropping tables at each loading of beans in the same cluster.
318: if (tClass != sClass) {
319: classmapping.addDependency(tClass.getFQName());
320: }
321:
322: // Mono-value cmr: create the Class Ref. and its NameDef
323: ClassRef cr = sClass.createClassRef(sCmr, tClass);
324: NameDef rndf = cr.createRefNameDef();
325:
326: if (sRole.hasJdbcMapping() || tClass == sClass) {
327: // source bean has a JDBC mapping for its CMR field.
328: // 1 <-> N case (N side), or 1 <-> 1 case (Jdbc side)
329: classmapping.createReferenceMapping(
330: "embedded-target-reference", rndf);
331: if (tClass != sClass) {
332: rdbtable.setColocated(true);
333: rdbtable.setColocatedMaster(true);
334: }
335: if (tEntity.hasSimplePkField()) {
336: // target bean has a Simple PK.
337: FieldJdbcDesc fd = (FieldJdbcDesc) tEntity
338: .getSimplePkField();
339: String cmrmappingname = sRole.getForeignKeyJdbcName(fd
340: .getJdbcFieldName());
341: PrimitiveElement pe = null;
342: String clafn = sCmr + "_" + fd.getName();
343: boolean peHasMapping = false;
344: if (cmrmappingname != null) {
345: //check if the CMR is mapper over a CMP
346: pe = getPrimitiveElementByColumn(classmapping,
347: cmrmappingname);
348: }
349: if (pe == null) {
350: //No CMP has been found ==> create an hidden field
351: pe = sClass.createHiddenField(clafn, JormType
352: .getPType(fd.getFieldType(), fd
353: .isPrimaryKey()), PType.NOSIZE,
354: PType.NOSIZE);
355: } else {
356: peHasMapping = true;
357: }
358: //Register the field into the namedef
359: rndf.setFieldName(pe.getName());
360: if (cmrmappingname != null) { // ???
361: if (!peHasMapping) {
362: rdbtable.createPrimitiveElementMapping(pe,
363: cmrmappingname, fd.getSqlType(), false);
364: }
365: } else if (tClass == sClass) {
366: // tClass == sClass : unidirectional cmr on same bean
367: cmrmappingname = tRole.getForeignKeyJdbcName(fd
368: .getJdbcFieldName());
369: PrimitiveElementMapping pem = classmapping
370: .getPrimitiveElementMapping(tRole
371: .getCmrFieldName()
372: + "_" + fd.getName());
373: classmapping.addPrimitiveElementMapping(clafn, pem);
374: }
375: if (logger.isLoggable(BasicLevel.DEBUG)) {
376: logger.log(BasicLevel.DEBUG, "CMR " + sCmr
377: + " is mapped over the field: " + clafn
378: + " / columname: " + cmrmappingname);
379: }
380: } else {
381: // target bean has a Composite PK.
382: NameRef cpk = rndf.createNameRef(tClass.getNameDef("")
383: .getNameRef().getCompositeName());
384: for (Iterator i = tEntity.getCmpFieldDescIterator(); i
385: .hasNext();) {
386: FieldJdbcDesc fd = (FieldJdbcDesc) i.next();
387: if (fd.isPrimaryKey()) {
388: String cmrmappingname = sRole
389: .getForeignKeyJdbcName(fd
390: .getJdbcFieldName());
391: PrimitiveElement pe = null;
392: String clafn = sCmr + "_" + fd.getName();
393: boolean peHasMapping = false;
394: if (cmrmappingname != null) {
395: //check if the CMR is mapper over a CMP
396: pe = getPrimitiveElementByColumn(
397: classmapping, cmrmappingname);
398: }
399: if (pe == null) {
400: //No CMP has been found ==> create an hidden field
401: pe = sClass.createHiddenField(clafn,
402: JormType.getPType(
403: fd.getFieldType(), fd
404: .isPrimaryKey()),
405: PType.NOSIZE, PType.NOSIZE);
406: } else {
407: peHasMapping = true;
408: }
409: cpk.addProjection(fd.getName(), pe.getName());
410: if (cmrmappingname != null) {
411: if (!peHasMapping) {
412: rdbtable.createPrimitiveElementMapping(
413: pe, cmrmappingname, fd
414: .getSqlType(), false);
415: }
416: } else if (tClass == sClass) {
417: // tClass == sClass : unidirectional cmr on same bean (???)
418: cmrmappingname = tRole
419: .getForeignKeyJdbcName(fd
420: .getJdbcFieldName());
421: PrimitiveElementMapping pem = classmapping
422: .getPrimitiveElementMapping(tRole
423: .getCmrFieldName()
424: + "_" + fd.getName());
425: classmapping.addPrimitiveElementMapping(
426: clafn, pem);
427: }
428: if (logger.isLoggable(BasicLevel.DEBUG)) {
429: logger.log(BasicLevel.DEBUG, "CMR " + sCmr
430: + " is mapped over the field: "
431: + clafn + " / columname: "
432: + cmrmappingname);
433: }
434: }
435: }
436: }
437: } else {
438: // The JDBC mapping for the source CMR field is done on the target bean.
439: // 1 <-> 1 case (non-jdbc side)
440: classmapping.createReferenceMapping("multi-table", rndf);
441: RdbExternalTable table2 = classmapping
442: .createRdbExternalTable(tEntity.getJdbcTableName());
443: table2.setColocated(true); // Table used by 2 beans => update before insert
444: table2.setColocatedMaster(false);
445: table2.setReadOnly(true);
446: RdbJoin joinTo2 = table2.createRdbJoin(sCmr);
447: if (logger.isLoggable(BasicLevel.DEBUG)) {
448: logger.log(BasicLevel.DEBUG, "CMR " + sCmr
449: + " is mapped over the external table: "
450: + tEntity.getJdbcTableName());
451: }
452: // source pk fields compose the join
453: if (sEntity.hasSimplePkField()) {
454: FieldJdbcDesc spk = (FieldJdbcDesc) sEntity
455: .getSimplePkField();
456: String cmrmappingname = tRole.getForeignKeyJdbcName(spk
457: .getJdbcFieldName());
458: joinTo2.addJoinColumnNames(spk.getJdbcFieldName(),
459: cmrmappingname);
460: if (logger.isLoggable(BasicLevel.DEBUG)) {
461: logger.log(BasicLevel.DEBUG, "CMR " + sCmr
462: + ": join: " + spk.getJdbcFieldName()
463: + " = " + cmrmappingname);
464: }
465: } else {
466: for (Iterator i = sEntity.getCmpFieldDescIterator(); i
467: .hasNext();) {
468: FieldJdbcDesc fd = (FieldJdbcDesc) i.next();
469: if (fd.isPrimaryKey()) {
470: String cmrmappingname = tRole
471: .getForeignKeyJdbcName(fd
472: .getJdbcFieldName());
473: joinTo2.addJoinColumnNames(fd
474: .getJdbcFieldName(), cmrmappingname);
475: if (logger.isLoggable(BasicLevel.DEBUG)) {
476: logger.log(BasicLevel.DEBUG, "CMR " + sCmr
477: + ": join: "
478: + fd.getJdbcFieldName() + " = "
479: + cmrmappingname);
480: }
481: }
482: }
483: }
484: // target pk fields compose the name def of reference
485: if (tEntity.hasSimplePkField()) {
486: FieldJdbcDesc tpk = (FieldJdbcDesc) tEntity
487: .getSimplePkField();
488: String clafn = sCmr + "_" + tpk.getName();
489: rndf.setFieldName(clafn);
490: ScalarField sf = sClass.createHiddenField(clafn,
491: JormType.getPType(tpk.getFieldType(), tpk
492: .isPrimaryKey()), PType.NOSIZE,
493: PType.NOSIZE);
494: table2.createPrimitiveElementMapping(sf, tpk
495: .getJdbcFieldName(), tpk.getSqlType(), false,
496: joinTo2);
497: if (logger.isLoggable(BasicLevel.DEBUG)) {
498: logger.log(BasicLevel.DEBUG, "CMR " + sCmr
499: + ": mapped over the field : " + clafn
500: + " column: " + tpk.getJdbcFieldName());
501: }
502: } else {
503: NameRef cpk = rndf.createNameRef(tClass.getNameDef("")
504: .getNameRef().getCompositeName());
505: for (Iterator i = tEntity.getCmpFieldDescIterator(); i
506: .hasNext();) {
507: FieldJdbcDesc fd = (FieldJdbcDesc) i.next();
508: if (fd.isPrimaryKey()) {
509: String clafn = sCmr + "_" + fd.getName();
510: ScalarField sf = sClass.createHiddenField(
511: clafn, JormType.getPType(fd
512: .getFieldType(), fd
513: .isPrimaryKey()), PType.NOSIZE,
514: PType.NOSIZE);
515: table2.createPrimitiveElementMapping(sf, fd
516: .getJdbcFieldName(), fd.getSqlType(),
517: false, joinTo2);
518: cpk.addProjection(fd.getName(), sf.getName());
519: if (logger.isLoggable(BasicLevel.DEBUG)) {
520: logger.log(BasicLevel.DEBUG, "CMR " + sCmr
521: + ": mapped over the field : "
522: + clafn + " column: "
523: + fd.getJdbcFieldName());
524: }
525: }
526: }
527: }
528: }
529: mip.print("JORM MI for " + sAsn + ": ", sClass, pstream);
530: mip.print("JORM MI Mapping for " + sAsn + ": ", classmapping,
531: pstream);
532: }
533:
534: /**
535: * Creates the Jorm Meta Information for a relationship role (Multivalued CMR field)
536: * @param sRole source EjbRelationship Role Descriptor
537: * @param tRole target EjbRelationship Role Descriptor
538: * @throws PException Jorm Manager reported an exception
539: */
540: private void createJormRoleMIMulti(EjbRelationshipRoleDesc sRole,
541: EjbRelationshipRoleDesc tRole) throws PException {
542:
543: if (logger.isLoggable(BasicLevel.DEBUG)) {
544: logger.log(BasicLevel.DEBUG, sRole.getName());
545: }
546:
547: // source bean in the relation
548: EntityJdbcCmp2Desc sEntity = (EntityJdbcCmp2Desc) sRole
549: .getSourceBean();
550: String sAsn = sEntity.getJormClassName();
551: Class sClass = manager.getClass(sAsn);
552:
553: // target bean in the relation.
554: EntityJdbcCmp2Desc tEntity = (EntityJdbcCmp2Desc) sRole
555: .getTargetBean();
556: String tAsn = tEntity.getJormClassName();
557: Class tClass = manager.getClass(tAsn);
558:
559: ClassProject cpro = sClass.getClassProject(PROJECT_NAME);
560: RdbMapping rdbmapping = (RdbMapping) cpro
561: .getMapping(MAPPER_NAME);
562: RdbClassMultiMapping classmapping = (RdbClassMultiMapping) rdbmapping
563: .getClassMapping();
564:
565: // There is always a cmr-field, sometimes added by JOnAS, because we
566: // only deal with bidirectional relations.
567: String sCmr = sRole.getCmrFieldName();
568:
569: // In case we have the same cmr field used in both roles, nothing to do
570: if (tClass == sClass && sClass.getTypedElement(sCmr) != null) {
571: if (logger.isLoggable(BasicLevel.DEBUG)) {
572: logger.log(BasicLevel.DEBUG,
573: "Nothing to do, same CMR field.");
574: }
575: return;
576: }
577:
578: // add Dependencies between beans (= same cluster of beans)
579: // avoids dropping tables at each loading of beans in the same cluster.
580: if (tClass != sClass) {
581: classmapping.addDependency(tClass.getFQName());
582: }
583:
584: // Multi-value cmr: create the gen class and its Reference NameDef.
585: GenClassRef gcr = sClass.createGenClassRef(sCmr, sRole
586: .getCmrFieldType().getName());
587: NameDef ndsg = gcr.createRefNameDef();
588:
589: RdbGenClassMapping gcm = null;
590: RdbTable tableGC = null;
591: if (sRole.isSourceMultiple()) {
592: if (logger.isLoggable(BasicLevel.DEBUG)) {
593: logger.log(BasicLevel.DEBUG,
594: "Create GenClassReference for the CMR field (Many-Many): "
595: + sCmr);
596: }
597: // M <-> N case
598: gcm = rdbmapping.createGenClassMapping(
599: "embedded-target-references", gcr);
600: // We need a jointure table in that case.
601: tableGC = gcm.createRdbTable(sRole.getRelation()
602: .getJdbcTableName());
603: if (sRole.isSlave()) {
604: tableGC.setReadOnly(true);
605: }
606: } else {
607: if (logger.isLoggable(BasicLevel.DEBUG)) {
608: logger.log(BasicLevel.DEBUG,
609: "Create GenClassReference for the CMR field (One-Many): "
610: + sCmr);
611: }
612: // 1 <-> N case (1 side) : store CMR on N side.
613: gcm = rdbmapping.createGenClassMapping(
614: "embedded-target-objects", gcr);
615: tableGC = gcm.createRdbTable(tEntity.getJdbcTableName());
616: tableGC.setReadOnly(true);
617: tableGC.setColocated(true);
618: }
619:
620: // How the current bean references the gen class
621: // = the identifier of the source class
622: // no mapping, because already done for the bean pk.
623: classmapping.createReferenceMapping(
624: "embedded-target-reference", ndsg);
625: if (sEntity.hasSimplePkField()) {
626: // source bean has a Simple PK.
627: FieldJdbcDesc fd = (FieldJdbcDesc) sEntity
628: .getSimplePkField();
629: ndsg.setFieldName(fd.getName());
630: } else {
631: // source bean has a Composite PK.
632: NameRef cpk = ndsg.createNameRef(sClass.getNameDef("")
633: .getNameRef().getCompositeName());
634: for (Iterator i = sEntity.getCmpFieldDescIterator(); i
635: .hasNext();) {
636: FieldJdbcDesc fd = (FieldJdbcDesc) i.next();
637: if (fd.isPrimaryKey()) {
638: // field names in the Composite are field names of the bean.
639: cpk.addProjection(fd.getName(), fd.getName());
640: }
641: }
642: }
643:
644: // How the gen class is identified (the gen class name)
645: // = the identifier of the source class
646: String fieldsuffix;
647: if (sClass == tClass) {
648: fieldsuffix = (sRole.isSlave() ? "2" : "1");
649: } else {
650: fieldsuffix = "";
651: }
652: NameDef ndid = gcr.createIdNameDef();
653: if (sEntity.hasSimplePkField()) {
654: // source bean has a Simple PK.
655: FieldJdbcDesc fd = (FieldJdbcDesc) sEntity
656: .getSimplePkField();
657: String clafn = sAsn + "_" + fd.getName() + fieldsuffix;
658: ndid.setFieldName(clafn);
659: ScalarField pe = gcr.createHiddenField(clafn, JormType
660: .getPType(fd.getFieldType(), fd.isPrimaryKey()),
661: PType.NOSIZE, PType.NOSIZE);
662:
663: String fkname = tRole.getForeignKeyJdbcName(fd
664: .getJdbcFieldName());
665: tableGC.createPrimitiveElementMapping(pe, fkname, fd
666: .getSqlType(), false);
667: if (logger.isLoggable(BasicLevel.DEBUG)) {
668: logger.log(BasicLevel.DEBUG,
669: "GC id is mapped over the field: " + clafn
670: + " / column:" + fkname);
671: }
672: } else {
673: // source bean has a Composite PK.
674: NameRef cpk = ndid.createNameRef(sClass.getNameDef("")
675: .getNameRef().getCompositeName());
676: for (Iterator i = sEntity.getCmpFieldDescIterator(); i
677: .hasNext();) {
678: FieldJdbcDesc fd = (FieldJdbcDesc) i.next();
679: if (fd.isPrimaryKey()) {
680: String clafn = sAsn + "_" + fd.getName()
681: + fieldsuffix;
682: ScalarField sf = gcr.createHiddenField(clafn,
683: JormType.getPType(fd.getFieldType(), fd
684: .isPrimaryKey()), PType.NOSIZE,
685: PType.NOSIZE);
686: cpk.addProjection(fd.getName(), sf.getName());
687: String fkname = tRole.getForeignKeyJdbcName(fd
688: .getJdbcFieldName());
689: tableGC.createPrimitiveElementMapping(sf, fkname,
690: fd.getSqlType(), false);
691: if (logger.isLoggable(BasicLevel.DEBUG)) {
692: logger
693: .log(BasicLevel.DEBUG,
694: "GC id is mapped over the field: "
695: + clafn + " / column:"
696: + fkname);
697: }
698: }
699: }
700: }
701: gcm.createIdentifierMapping(ndid);
702:
703: // How the referenced class is referenced from the gen class.
704: // Describes an Element of the GenClass.
705: // = pk of the target bean
706: if (sClass == tClass) {
707: fieldsuffix = (tRole.isSlave() ? "2" : "1");
708: } else {
709: fieldsuffix = "";
710: }
711: // Create the ClassRef and its NameDef.
712: NameDef ndr2 = gcr.createClassRef(tClass).createRefNameDef();
713: gcm.createReferenceMapping("embedded-target-object", ndr2);
714:
715: if (tEntity.hasSimplePkField()) {
716: // target bean has a Simple PK.
717: FieldJdbcDesc fd = (FieldJdbcDesc) tEntity
718: .getSimplePkField();
719: String fkname;
720: if (sRole.isSourceMultiple()) {
721: // M <-> N case
722: fkname = sRole.getForeignKeyJdbcName(fd
723: .getJdbcFieldName());
724: } else {
725: // 1 <-> N case
726: fkname = fd.getJdbcFieldName();
727: }
728: ScalarField pe = getPrimitiveElementByColumn(gcm, fkname);
729: if (pe == null) {
730: String clafn = tAsn + "_" + fd.getName() + fieldsuffix;
731: pe = gcr.createHiddenField(clafn, JormType.getPType(fd
732: .getFieldType(), fd.isPrimaryKey()),
733: PType.NOSIZE, PType.NOSIZE);
734: tableGC.createPrimitiveElementMapping(pe, fkname, fd
735: .getSqlType(), false);
736: }
737: ndr2.setFieldName(pe.getName());
738: if (logger.isLoggable(BasicLevel.DEBUG)) {
739: logger.log(BasicLevel.DEBUG,
740: "GC elem is mapped over the field: "
741: + pe.getName() + " / column:" + fkname);
742: }
743: } else {
744: // target Bean has a Composite PK.
745: NameRef cpk = ndr2.createNameRef(tClass.getNameDef("")
746: .getNameRef().getCompositeName());
747: for (Iterator i = tEntity.getCmpFieldDescIterator(); i
748: .hasNext();) {
749: FieldJdbcDesc fd = (FieldJdbcDesc) i.next();
750: if (fd.isPrimaryKey()) {
751: String fkname;
752: if (sRole.isSourceMultiple()) {
753: // M <-> N case
754: fkname = sRole.getForeignKeyJdbcName(fd
755: .getJdbcFieldName());
756: } else {
757: // 1 <-> N case
758: fkname = fd.getJdbcFieldName();
759: }
760: ScalarField pe = getPrimitiveElementByColumn(gcm,
761: fkname);
762: if (pe == null) {
763: String clafn = tAsn + "_" + fd.getName()
764: + fieldsuffix;
765: pe = gcr.createHiddenField(clafn, JormType
766: .getPType(fd.getFieldType(), fd
767: .isPrimaryKey()), PType.NOSIZE,
768: PType.NOSIZE);
769: tableGC.createPrimitiveElementMapping(pe,
770: fkname, fd.getSqlType(), false);
771: }
772: cpk.addProjection(fd.getName(), pe.getName());
773: if (logger.isLoggable(BasicLevel.DEBUG)) {
774: logger.log(BasicLevel.DEBUG,
775: "GC elem is mapped over the field: "
776: + pe.getName() + " / column:"
777: + fkname);
778: }
779: }
780: }
781: }
782: mip.print("JORM MI for " + sAsn + ": ", sClass, pstream);
783: mip.print("JORM MI Mapping for " + sAsn + ": ", classmapping,
784: pstream);
785: }
786:
787: private PrimitiveElement getPrimitiveElementByColumn(
788: RdbClassMultiMapping cm, String col) {
789: PrimitiveElementMapping pem = cm.getRdbTable()
790: .getPrimitiveElementMappingByCol(col);
791: if (pem == null) {
792: if (logger.isLoggable(BasicLevel.DEBUG)) {
793: logger.log(BasicLevel.DEBUG, "no " + col);
794: }
795: return null;
796: }
797: if (logger.isLoggable(BasicLevel.DEBUG)) {
798: logger.log(BasicLevel.DEBUG, "yes " + col);
799: }
800: return (PrimitiveElement) pem.getLinkedMO();
801: }
802:
803: private ScalarField getPrimitiveElementByColumn(
804: RdbGenClassMapping cm, String col) {
805: PrimitiveElementMapping pem = cm.getRdbTable()
806: .getPrimitiveElementMappingByCol(col);
807: if (pem == null) {
808: if (logger.isLoggable(BasicLevel.DEBUG)) {
809: logger.log(BasicLevel.DEBUG, "no " + col);
810: }
811: return null;
812: }
813: if (logger.isLoggable(BasicLevel.DEBUG)) {
814: logger.log(BasicLevel.DEBUG, "yes " + col);
815: }
816: return (ScalarField) pem.getLinkedMO();
817: }
818: }
|