KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > jonas_ejb > lib > RdbMappingBuilder


1 /**
2  * JOnAS: Java(TM) Open Application Server
3  * Copyright (C) 1999-2004 Bull S.A.
4  * Contact: jonas-team@objectweb.org
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19  * USA
20  *
21  * --------------------------------------------------------------------------
22  * $Id: RdbMappingBuilder.java,v 1.34 2005/04/28 16:53:00 benoitf Exp $
23  * --------------------------------------------------------------------------
24  */

25
26
27 package org.objectweb.jonas_ejb.lib;
28
29 import java.util.Iterator JavaDoc;
30 import org.objectweb.jonas.common.Log;
31 import org.objectweb.jonas_ejb.deployment.api.BeanDesc;
32 import org.objectweb.jonas_ejb.deployment.api.DeploymentDescEjb2;
33 import org.objectweb.jonas_ejb.deployment.api.EjbRelationDesc;
34 import org.objectweb.jonas_ejb.deployment.api.EjbRelationshipRoleDesc;
35 import org.objectweb.jonas_ejb.deployment.api.EntityJdbcCmp2Desc;
36 import org.objectweb.jonas_ejb.deployment.api.FieldJdbcDesc;
37 import org.objectweb.jonas_lib.deployment.api.DeploymentDescException;
38 import org.objectweb.jorm.api.PException;
39 import org.objectweb.jorm.metainfo.api.Class;
40 import org.objectweb.jorm.metainfo.api.ClassProject;
41 import org.objectweb.jorm.metainfo.api.ClassRef;
42 import org.objectweb.jorm.metainfo.api.CompositeName;
43 import org.objectweb.jorm.metainfo.api.GenClassRef;
44 import org.objectweb.jorm.metainfo.api.Manager;
45 import org.objectweb.jorm.metainfo.api.NameDef;
46 import org.objectweb.jorm.metainfo.api.NameRef;
47 import org.objectweb.jorm.metainfo.api.PrimitiveElement;
48 import org.objectweb.jorm.metainfo.api.ScalarField;
49 import org.objectweb.jorm.metainfo.api.PrimitiveElementMapping;
50 import org.objectweb.jorm.metainfo.lib.JormManager;
51 import org.objectweb.jorm.metainfo.lib.MetaInfoPrinter;
52 import org.objectweb.jorm.type.api.PType;
53 import org.objectweb.jorm.mapper.rdb.metainfo.RdbMappingPrinter;
54 import org.objectweb.jorm.mapper.rdb.metainfo.RdbMappingFactory;
55 import org.objectweb.jorm.mapper.rdb.metainfo.RdbMapping;
56 import org.objectweb.jorm.mapper.rdb.metainfo.RdbClassMultiMapping;
57 import org.objectweb.jorm.mapper.rdb.metainfo.RdbTable;
58 import org.objectweb.jorm.mapper.rdb.metainfo.RdbGenClassMapping;
59 import org.objectweb.jorm.mapper.rdb.metainfo.RdbExternalTable;
60 import org.objectweb.jorm.mapper.rdb.metainfo.RdbJoin;
61 import org.objectweb.util.monolog.api.Logger;
62 import org.objectweb.util.monolog.api.BasicLevel;
63 import org.objectweb.util.monolog.wrapper.printwriter.PrintStreamImpl;
64
65 /**
66  * Class to hold meta-information for Jorm
67  * @author Sebastien Chassande-Barrioz for INRIA : Initial developper
68  * @author Philippe Durieux
69  */

70 public class RdbMappingBuilder {
71
72     /**
73      * Logger for tracing
74      */

75     private Logger logger = null;
76
77
78     /**
79      * The JORM meta-information manager
80      */

81     private JormManager manager = null;
82
83     /**
84      * JOnAS map Entity beans on relational Databases :
85      * The JORM mapper is "rdb".
86      * It could be a good idea to put all the mapping information in another Class
87      */

88     public static final String JavaDoc MAPPER_NAME = "rdb";
89
90     /**
91      * Jorm need a project name to store the mapping information (Jorm Meta Information)
92      */

93     public static final String JavaDoc PROJECT_NAME = "jonas";
94
95     /**
96      * MetaInfo printer (debug)
97      */

98     private PrintStreamImpl pstream;
99     private MetaInfoPrinter mip;
100
101     /**
102      * Constructor
103      * @param dd Deployment Descriptor for the ejb-jar
104      * @param logger the Logger to be used for tracing.
105      * @throws DeploymentDescException Cannot build Jorm Meta Information
106      */

107     public RdbMappingBuilder(DeploymentDescEjb2 dd, Logger logger) throws DeploymentDescException {
108         this.logger = Log.getLogger("org.objectweb.jonas_ejb.mijorm");
109         pstream = new PrintStreamImpl(this.logger);
110         mip = new MetaInfoPrinter();
111         mip.addMappingPrinter(new RdbMappingPrinter());
112
113         // Init a Jorm manager mapped on Rdb. Rdb is the only mapping
114
// supported by JOnAS today.
115
manager = new JormManager();
116         manager.setLogger(logger);
117         manager.init();
118         manager.addMappingFactory("rdb", new RdbMappingFactory());
119
120         try {
121             // Create the jorm meta information for entity beans CMP2
122
for (Iterator JavaDoc i = dd.getBeanDescIterator(); i.hasNext(); ) {
123                 BeanDesc bd = (BeanDesc) i.next();
124                 if (bd instanceof EntityJdbcCmp2Desc) {
125                     createJormEntityMI((EntityJdbcCmp2Desc) bd);
126                 }
127             }
128
129             // Create the jorm meta information for Relations
130
for (Iterator JavaDoc i = dd.getEjbRelationDescIterator(); i.hasNext(); ) {
131                 EjbRelationDesc relation = (EjbRelationDesc) i.next();
132                 createJormRelationMI(relation);
133             }
134         } catch (PException e) {
135             logger.log(BasicLevel.ERROR, "Jorm Exception raised: " + e);
136             throw new DeploymentDescException(e);
137         }
138     }
139
140     /**
141      * @return the Jorm MetaInfo Manager
142      */

143     public Manager getJormMIManager() {
144         return manager;
145     }
146
147     /**
148      * @return the Jorm Project Name
149      */

150     public static String JavaDoc getProjectName() {
151         return PROJECT_NAME;
152     }
153
154     /**
155      * Creates the Jorm Meta Information for an entity bean (CMP2)
156      * @param bean the Bean Descriptor
157      * @throws PException Jorm Manager reported an exception
158      */

159     private void createJormEntityMI(EntityJdbcCmp2Desc bean) throws PException {
160
161         String JavaDoc asn = bean.getJormClassName();
162         if (logger.isLoggable(BasicLevel.DEBUG)) {
163             logger.log(BasicLevel.DEBUG, "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 JavaDoc myejb = manager.createClass(asn);
170         bean.addToJormList(myejb);
171         ClassProject acp = myejb.createClassProject(PROJECT_NAME);
172         RdbMapping mapping = (RdbMapping) acp.createMapping(MAPPER_NAME);
173         RdbClassMultiMapping classmapping = mapping.createClassMultiMapping("to-table");
174         String JavaDoc tablename = bean.getJdbcTableName();
175         RdbTable mytable = classmapping.createRdbTable(tablename);
176
177         // --------------------------------------------------------------------
178
// CMP fields
179
// --------------------------------------------------------------------
180
for (Iterator JavaDoc i = bean.getCmpFieldDescIterator(); i.hasNext();) {
181             FieldJdbcDesc fd = (FieldJdbcDesc) i.next();
182             String JavaDoc fieldname = fd.getName();
183             if (logger.isLoggable(BasicLevel.DEBUG)) {
184                 logger.log(BasicLevel.DEBUG, "Create PrimitiveElement for the CMP field: " + fieldname);
185             }
186             PType pt = JormType.getPType(fd.getFieldType(), fd.isPrimaryKey());
187             PrimitiveElement pe = myejb.createPrimitiveElement(fieldname, pt, PType.NOSIZE, PType.NOSIZE);
188             mytable.createPrimitiveElementMapping(pe, fd.getJdbcFieldName(), fd.getSqlType(), fd.isPrimaryKey());
189         }
190
191         // --------------------------------------------------------------------
192
// Primary Key
193
// --------------------------------------------------------------------
194
NameDef nds = myejb.createNameDef();
195         if (bean.hasSimplePkField()) {
196             // PK is a single field
197
nds.setFieldName(bean.getSimplePkField().getName());
198         } else {
199             // Define a Composite Name (name = PK Class Name) and a NameRef
200
// Sometimes, the CompositeName already exists, for example if 2 beans
201
// have the same PK Class.
202
boolean newcn = false;
203             CompositeName cn = manager.getCompositeName(bean.getJormPKClassName());
204             if (cn == null) {
205                 cn = manager.createCompositeName(bean.getJormPKClassName());
206                 bean.addToJormList(cn);
207                 newcn = true;
208             }
209             // Use the CompositeName into the NameDef
210
NameRef nrs = nds.createNameRef(cn);
211             // fill the composite name with pk fields and link these fields to the class fields
212
for (Iterator JavaDoc it = bean.getCmpFieldDescIterator(); it.hasNext();) {
213                 FieldJdbcDesc fd = (FieldJdbcDesc) it.next();
214                 if (fd.isPrimaryKey()) {
215                     String JavaDoc fieldName = fd.getName();
216                     if (newcn) {
217                         cn.createCompositeNameField(fieldName, JormType.getPType(fd.getFieldType(), fd.isPrimaryKey()),
218                                                     PType.NOSIZE, PType.NOSIZE);
219                     }
220                     nrs.addProjection(fieldName, fieldName);
221                 }
222             }
223         }
224         classmapping.createIdentifierMapping(nds);
225
226         mip.print("Jorm MI for " + asn + ": ", myejb, pstream);
227         mip.print("JORM MI Mapping for " + asn + ": ", classmapping, pstream);
228     }
229
230     /**
231      * Creates the Jorm Meta Information for a relation between CMP2 entity beans
232      * @param relation the Relation Descriptor
233      * @throws PException Jorm Manager reported an exception
234      */

235     private void createJormRelationMI(EjbRelationDesc relation) throws PException {
236         if (logger.isLoggable(BasicLevel.DEBUG)) {
237             logger.log(BasicLevel.DEBUG, "Create Jorm MI for the relation: " + relation.getName());
238         }
239         EjbRelationshipRoleDesc role1 = relation.getRelationshipRole1();
240         EjbRelationshipRoleDesc role2 = relation.getRelationshipRole2();
241         // role1
242
if (role1.isTargetMultiple())
243             createJormRoleMIMulti(role1, role2);
244         else
245             createJormRoleMIOne(role1, role2);
246         // role2
247
if (role2.isTargetMultiple())
248             createJormRoleMIMulti(role2, role1);
249         else
250             createJormRoleMIOne(role2, role1);
251     }
252
253     /**
254      * Creates the Jorm Meta Information for a relationship role (CMR field)
255      * when the target is mono.
256      * @param sRole source EjbRelationship Role Descriptor
257      * @param tRole target EjbRelationship Role Descriptor
258      * @throws PException Jorm Manager reported an exception
259      */

260     private void createJormRoleMIOne(EjbRelationshipRoleDesc sRole, EjbRelationshipRoleDesc tRole)
261         throws PException {
262
263         if (logger.isLoggable(BasicLevel.DEBUG)) {
264             logger.log(BasicLevel.DEBUG, sRole.getName());
265         }
266
267         // source bean in the relation
268
EntityJdbcCmp2Desc sEntity = (EntityJdbcCmp2Desc) sRole.getSourceBean();
269         String JavaDoc sAsn = sEntity.getJormClassName();
270         Class JavaDoc sClass = manager.getClass(sAsn);
271
272         // target bean in the relation.
273
EntityJdbcCmp2Desc tEntity = (EntityJdbcCmp2Desc) sRole.getTargetBean();
274         String JavaDoc tAsn = tEntity.getJormClassName();
275         Class JavaDoc tClass = manager.getClass(tAsn);
276
277         ClassProject cpro = sClass.getClassProject(PROJECT_NAME);
278         RdbMapping rdbmapping = (RdbMapping) cpro.getMapping(MAPPER_NAME);
279         RdbClassMultiMapping classmapping = (RdbClassMultiMapping) rdbmapping.getClassMapping();
280         RdbTable rdbtable = classmapping.getRdbTable();
281
282         // There is always a cmr-field, sometimes added by JOnAS, because we
283
// only deal with bidirectional relations.
284
String JavaDoc sCmr = sRole.getCmrFieldName();
285
286         // In case we have the same cmr field used in both roles, nothing to do
287
if (tClass == sClass && sClass.getTypedElement(sCmr) != null) {
288             if (logger.isLoggable(BasicLevel.DEBUG)) {
289                 logger.log(BasicLevel.DEBUG, "Nothing to do, same CMR field.");
290             }
291             return;
292         }
293
294         // add Dependencies between beans (= same cluster of beans)
295
// avoids dropping tables at each loading of beans in the same cluster.
296
if (tClass != sClass) {
297             classmapping.addDependency(tClass.getFQName());
298         }
299
300         // Mono-value cmr: create the Class Ref. and its NameDef
301
ClassRef cr = sClass.createClassRef(sCmr, tClass);
302         NameDef rndf = cr.createRefNameDef();
303
304         if (sRole.hasJdbcMapping() || tClass == sClass) {
305             // source bean has a JDBC mapping for its CMR field.
306
// 1 <-> N case (N side), or 1 <-> 1 case (Jdbc side)
307
classmapping.createReferenceMapping("embedded-target-reference", rndf);
308             if (tClass != sClass) {
309                 rdbtable.setColocated(true);
310                 rdbtable.setColocatedMaster(true);
311             }
312             if (tEntity.hasSimplePkField()) {
313                 // target bean has a Simple PK.
314
FieldJdbcDesc fd = (FieldJdbcDesc) tEntity.getSimplePkField();
315                 String JavaDoc cmrmappingname = sRole.getForeignKeyJdbcName(fd.getJdbcFieldName());
316                 PrimitiveElement pe = null;
317                 String JavaDoc clafn = sCmr + "_" + fd.getName();
318                 boolean peHasMapping = false;
319                 if (cmrmappingname != null) {
320                     //check if the CMR is mapper over a CMP
321
pe = getPrimitiveElementByColumn(classmapping, cmrmappingname);
322                 }
323                 if (pe == null) {
324                     //No CMP has been found ==> create an hidden field
325
pe = sClass.createHiddenField(clafn,
326                                                   JormType.getPType(fd.getFieldType(), fd.isPrimaryKey()),
327                                                   PType.NOSIZE, PType.NOSIZE);
328                 } else {
329                     peHasMapping = true;
330                 }
331                 //Register the field into the namedef
332
rndf.setFieldName(pe.getName());
333                 if (cmrmappingname != null) { // ???
334
if (!peHasMapping) {
335                         rdbtable.createPrimitiveElementMapping(pe, cmrmappingname, fd.getSqlType(), false);
336                     }
337                 } else if (tClass == sClass) {
338                     // tClass == sClass : unidirectional cmr on same bean
339
cmrmappingname = tRole.getForeignKeyJdbcName(fd.getJdbcFieldName());
340                     PrimitiveElementMapping pem = classmapping.getPrimitiveElementMapping(tRole.getCmrFieldName() + "_" + fd.getName());
341                     classmapping.addPrimitiveElementMapping(clafn, pem);
342                 }
343                 if (logger.isLoggable(BasicLevel.DEBUG)) {
344                     logger.log(BasicLevel.DEBUG, "CMR " + sCmr + " is mapped over the field: " + clafn + " / columname: " + cmrmappingname);
345                 }
346             } else {
347                 // target bean has a Composite PK.
348
NameRef cpk = rndf.createNameRef(tClass.getNameDef("").getNameRef().getCompositeName());
349                 for (Iterator JavaDoc i = tEntity.getCmpFieldDescIterator(); i.hasNext(); ) {
350                     FieldJdbcDesc fd = (FieldJdbcDesc) i.next();
351                     if (fd.isPrimaryKey()) {
352                         String JavaDoc cmrmappingname = sRole.getForeignKeyJdbcName(fd.getJdbcFieldName());
353                         PrimitiveElement pe = null;
354                         String JavaDoc clafn = sCmr + "_" + fd.getName();
355                         boolean peHasMapping = false;
356                         if (cmrmappingname != null) {
357                             //check if the CMR is mapper over a CMP
358
pe = getPrimitiveElementByColumn(classmapping, cmrmappingname);
359                         }
360                         if (pe == null) {
361                             //No CMP has been found ==> create an hidden field
362
pe = sClass.createHiddenField(clafn,
363                                                           JormType.getPType(fd.getFieldType(), fd.isPrimaryKey()),
364                                                           PType.NOSIZE, PType.NOSIZE);
365                         } else {
366                             peHasMapping = true;
367                         }
368                         cpk.addProjection(fd.getName(), pe.getName());
369                         if (cmrmappingname != null) {
370                             if (!peHasMapping) {
371                                 rdbtable.createPrimitiveElementMapping(pe, cmrmappingname, fd.getSqlType(), false);
372                             }
373                         } else if (tClass == sClass) {
374                             // tClass == sClass : unidirectional cmr on same bean (???)
375
cmrmappingname = tRole.getForeignKeyJdbcName(fd.getJdbcFieldName());
376                             PrimitiveElementMapping pem = classmapping.getPrimitiveElementMapping(tRole.getCmrFieldName() + "_" + fd.getName());
377                             classmapping.addPrimitiveElementMapping(clafn, pem);
378                         }
379                         if (logger.isLoggable(BasicLevel.DEBUG)) {
380                             logger.log(BasicLevel.DEBUG, "CMR " + sCmr + " is mapped over the field: " + clafn + " / columname: " + cmrmappingname);
381                         }
382                     }
383                 }
384             }
385         } else {
386             // The JDBC mapping for the source CMR field is done on the target bean.
387
// 1 <-> 1 case (non-jdbc side)
388
classmapping.createReferenceMapping("multi-table", rndf);
389             RdbExternalTable table2 = classmapping.createRdbExternalTable(tEntity.getJdbcTableName());
390             table2.setColocated(true); // Table used by 2 beans => update before insert
391
table2.setColocatedMaster(false);
392             table2.setReadOnly(true);
393             RdbJoin joinTo2 = table2.createRdbJoin(sCmr);
394             if (logger.isLoggable(BasicLevel.DEBUG)) {
395                 logger.log(BasicLevel.DEBUG, "CMR " + sCmr + " is mapped over the external table: " + tEntity.getJdbcTableName());
396             }
397             // source pk fields compose the join
398
if (sEntity.hasSimplePkField()) {
399                 FieldJdbcDesc spk = (FieldJdbcDesc) sEntity.getSimplePkField();
400                 String JavaDoc cmrmappingname = tRole.getForeignKeyJdbcName(spk.getJdbcFieldName());
401                 joinTo2.addJoinColumnNames(spk.getJdbcFieldName(), cmrmappingname);
402                 if (logger.isLoggable(BasicLevel.DEBUG)) {
403                     logger.log(BasicLevel.DEBUG, "CMR " + sCmr + ": join: " + spk.getJdbcFieldName() + " = " + cmrmappingname);
404                 }
405             } else {
406                 for (Iterator JavaDoc i = sEntity.getCmpFieldDescIterator(); i.hasNext(); ) {
407                     FieldJdbcDesc fd = (FieldJdbcDesc) i.next();
408                     if (fd.isPrimaryKey()) {
409                         String JavaDoc cmrmappingname = tRole.getForeignKeyJdbcName(fd.getJdbcFieldName());
410                         joinTo2.addJoinColumnNames(fd.getJdbcFieldName(), cmrmappingname);
411                         if (logger.isLoggable(BasicLevel.DEBUG)) {
412                             logger.log(BasicLevel.DEBUG, "CMR " + sCmr + ": join: " + fd.getJdbcFieldName() + " = " + cmrmappingname);
413                         }
414                     }
415                 }
416             }
417             // target pk fields compose the name def of reference
418
if (tEntity.hasSimplePkField()) {
419                 FieldJdbcDesc tpk = (FieldJdbcDesc) tEntity.getSimplePkField();
420                 String JavaDoc clafn = sCmr + "_" + tpk.getName();
421                 rndf.setFieldName(clafn);
422                 ScalarField sf = sClass.createHiddenField(clafn,
423                                                           JormType.getPType(tpk.getFieldType(), tpk.isPrimaryKey()),
424                                                           PType.NOSIZE, PType.NOSIZE);
425                 table2.createPrimitiveElementMapping(sf, tpk.getJdbcFieldName(), tpk.getSqlType(), false, joinTo2);
426                 if (logger.isLoggable(BasicLevel.DEBUG)) {
427                     logger.log(BasicLevel.DEBUG, "CMR " + sCmr + ": mapped over the field : " + clafn + " column: " + tpk.getJdbcFieldName());
428                 }
429             } else {
430                 NameRef cpk = rndf.createNameRef(tClass.getNameDef("").getNameRef().getCompositeName());
431                 for (Iterator JavaDoc i = tEntity.getCmpFieldDescIterator(); i.hasNext(); ) {
432                     FieldJdbcDesc fd = (FieldJdbcDesc) i.next();
433                     if (fd.isPrimaryKey()) {
434                         String JavaDoc clafn = sCmr + "_" + fd.getName();
435                         ScalarField sf = sClass.createHiddenField(clafn,
436                                                                   JormType.getPType(fd.getFieldType(), fd.isPrimaryKey()),
437                                                                   PType.NOSIZE, PType.NOSIZE);
438                         table2.createPrimitiveElementMapping(sf, fd.getJdbcFieldName(), fd.getSqlType(), false, joinTo2);
439                         cpk.addProjection(fd.getName(), sf.getName());
440                         if (logger.isLoggable(BasicLevel.DEBUG)) {
441                             logger.log(BasicLevel.DEBUG, "CMR " + sCmr + ": mapped over the field : " + clafn + " column: " + fd.getJdbcFieldName());
442                         }
443                     }
444                 }
445             }
446         }
447         mip.print("JORM MI for " + sAsn + ": ", sClass, pstream);
448         mip.print("JORM MI Mapping for " + sAsn + ": ", classmapping, pstream);
449     }
450
451     /**
452      * Creates the Jorm Meta Information for a relationship role (Multivalued CMR field)
453      * @param sRole source EjbRelationship Role Descriptor
454      * @param tRole target EjbRelationship Role Descriptor
455      * @throws PException Jorm Manager reported an exception
456      */

457     private void createJormRoleMIMulti(EjbRelationshipRoleDesc sRole, EjbRelationshipRoleDesc tRole)
458         throws PException {
459
460         if (logger.isLoggable(BasicLevel.DEBUG)) {
461             logger.log(BasicLevel.DEBUG, sRole.getName());
462         }
463
464         // source bean in the relation
465
EntityJdbcCmp2Desc sEntity = (EntityJdbcCmp2Desc) sRole.getSourceBean();
466         String JavaDoc sAsn = sEntity.getJormClassName();
467         Class JavaDoc sClass = manager.getClass(sAsn);
468
469         // target bean in the relation.
470
EntityJdbcCmp2Desc tEntity = (EntityJdbcCmp2Desc) sRole.getTargetBean();
471         String JavaDoc tAsn = tEntity.getJormClassName();
472         Class JavaDoc tClass = manager.getClass(tAsn);
473
474         ClassProject cpro = sClass.getClassProject(PROJECT_NAME);
475         RdbMapping rdbmapping = (RdbMapping) cpro.getMapping(MAPPER_NAME);
476         RdbClassMultiMapping classmapping = (RdbClassMultiMapping) rdbmapping.getClassMapping();
477
478         // There is always a cmr-field, sometimes added by JOnAS, because we
479
// only deal with bidirectional relations.
480
String JavaDoc sCmr = sRole.getCmrFieldName();
481
482         // In case we have the same cmr field used in both roles, nothing to do
483
if (tClass == sClass && sClass.getTypedElement(sCmr) != null) {
484             if (logger.isLoggable(BasicLevel.DEBUG)) {
485                 logger.log(BasicLevel.DEBUG, "Nothing to do, same CMR field.");
486             }
487             return;
488         }
489
490         // add Dependencies between beans (= same cluster of beans)
491
// avoids dropping tables at each loading of beans in the same cluster.
492
if (tClass != sClass) {
493             classmapping.addDependency(tClass.getFQName());
494         }
495
496         // Multi-value cmr: create the gen class and its Reference NameDef.
497
GenClassRef gcr = sClass.createGenClassRef(sCmr, sRole.getCmrFieldType().getName());
498         NameDef ndsg = gcr.createRefNameDef();
499
500         RdbGenClassMapping gcm = null;
501         RdbTable tableGC = null;
502         if (sRole.isSourceMultiple()) {
503             if (logger.isLoggable(BasicLevel.DEBUG)) {
504                 logger.log(BasicLevel.DEBUG, "Create GenClassReference for the CMR field (Many-Many): " + sCmr);
505             }
506             // M <-> N case
507
gcm = rdbmapping.createGenClassMapping("embedded-target-references", gcr);
508             // We need a jointure table in that case.
509
tableGC = gcm.createRdbTable(sRole.getRelation().getJdbcTableName());
510             if (sRole.isSlave()) {
511                 tableGC.setReadOnly(true);
512             }
513         } else {
514             if (logger.isLoggable(BasicLevel.DEBUG)) {
515                 logger.log(BasicLevel.DEBUG, "Create GenClassReference for the CMR field (One-Many): " + sCmr);
516             }
517             // 1 <-> N case (1 side) : store CMR on N side.
518
gcm = rdbmapping.createGenClassMapping("embedded-target-objects", gcr);
519             tableGC = gcm.createRdbTable(tEntity.getJdbcTableName());
520             tableGC.setReadOnly(true);
521             tableGC.setColocated(true);
522         }
523
524         // How the current bean references the gen class
525
// = the identifier of the source class
526
// no mapping, because already done for the bean pk.
527
classmapping.createReferenceMapping("embedded-target-reference", ndsg);
528         if (sEntity.hasSimplePkField()) {
529             // source bean has a Simple PK.
530
FieldJdbcDesc fd = (FieldJdbcDesc) sEntity.getSimplePkField();
531             ndsg.setFieldName(fd.getName());
532         } else {
533             // source bean has a Composite PK.
534
NameRef cpk = ndsg.createNameRef(sClass.getNameDef("").getNameRef().getCompositeName());
535             for (Iterator JavaDoc i = sEntity.getCmpFieldDescIterator(); i.hasNext(); ) {
536                 FieldJdbcDesc fd = (FieldJdbcDesc) i.next();
537                 if (fd.isPrimaryKey()) {
538                     // field names in the Composite are field names of the bean.
539
cpk.addProjection(fd.getName(), fd.getName());
540                 }
541             }
542         }
543
544         // How the gen class is identified (the gen class name)
545
// = the identifier of the source class
546
String JavaDoc fieldsuffix;
547         if (sClass == tClass) {
548             fieldsuffix = (sRole.isSlave() ? "2" : "1");
549         } else {
550             fieldsuffix = "";
551         }
552         NameDef ndid = gcr.createIdNameDef();
553         if (sEntity.hasSimplePkField()) {
554             // source bean has a Simple PK.
555
FieldJdbcDesc fd = (FieldJdbcDesc) sEntity.getSimplePkField();
556             String JavaDoc clafn = sAsn + "_" + fd.getName() + fieldsuffix;
557             ndid.setFieldName(clafn);
558             ScalarField pe = gcr.createHiddenField(clafn,
559                                                    JormType.getPType(fd.getFieldType(), fd.isPrimaryKey()),
560                                                    PType.NOSIZE, PType.NOSIZE);
561
562             String JavaDoc fkname = tRole.getForeignKeyJdbcName(fd.getJdbcFieldName());
563             tableGC.createPrimitiveElementMapping(pe, fkname, fd.getSqlType(), false);
564             if (logger.isLoggable(BasicLevel.DEBUG)) {
565                 logger.log(BasicLevel.DEBUG, "GC id is mapped over the field: " + clafn + " / column:" + fkname);
566             }
567         } else {
568             // source bean has a Composite PK.
569
NameRef cpk = ndid.createNameRef(sClass.getNameDef("").getNameRef().getCompositeName());
570             for (Iterator JavaDoc i = sEntity.getCmpFieldDescIterator(); i.hasNext(); ) {
571                 FieldJdbcDesc fd = (FieldJdbcDesc) i.next();
572                 if (fd.isPrimaryKey()) {
573                     String JavaDoc clafn = sAsn + "_" + fd.getName() + fieldsuffix;
574                     ScalarField sf = gcr.createHiddenField(clafn,
575                                                            JormType.getPType(fd.getFieldType(), fd.isPrimaryKey()),
576                                                            PType.NOSIZE, PType.NOSIZE);
577                     cpk.addProjection(fd.getName(), sf.getName());
578                     String JavaDoc fkname = tRole.getForeignKeyJdbcName(fd.getJdbcFieldName());
579                     tableGC.createPrimitiveElementMapping(sf, fkname, fd.getSqlType(), false);
580                     if (logger.isLoggable(BasicLevel.DEBUG)) {
581                         logger.log(BasicLevel.DEBUG, "GC id is mapped over the field: " + clafn + " / column:" + fkname);
582                     }
583                 }
584             }
585         }
586         gcm.createIdentifierMapping(ndid);
587
588         // How the referenced class is referenced from the gen class.
589
// Describes an Element of the GenClass.
590
// = pk of the target bean
591
if (sClass == tClass) {
592             fieldsuffix = (tRole.isSlave() ? "2" : "1");
593         } else {
594             fieldsuffix = "";
595         }
596         // Create the ClassRef and its NameDef.
597
NameDef ndr2 = gcr.createClassRef(tClass).createRefNameDef();
598         gcm.createReferenceMapping("embedded-target-object", ndr2);
599
600         if (tEntity.hasSimplePkField()) {
601             // target bean has a Simple PK.
602
FieldJdbcDesc fd = (FieldJdbcDesc) tEntity.getSimplePkField();
603             String JavaDoc fkname;
604             if (sRole.isSourceMultiple()) {
605                 // M <-> N case
606
fkname = sRole.getForeignKeyJdbcName(fd.getJdbcFieldName());
607             } else {
608                 // 1 <-> N case
609
fkname = fd.getJdbcFieldName();
610             }
611             ScalarField pe = getPrimitiveElementByColumn(gcm, fkname);
612             if (pe == null) {
613                 String JavaDoc clafn = tAsn + "_" + fd.getName() + fieldsuffix;
614                 pe = gcr.createHiddenField(clafn,
615                                            JormType.getPType(fd.getFieldType(), fd.isPrimaryKey()),
616                                            PType.NOSIZE, PType.NOSIZE);
617                 tableGC.createPrimitiveElementMapping(pe, fkname, fd.getSqlType(), false);
618             }
619             ndr2.setFieldName(pe.getName());
620             if (logger.isLoggable(BasicLevel.DEBUG)) {
621                 logger.log(BasicLevel.DEBUG, "GC elem is mapped over the field: " + pe.getName() + " / column:" + fkname);
622             }
623         } else {
624             // target Bean has a Composite PK.
625
NameRef cpk = ndr2.createNameRef(tClass.getNameDef("").getNameRef().getCompositeName());
626             for (Iterator JavaDoc i = tEntity.getCmpFieldDescIterator(); i.hasNext(); ) {
627                 FieldJdbcDesc fd = (FieldJdbcDesc) i.next();
628                 if (fd.isPrimaryKey()) {
629                     String JavaDoc fkname;
630                     if (sRole.isSourceMultiple()) {
631                         // M <-> N case
632
fkname = sRole.getForeignKeyJdbcName(fd.getJdbcFieldName());
633                     } else {
634                         // 1 <-> N case
635
fkname = fd.getJdbcFieldName();
636                     }
637                     ScalarField pe = getPrimitiveElementByColumn(gcm, fkname);
638                     if (pe == null) {
639                         String JavaDoc clafn = tAsn + "_" + fd.getName() + fieldsuffix;
640                         pe = gcr.createHiddenField(clafn,
641                                                    JormType.getPType(fd.getFieldType(), fd.isPrimaryKey()),
642                                                    PType.NOSIZE, PType.NOSIZE);
643                         tableGC.createPrimitiveElementMapping(pe, fkname, fd.getSqlType(), false);
644                     }
645                     cpk.addProjection(fd.getName(), pe.getName());
646                     if (logger.isLoggable(BasicLevel.DEBUG)) {
647                         logger.log(BasicLevel.DEBUG, "GC elem is mapped over the field: " + pe.getName() + " / column:" + fkname);
648                     }
649                 }
650             }
651         }
652         mip.print("JORM MI for " + sAsn + ": ", sClass, pstream);
653         mip.print("JORM MI Mapping for " + sAsn + ": ", classmapping, pstream);
654     }
655
656     private PrimitiveElement getPrimitiveElementByColumn(RdbClassMultiMapping cm, String JavaDoc col) {
657         PrimitiveElementMapping pem = cm.getRdbTable().getPrimitiveElementMappingByCol(col);
658         if (pem == null) {
659             if (logger.isLoggable(BasicLevel.DEBUG)) {
660                 logger.log(BasicLevel.DEBUG, "no " + col);
661             }
662             return null;
663         }
664         if (logger.isLoggable(BasicLevel.DEBUG)) {
665             logger.log(BasicLevel.DEBUG, "yes " + col);
666         }
667         return (PrimitiveElement) pem.getLinkedMO();
668     }
669
670     private ScalarField getPrimitiveElementByColumn(RdbGenClassMapping cm, String JavaDoc col) {
671         PrimitiveElementMapping pem = cm.getRdbTable().getPrimitiveElementMappingByCol(col);
672         if (pem == null) {
673             if (logger.isLoggable(BasicLevel.DEBUG)) {
674                 logger.log(BasicLevel.DEBUG, "no " + col);
675             }
676             return null;
677         }
678         if (logger.isLoggable(BasicLevel.DEBUG)) {
679             logger.log(BasicLevel.DEBUG, "yes " + col);
680         }
681         return (ScalarField) pem.getLinkedMO();
682     }
683 }
684
Popular Tags