KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > speedo > generation > jorm > rdb > OneTableRdbJormIMappingBuilder


1 /**
2  * Copyright (C) 2001-2004 France Telecom R&D
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  */

18 package org.objectweb.speedo.generation.jorm.rdb;
19
20 import org.objectweb.jorm.api.PException;
21 import org.objectweb.jorm.lib.JormPathHelper;
22 import org.objectweb.jorm.mapper.rdb.metainfo.RdbClassMapping;
23 import org.objectweb.jorm.mapper.rdb.metainfo.RdbClassMultiMapping;
24 import org.objectweb.jorm.mapper.rdb.metainfo.RdbExternalTable;
25 import org.objectweb.jorm.mapper.rdb.metainfo.RdbGenClassMapping;
26 import org.objectweb.jorm.mapper.rdb.metainfo.RdbJoin;
27 import org.objectweb.jorm.mapper.rdb.metainfo.RdbPrimitiveElementMapping;
28 import org.objectweb.jorm.mapper.rdb.metainfo.RdbTable;
29 import org.objectweb.jorm.metainfo.api.Class;
30 import org.objectweb.jorm.metainfo.api.ClassMapping;
31 import org.objectweb.jorm.metainfo.api.ClassRef;
32 import org.objectweb.jorm.metainfo.api.CommonClassMapping;
33 import org.objectweb.jorm.metainfo.api.GenClassMapping;
34 import org.objectweb.jorm.metainfo.api.GenClassRef;
35 import org.objectweb.jorm.metainfo.api.Manager;
36 import org.objectweb.jorm.metainfo.api.Mapping;
37 import org.objectweb.jorm.metainfo.api.MetaObject;
38 import org.objectweb.jorm.metainfo.api.NameDef;
39 import org.objectweb.jorm.metainfo.api.PrimitiveElement;
40 import org.objectweb.jorm.metainfo.api.PrimitiveElementMapping;
41 import org.objectweb.jorm.metainfo.api.TypedElement;
42 import org.objectweb.jorm.util.api.Loggable;
43 import org.objectweb.speedo.api.SpeedoException;
44 import org.objectweb.speedo.api.SpeedoProperties;
45 import org.objectweb.speedo.generation.jorm.JormMIMappingBuilder;
46 import org.objectweb.speedo.metadata.SpeedoClass;
47 import org.objectweb.speedo.metadata.SpeedoCollection;
48 import org.objectweb.speedo.metadata.SpeedoElement;
49 import org.objectweb.speedo.metadata.SpeedoExtension;
50 import org.objectweb.speedo.metadata.SpeedoField;
51 import org.objectweb.speedo.metadata.SpeedoMap;
52 import org.objectweb.util.monolog.api.BasicLevel;
53 import org.objectweb.util.monolog.api.Logger;
54 import org.objectweb.util.monolog.api.LoggerFactory;
55
56 import java.util.HashMap JavaDoc;
57 import java.util.Iterator JavaDoc;
58 import java.util.Map JavaDoc;
59 import java.util.StringTokenizer JavaDoc;
60
61 /**
62  * This class is an implementation of the JormMIMappingBuilder for the mapper
63  * rdb and its sub mappers. It defines a simple mapping where each persistent
64  * objects (generic class included) are mapped over one table.
65  *
66  * @author S.Chassande-Barrioz
67  */

68 public class OneTableRdbJormIMappingBuilder
69         implements JormMIMappingBuilder, SpeedoProperties, Loggable {
70
71     private final static String JavaDoc CLASS_MAPPING_RULE_NAME = "multi-table";
72     private final static String JavaDoc GENCLASS_MAPPING_RULE_NAME = "to-table";
73
74     private Logger logger;
75     private boolean debug = false;
76
77     // IMPLEMENTATION OF THE Loggable INTERFACE //
78
//------------------------------------------//
79

80     public Logger getLogger() {
81         return logger;
82     }
83
84     public LoggerFactory getLoggerFactory() {
85         return null;
86     }
87
88     public void setLogger(Logger logger) {
89         this.logger = logger;
90         debug = logger != null && logger.isLoggable(BasicLevel.DEBUG);
91     }
92
93     public void setLoggerFactory(LoggerFactory loggerFactory) {
94         if (logger == null && loggerFactory != null) {
95             setLogger(loggerFactory.getLogger(
96                     SpeedoProperties.LOGGER_NAME
97                 + ".generation.jorm.mimappingbuilder"));
98         }
99     }
100
101     // IMPLEMENTATION OF THE Loggable INTERFACE //
102
//------------------------------------------//
103

104     /**
105      * It builds a RdbClassMultiMapping and creates the main table.
106      * The name of the table is built with the short class name.
107      * @param clazz is the Jorm meta object representing the class which the
108      * ClassMapping must be built.
109      * @param mapping is the Mapping instance which will host the ClassMapping.
110      * @return the ClassMapping instance built by the method (never null).
111      * @throws org.objectweb.jorm.api.PException if it is not possible to build the ClassMapping
112      */

113     public ClassMapping createClassMapping(Class JavaDoc clazz,
114                                            SpeedoClass sc,
115                                            Mapping mapping)
116             throws PException, SpeedoException {
117         RdbClassMultiMapping rcm = new RdbClassMultiMapping(
118                 CLASS_MAPPING_RULE_NAME, clazz, mapping);
119         mapping.setClassMapping(rcm);
120         rcm.createRdbTable(getTableName(sc));
121         return rcm;
122     }
123
124     public void finalizeClassMapping(SpeedoClass sc,
125                                      String JavaDoc projectName,
126                                      String JavaDoc mapperName)
127         throws PException, SpeedoException {
128         RdbClassMultiMapping rcm = (RdbClassMultiMapping) sc.jormclass
129             .getClassProject(projectName).getMapping(mapperName).getClassMapping();
130         if (sc.superClassName != null) {
131             String JavaDoc ruleName;
132             String JavaDoc im = sc.getExtensionValueByKey(SpeedoProperties.INHERITANCE_MAPPING);
133             if (im == null) {
134                 throw new SpeedoException(
135                     "No inheritance mapping defined for the class '" + sc.getFQName() +"'");
136             } else if (SpeedoProperties.INHERITANCE_FILTERED_MAPPING.equals(im)) {
137
138                 ruleName = RdbClassMapping.MAP_NEW_FIELDS_TO_EXTENDED_STRUCTURES;
139             } else if (SpeedoProperties.INHERITANCE_HORIZONTAL_MAPPING.equals(im)) {
140                 ruleName = RdbClassMapping.REMAP_FIELDS_TO_NEW_STRUCTURES;
141             } else if (SpeedoProperties.INHERITANCE_VERTICAL_MAPPING.equals(im)) {
142                 ruleName = RdbClassMapping.MAP_NEW_FIELDS_TO_ADDED_STRUCTURES;
143                 //TODO: support vertical inheritance mapping
144
//TODO: link the main table to the one of the parent, and create an external table
145
throw new SpeedoException("The vertical mapping for the inheritance is not supported currently");
146             } else {
147                 throw new SpeedoException("Inheritance mapping type is unknown ("
148                     + im + ") for the class '" + sc.getFQName() +"'");
149             }
150             SpeedoClass parent = sc.getSpeedoClassFromContext(sc.superClassName);
151             rcm.createParentClassMapping(ruleName, sc.jormclass.getSuperClass(parent.getFQName()));
152             //Add inter dependencies between the parent and its child
153
if (debug) {
154                 logger.log(BasicLevel.DEBUG, "Add dependencies between "
155                     + parent.getFQName() + " and " + sc.getFQName());
156             }
157             rcm.addDependency(parent.getFQName());
158             parent.jormclass.getClassProject(projectName)
159                 .getMapping(mapperName).getClassMapping().addDependency(sc.getFQName());
160         }
161     }
162
163     /**
164      * It builds a RdbClassMultiMapping and creates the table.
165      * the table is build with the generic class identifier ("A/f1" ==> "A_f1")
166      * @param gcr is the Jorm meta object representing the gen class which the
167      * GenClassMapping must be built.
168      * @param mapping is the Mapping instance which will host the GenClassMapping.
169      * @return the GenClassMapping instance built by the method (never null).
170      * @throws org.objectweb.jorm.api.PException if it is not possible to build the GenClassMapping
171      */

172     public GenClassMapping createGenClassMapping(GenClassRef gcr,
173                                                  SpeedoField sf,
174                                                  Mapping mapping)
175             throws PException, SpeedoException {
176         RdbGenClassMapping rgcm = new RdbGenClassMapping(
177                 GENCLASS_MAPPING_RULE_NAME, gcr, mapping);
178         mapping.addGenClassMapping(gcr.getGenClassId(), rgcm);
179         SpeedoExtension se = sf.getExtension(VENDOR_NAME, JOIN_TABLE);
180         if (se != null) {
181             rgcm.createRdbTable(se.value);
182             se = sf.getExtensionByKey(REVERSE_FIELD);
183             if (se != null) {
184                 String JavaDoc cn = null;
185                 if (sf.jdoTuple instanceof SpeedoCollection) {
186                     cn = (String JavaDoc) ((SpeedoCollection) sf.jdoTuple).elementType;
187                 } else if (sf.jdoTuple instanceof SpeedoMap) {
188                     cn = (String JavaDoc) ((SpeedoMap) sf.jdoTuple).valueType;
189                 }
190                 SpeedoClass sc = sf.jdoClass.jdoPackage.jdoXMLDescriptor.smi.
191                     getSpeedoClass(cn, sf.jdoClass.jdoPackage);
192                 SpeedoField sf2 = (SpeedoField) sc.jdoField.get(se.value);
193                 Class JavaDoc c = ((Manager) gcr.getParent().getParent().getParent())
194                         .getClass(sc.getFQName());
195                 TypedElement te = c.getTypedElement(sf2.name);
196                 if (te instanceof GenClassRef) {
197                     rgcm.getRdbTable().setReadOnly(true);
198                     logger.log(BasicLevel.DEBUG, "field '" + sf.name + "' is read only");
199                 }
200                 //optimisation: if there is a reverse field then we suppose that
201
}
202         } else if (gcr.isClassRef()
203                 && sf.getExtension(VENDOR_NAME, SOURCE_FK) != null
204                 && sf.getExtension(VENDOR_NAME, TARGET_FK) == null) {
205             // The gen class is mapped over the table of the targeted class
206
SpeedoClass tsc = sf.jdoClass.jdoPackage.jdoXMLDescriptor
207                     .getSpeedoClass(gcr.getClassRef().getMOClass().getFQName(), true);
208             se = (tsc == null ? null : tsc.getExtensionByKey(SQL_NAME));
209             Manager mgr = getManager(gcr);
210             Class JavaDoc tclazz = mgr.getClass(tsc.getFQName());
211             RdbClassMultiMapping trcm = (RdbClassMultiMapping)
212             tclazz.getClassProject(mapping.getClassMapping().getProjectName())
213                 .getMapping(mapping.getMapperName()).getClassMapping();
214             RdbTable t = rgcm.createRdbTable(
215                     (se == null ? getTableName(tsc) : se.value));
216             // The GC table and the table of the targeted class are colocated
217
t.setColocated(true);
218             se = sf.getExtensionByKey(REVERSE_FIELD);
219             if (se != null) {
220                 logger.log(BasicLevel.DEBUG, "REVERSE-FIELD(" + sf.name + "):" + se.value);
221                 //optimisation: if there is a reverse field then we suppose that
222
// the user will do the coherence.
223
t.setReadOnly(true);
224             } else {
225                 logger.log(BasicLevel.DEBUG, "No REVERSE-FIELD(" + sf.name + ")");
226                 trcm.getRdbTable().setColocated(true);
227                 trcm.getRdbTable().setColocatedMaster(true);
228             }
229             trcm.addDependency(sf.jdoClass.getFQName());
230             mapping.getClassMapping().addDependency(tclazz.getFQName());
231         } else {
232             //default mapping: join table
233
rgcm.createRdbTable(getTableName(gcr));
234         }
235         return rgcm;
236     }
237
238     /**
239      * The column name is built with the field name.
240      * @param pe is the Jorm meta object representing a primitive field
241      * @param cm is the MappingStructure which will host the mapping of the
242      * field
243      * @return a PrimitiveElementMapping corresponding to the given primitive
244      * field.
245      * @throws org.objectweb.jorm.api.PException if it is not possible to build the mapping of the
246      * primitive field.
247      */

248     public PrimitiveElementMapping createFieldMapping(PrimitiveElement pe,
249                                                       SpeedoElement selem,
250                                                       CommonClassMapping cm)
251             throws PException {
252         RdbTable t;
253         boolean ingc = false;
254         String JavaDoc extensionColName = SQL_NAME;
255         String JavaDoc extensionColType = SQL_TYPE;
256         if (cm instanceof RdbClassMultiMapping) {
257             t = ((RdbClassMultiMapping) cm).getRdbTable();
258         } else if (cm instanceof RdbGenClassMapping) {
259             ingc = true;
260             GenClassRef gcr = (GenClassRef) pe.getParent();
261             if (gcr.getPrimitiveElement() == pe) {
262                 extensionColName = ELEMENT;
263                 extensionColType = ELEMENT_TYPE;
264             } else {
265                 Iterator JavaDoc it = gcr.getIndexFields().iterator();
266                 if (it.hasNext() && pe == it.next()) {
267                     extensionColName = INDEX;
268                     extensionColType = INDEX_TYPE;
269                 }
270             }
271             t = ((RdbGenClassMapping) cm).getRdbTable();
272         } else {
273             new Exception JavaDoc().printStackTrace();
274             throw new PException("Unmanaged HelperClassMapping: " + cm);
275         }
276         String JavaDoc colName = getColumnName(pe);
277         String JavaDoc colType = null;
278         if (selem != null) {
279             if (selem instanceof SpeedoClass) {
280                 //Search the mapping of the inherited field (horizontal mapping).
281
extensionColName = pe.getName() + '-' + extensionColName;
282                 extensionColType = pe.getName() + '-' + extensionColType;
283             } else if (selem instanceof SpeedoField
284                     && ((SpeedoField) selem).jdoTuple instanceof SpeedoMap
285                     && selem.getExtensionValueByKey(KEY_FIELD) != null
286                     ) {
287
288             }
289             SpeedoExtension seColName = selem.getExtensionByKey(extensionColName);
290             if (seColName != null) {
291                 colName = seColName.value;
292             }
293             SpeedoExtension seColType = selem.getExtensionByKey(extensionColType);
294             if (seColType != null) {
295                 colType = seColType.value;
296             }
297         }
298         return t.createPrimitiveElementMapping(pe,colName, colType, false);
299     }
300
301     /**
302      * It creates the mapping of a name def (reference or identifier).
303      * @param cm is the MappingStructure which will host the mapping of the
304      * fields of the name def
305      * @param nd is the NameDef which must be mapped.
306      * @throws org.objectweb.jorm.api.PException if it is not possible to build the mapping of the
307      * field.
308      */

309     public void createNameDefMapping(CommonClassMapping cm,
310                                      NameDef nd,
311                                      SpeedoClass sc,
312                                      boolean isIdentifier,
313                                      boolean isInGenClass)
314             throws PException, SpeedoException {
315         if (debug) {
316             logger.log(BasicLevel.DEBUG, "RdbMapping: createNameDefMapping "
317                 + "\n\tnd=" + nd
318                 + "\n\tsc=" + (sc == null ? null : sc.getFQName())
319                 + "\n\tisIdentifier=" + isIdentifier
320                 + "\n\tisInGenClass=" + isInGenClass
321                 );
322         }
323         if (!isInGenClass) {
324             Class JavaDoc clazz;
325             if (isIdentifier) {
326                 //This is the identifier of the class
327
clazz = (Class JavaDoc) nd.getParent();
328                 if (nd.isFieldName()) {
329                     PrimitiveElement pe = (PrimitiveElement)
330                             clazz.getTypedElement(nd.getFieldName());
331                     if (pe == null) {
332                         throw new SpeedoException("impossible to map the fields of the namedef of the metaobject '" + JormPathHelper.getPath(clazz) + "'.");
333                     }
334                     createFieldMapping(pe, null, cm);
335                 } else {
336                     Iterator JavaDoc it = nd.getNameRef().getProjection().values().iterator();
337                     while(it.hasNext()) {
338                         PrimitiveElement pe = (PrimitiveElement)
339                             clazz.getTypedElement((String JavaDoc) it.next());
340                         if (pe == null) {
341                             throw new SpeedoException("impossible to map the fields of the namedef of the metaobject '" + JormPathHelper.getPath(clazz) + "'.");
342                         }
343                         createFieldMapping(pe, null, cm);
344                     }
345                 }
346             } else {
347                 MetaObject mo = nd.getParent();
348                 if (mo instanceof GenClassRef) {
349                     NameDef classNd = (NameDef) cm.getIdentifierMapping().getLinkedMO();
350                     if ((nd.isFieldName() && classNd.isFieldName() && nd.getFieldName().equals(classNd.getFieldName()))
351                         || (nd.isNameRef() && classNd.isNameRef()
352                             && classNd.getNameRef().getCompositeName().equals(nd.getNameRef().getCompositeName())
353                             && classNd.getNameRef().getProjection().equals(nd.getNameRef().getProjection())) ) {
354                         // The reference of the gen class is mapped over the source
355
// class identifier, then the field of the identifier are
356
// already mapped.
357
logger.log(BasicLevel.DEBUG, "Mapping of the GCR ref '"
358                                 + ((GenClassRef) mo).getName()
359                                 + "' already defined");
360                     } else {
361                         //The reference of the gen class is mapped over fields
362
// which do not composed the source class identifier
363
// then the mapping of these field must be created.
364
createGenClassRefNameDef(sc, (GenClassRef) mo, cm, nd);
365                     }
366                 } else {
367                     //This is a reference to a persistent object since a class.
368
createClassRefNameDef(sc, (ClassRef) mo, cm, nd);
369                 }
370             }
371         } else {
372             if (isIdentifier) {
373                 creaGenClassRefIdNameDef(nd, sc, (RdbGenClassMapping) cm);
374             } else {
375                 creaGenClassRefRefNameDef(nd, sc, (RdbGenClassMapping) cm);
376             }
377         }
378     }
379
380
381     // PRIVATE METHODS //
382
//-----------------//
383
private void createGenClassRefNameDef(SpeedoClass sc,
384                                        GenClassRef gcr,
385                                        CommonClassMapping cm,
386                                        NameDef gcrnd)
387             throws SpeedoException, PException {
388         logger.log(BasicLevel.DEBUG, "Defining the mapping of the GCR ref '"
389                 + gcr.getName() + "' ...");
390         //The ClassMapping of the current class.
391
RdbClassMultiMapping rcm = (RdbClassMultiMapping) cm;
392         if (gcrnd.isFieldName()) {
393             String JavaDoc fn = gcrnd.getFieldName();
394             PrimitiveElement pe = (PrimitiveElement)
395                     sc.jormclass.getTypedElement(fn);
396             if (pe == null) {
397                 pe = sc.jormclass.getHiddenField(fn);
398             }
399             if (pe == null) {
400                 throw new SpeedoException("No field '" + fn
401                         + "' found on the class '" + sc.getFQName() + "'");
402             }
403             logger.log(BasicLevel.DEBUG, "Map the PE '" + pe.getName()
404                     + "' on the column '" + pe.getName() + "'.");
405             rcm.getRdbTable().createPrimitiveElementMapping(pe, pe.getName());
406         } else if (gcrnd.isNameRef()) {
407             Iterator JavaDoc itClaFns = gcrnd.getNameRef().getProjection().values().iterator();
408             while(itClaFns.hasNext()) {
409                 String JavaDoc fn = (String JavaDoc) itClaFns.next();
410                 PrimitiveElement pe = (PrimitiveElement)
411                         sc.jormclass.getTypedElement(fn);
412                 if (pe == null) {
413                     pe = sc.jormclass.getHiddenField(fn);
414                 }
415                 if (pe == null) {
416                     throw new SpeedoException("No field '" + fn
417                             + "' found on the class '" + sc.getFQName() + "'");
418                 }
419                 logger.log(BasicLevel.DEBUG, "Map the PE '" + pe.getName()
420                         + "' on the column '" + pe.getName() + "'.");
421                 rcm.getRdbTable().createPrimitiveElementMapping(pe, pe.getName());
422             }
423         }
424     }
425
426     /**
427      * Mappes a ClassRef over sql columns. In according to the speedo extension
428      * a local foreign key (default case) or a join with the referenced table
429      * is added for the reference mapping.
430      * @param sc is the SpeedoClass hosting the reference
431      * @param cr is the jorm meta object representing the reference
432      * @param cm is the ClassMapping of the class hosting the reference
433      * @param crnd is the name def of the reference.
434      * @throws org.objectweb.speedo.api.SpeedoException if the meta information is not complete
435      */

436     private void createClassRefNameDef(SpeedoClass sc,
437                                        ClassRef cr,
438                                        CommonClassMapping cm,
439                                        NameDef crnd)
440             throws SpeedoException, PException {
441         logger.log(BasicLevel.DEBUG, "Create the name def of the ClassRef: "
442                 + JormPathHelper.getPath(cr));
443         //The ClassMapping of the current class.
444
RdbClassMultiMapping rcm = (RdbClassMultiMapping) cm;
445         //The Speedo Meta object of the referenced class
446
SpeedoClass tsc = sc.jdoPackage.jdoXMLDescriptor
447             .getSpeedoClass(cr.getMOClass().getFQName(), true);
448         //The ClassMapping of the referenced class.
449
RdbClassMultiMapping trcm = (RdbClassMultiMapping)
450                 tsc.jormclass.getClassProject(cm.getProjectName())
451                 .getMapping(cm.getMapperName()).getClassMapping();
452         //The Speedo meta object mathcing to the ClassRef
453
SpeedoField sf = (SpeedoField) sc.jdoField.get(cr.getName());
454         if (sf == null) {
455             throw new SpeedoException("impossible to map the namedef of the field '"
456                     + JormPathHelper.getPath(cr) + "': no SpeedoField '"
457                     + cr.getName()+ "' on the SpeedoClass " + sc.getFQName());
458         }
459
460         //The name def of the referenced class
461
NameDef tclassnd = (NameDef)
462                 trcm.getIdentifierMapping().getLinkedMO();
463
464         SpeedoExtension se = sf.getExtension(VENDOR_NAME, SOURCE_FK);
465         String JavaDoc sfk = (se == null ? null : se.value);
466         if (sfk != null) {
467             //foreign key in the external table
468
if (tsc.superClassName != null) {
469                 throw new PException(
470                     "Jorm does not support to store a polymorphic reference '"
471                     + sc.getFQName() + "." + cr.getName()+ "'with a " + SOURCE_FK);
472             }
473             se = tsc.getExtensionByKey(SQL_NAME);
474             String JavaDoc tn = (se == null ? getTableName(sc) : se.value);
475             logger.log(BasicLevel.DEBUG, " - External table: " + tn);
476             RdbExternalTable exttable = rcm.createRdbExternalTable(tn);
477             if (sf.getExtensionByKey(REVERSE_FIELD) != null) {
478                 exttable.setReadOnly(true);
479             }
480             // The external table and the table of the targeted class are
481
// colocated
482
exttable.setColocated(true);
483             trcm.getRdbTable().setColocated(true);
484             trcm.getRdbTable().setColocatedMaster(true);
485             trcm.addDependency(sc.getFQName());
486             cm.addDependency(tsc.getFQName());
487
488             //optimisation: if there is a reverse field then we suppose that
489
// the user will do the coherence.
490
se = sf.getExtension(VENDOR_NAME, REVERSE_FIELD);
491             logger.log(BasicLevel.DEBUG, " - readonly: " + (se != null));
492             exttable.setReadOnly(se != null);
493
494             //Define the join to the external table
495
RdbJoin j = exttable.createRdbJoin(cr.getName());
496             Iterator JavaDoc it = getPk2Fk(sfk).entrySet().iterator();
497             while(it.hasNext()) {
498                 Map.Entry me = (Map.Entry) it.next();
499                 logger.log(BasicLevel.DEBUG, " - join: "
500                         + me.getKey() + " == " + me.getValue());
501                 j.addJoinColumnNames((String JavaDoc) me.getKey(),
502                         (String JavaDoc) me.getValue());
503             }
504             //map the name def over pk field of the referenced class
505
if (tclassnd.isFieldName()) {
506                 RdbPrimitiveElementMapping pem = (RdbPrimitiveElementMapping)
507                         trcm.getPrimitiveElementMapping(tclassnd.getFieldName(), true);
508                 PrimitiveElement pe = (PrimitiveElement)
509                         sc.jormclass.getTypedElement(crnd.getFieldName());
510                 exttable.createPrimitiveElementMapping(pe, pem.getName(), null, false, j);
511             } else {
512                 Map tclassndproj = tclassnd.getNameRef().getProjection();
513                 it = crnd.getNameRef().getProjection().entrySet().iterator();
514                 while(it.hasNext()) {
515                     Map.Entry me = (Map.Entry) it.next();
516                     PrimitiveElement pe = (PrimitiveElement)
517                             sc.jormclass.getTypedElement((String JavaDoc) me.getValue());
518                     RdbPrimitiveElementMapping pem = (RdbPrimitiveElementMapping)
519                         trcm.getPrimitiveElementMapping(
520                                 (String JavaDoc) tclassndproj.get(me.getKey()), true);
521                     exttable.createPrimitiveElementMapping(pe, pem.getName(), null, false, j);
522                 }
523             }
524         } else {
525             //local foreign keys
526
RdbTable table = rcm.getRdbTable();
527             logger.log(BasicLevel.DEBUG, " - main table: " + table.getName());
528
529             se = sf.getExtension(VENDOR_NAME, TARGET_FK);
530             String JavaDoc tfk = (se == null ? null : se.value);
531             Map pk2fk = null;
532             if (tfk != null) {
533                 pk2fk = getPk2Fk(tfk);
534             } else {
535                 //default mapping of a reference: local foreign keys
536
// The column name is equal to the field name.
537
logger.log(BasicLevel.DEBUG, " - default mapping");
538                 pk2fk = new HashMap JavaDoc();
539                 if (crnd.isFieldName()) {
540                     RdbPrimitiveElementMapping pem = (RdbPrimitiveElementMapping)
541                             trcm.getPrimitiveElementMapping(tclassnd.getFieldName(), true);
542                     pk2fk.put(pem.getName(), crnd.getFieldName());
543                     logger.log(BasicLevel.DEBUG, " - pk2fk: " + pem.getName() + " == " + crnd.getFieldName());
544                 } else {
545                     Iterator JavaDoc it = crnd.getNameRef().getProjection().entrySet().iterator();
546                     Map tclassndproj = tclassnd.getNameRef().getProjection();
547                     while (it.hasNext()) {
548                         Map.Entry me = (Map.Entry) it.next();
549                         RdbPrimitiveElementMapping pem = getPEMOfField(
550                             tsc, cm.getProjectName(), cm.getMapperName(), (String JavaDoc)
551                         tclassndproj.get(me.getKey()));
552                         pk2fk.put(pem.getName(), me.getValue());
553                     }
554                 }
555             }
556             //Map the name def of the reference over new local columns
557
if (crnd.isFieldName()) {
558                 //find the pk column name
559
RdbPrimitiveElementMapping pem = getPEMOfField(
560                     tsc, cm.getProjectName(), cm.getMapperName(), tclassnd.getFieldName());
561
562                 //find the field in the class used in by this name def
563
PrimitiveElement pe = (PrimitiveElement)
564                         sc.jormclass.getTypedElement(crnd.getFieldName());
565                 //find the fk column name
566
String JavaDoc colname = (String JavaDoc) pk2fk.get(pem.getName());
567                 //check if the fk column name is already used
568
PrimitiveElementMapping pem2 =
569                         table.getPrimitiveElementMappingByCol(colname);
570                 if (pem2 == null) {
571                     // create it
572
if (colname == null) {
573                         throw new SpeedoException("No column name defined for a foreign key: "
574                             + "\n\tfield name=" + pe.getName()
575                             + "\n\tpk column name=" + pem.getName());
576                     }
577                     table.createPrimitiveElementMapping(pe, colname, pem.getType(), false);
578                 } else {
579                     //it exists then assign the real primitive element to the
580
// the name def
581
logger.log(BasicLevel.INFO, "pas collection:\n pe.getParent():" + pe.getParent().toString()
582                             + "\n pe.getName():" + pe.getName() + "\n pem2.getLinkedMO():" + pem2.getLinkedMO());
583                     ((Class JavaDoc) pe.getParent()).removeTypedElement(pe.getName());
584                     pe = (PrimitiveElement) pem2.getLinkedMO();
585                     crnd.setFieldName(pe.getName());
586                 }
587             } else {
588                 Map tclassndproj = tclassnd.getNameRef().getProjection();
589                 Iterator JavaDoc it = crnd.getNameRef().getProjection().entrySet().iterator();
590                 while(it.hasNext()) {
591                     Map.Entry me = (Map.Entry) it.next();
592                     //find the field in the class used in by this name def
593
PrimitiveElement pe = (PrimitiveElement)
594                             sc.jormclass.getTypedElement((String JavaDoc) me.getValue());
595                     //find the pk column
596
RdbPrimitiveElementMapping pem = getPEMOfField(
597                         tsc, cm.getProjectName(), cm.getMapperName(),
598                         (String JavaDoc) tclassndproj.get(me.getKey()));
599                     //find the fk column name
600
String JavaDoc colname = (String JavaDoc) pk2fk.get(pem.getName());
601                     //check if the fk column name is already used
602
PrimitiveElementMapping pem2 =
603                             table.getPrimitiveElementMappingByCol(colname);
604                     if (pem2 == null) {
605                         // create it
606
if (colname == null) {
607                             throw new SpeedoException("No column name defined for a foreign key: "
608                                 + "\n\tfield name=" + pe.getName()
609                                 + "\n\tpk column name=" + pem.getName());
610                         }
611                         table.createPrimitiveElementMapping(pe, colname, pem.getType(), false);
612                     } else {
613                         //it exists then assign the real primitive element to the
614
// the name def
615
((Class JavaDoc) pe.getParent()).removeTypedElement(pe.getName());
616                         pe = (PrimitiveElement) pem2.getLinkedMO();
617                         me.setValue(pe.getName());
618                     }
619                 }
620             }
621         }
622     }
623
624     private RdbPrimitiveElementMapping getPEMOfField(SpeedoClass tsc,
625                                       String JavaDoc projectName,
626                                       String JavaDoc mapperName,
627                                       String JavaDoc fieldName) throws PException {
628         RdbClassMultiMapping trcm = (RdbClassMultiMapping)
629             tsc.jormclass.getClassProject(projectName)
630             .getMapping(mapperName).getClassMapping();
631         RdbPrimitiveElementMapping pem = (RdbPrimitiveElementMapping)
632             trcm.getPrimitiveElementMapping(fieldName, true);
633         if (pem == null) {
634             if (tsc.superClassName == null) {
635                 throw new PException("No mapping found for the field '"
636                     + fieldName + "' for the class '" + tsc.getFQName() + "'.");
637
638             } else {
639                 //the mapping of this field is inherited from parent
640
return getPEMOfField(
641                     tsc.getSpeedoClassFromContext(tsc.superClassName),
642                     projectName, mapperName, fieldName);
643             }
644         } else {
645             return pem;
646         }
647     }
648
649
650     /**
651      * Mappes the identifier of a GenClassRef over sql columns. In according
652      * to the speedo extensions a join table is used (default case) or not.
653      *
654      * The columms match to the foreign key of the souce class. The default
655      * column names of the join table are the name of the hidden field of the
656      * genclass.
657      *
658      * @param sc is the SpeedoClass hosting the reference
659      * @param nd is the name def of the gen class identifier
660      * @param sc is the Speedo meta object hosting the field which references
661      * the generic class.
662      * @param rgcm is the jorm meta object representing the mapping of the gen
663      * class.
664      * @throws org.objectweb.jorm.api.PException
665      */

666     private void creaGenClassRefIdNameDef(NameDef nd,
667                                      SpeedoClass sc,
668                                      RdbGenClassMapping rgcm)
669             throws PException {
670         MetaObject mo = nd.getParent();
671         RdbTable table = rgcm.getRdbTable();
672         GenClassRef gcr = (GenClassRef) mo;
673         SpeedoField sf = (SpeedoField) sc.jdoField.get(gcr.getName());
674         RdbClassMultiMapping srcm = (RdbClassMultiMapping)
675                 ((Class JavaDoc) gcr.getParent())
676                 .getClassProject(rgcm.getProjectName())
677                 .getMapping(rgcm.getMapperName()).getClassMapping();
678         NameDef sclassnd = (NameDef) srcm.getIdentifierMapping().getLinkedMO();
679         SpeedoExtension se = sf.getExtension(VENDOR_NAME, SOURCE_FK);
680         Map pk2fk = (se == null
681                 ? null // default mapping
682
: getPk2Fk(se.value));
683         if (nd.isFieldName()) {
684             PrimitiveElement pe = gcr.getHiddenField(nd.getFieldName());
685             String JavaDoc colname = null;
686             if (pk2fk != null) {
687                 RdbPrimitiveElementMapping pem = (RdbPrimitiveElementMapping)
688                         srcm.getPrimitiveElementMapping(sclassnd.getFieldName(), true);
689                 colname = (String JavaDoc) pk2fk.get(pem.getName());
690                 if (colname == null) {
691                     logger.log(BasicLevel.WARN, "No " + SOURCE_FK
692                         + " defined for the primary column " + pem.getName()
693                         + " of the field " + gcr.getName()
694                         + " of the class " + sc.getFQName()
695                         + ", use the default mapping");
696                 }
697             }
698             if (colname == null) {
699                 // default mapping
700
colname = pe.getName();
701             }
702             //check if the column name is already used
703
PrimitiveElementMapping pem2 =
704                     table.getPrimitiveElementMappingByCol(colname);
705             if (pem2 == null) {
706                 // create it
707
table.createPrimitiveElementMapping(pe, colname);
708             } else {
709                 //it exists then assign the real primitive element to the
710
// the name def
711
((GenClassRef) pe.getParent()).removeTypedElement(pe.getName());
712                 pe = (PrimitiveElement) pem2.getLinkedMO();
713                 nd.setFieldName(pe.getName());
714             }
715         } else {
716             Map sclassndproj = sclassnd.getNameRef().getProjection();
717             Iterator JavaDoc it = nd.getNameRef().getProjection().entrySet().iterator();
718             while (it.hasNext()) {
719                 Map.Entry me = (Map.Entry) it.next();
720                 PrimitiveElement pe =
721                         gcr.getHiddenField((String JavaDoc) me.getValue());
722                 String JavaDoc colname = null;
723                 if (pk2fk != null) {
724                     RdbPrimitiveElementMapping pem = (RdbPrimitiveElementMapping)
725                             srcm.getPrimitiveElementMapping(
726                                     (String JavaDoc) sclassndproj.get(me.getKey()), true);
727                     colname = (String JavaDoc) pk2fk.get(pem.getName());
728                     if (colname == null) {
729                         logger.log(BasicLevel.WARN, "No " + SOURCE_FK
730                             + " defined for the primary column " + pem.getName()
731                             + " of the field " + gcr.getName()
732                             + " of the class " + sc.getFQName()
733                             + ", use the default mapping");
734                     }
735                 }
736                 if (colname == null) {
737                     // default mapping
738
colname = pe.getName();
739                 }
740                 //check if the column name is already used
741
PrimitiveElementMapping pem2 =
742                         table.getPrimitiveElementMappingByCol(colname);
743                 if (pem2 == null) {
744                     // create it
745
table.createPrimitiveElementMapping(pe, colname);
746                 } else {
747                     //it exists then assign the real primitive element to the
748
// the name def
749
((GenClassRef) pe.getParent()).removeTypedElement(pe.getName());
750                     pe = (PrimitiveElement) pem2.getLinkedMO();
751                     me.setValue(pe.getName());
752                 }
753             }
754         }
755     }
756
757
758     /**
759      * Mappes the element of a GenClassRef over sql columns. In according
760      * to the speedo extensions a join table is used (default case) or not.
761      *
762      * The element of the gen class is a Gen class (not supported) or
763      * a classRef. In all case the parent of this element is the GenClassRef
764      *
765      * @param sc is the SpeedoClass hosting the reference
766      * @param nd is the name def of the gen class element
767      * @param sc is the Speedo meta object hosting the field which references
768      * the generic class.
769      * @param rgcm is the jorm meta object representing the mapping of the gen
770      * class.
771      * @throws org.objectweb.jorm.api.PException
772      */

773     private void creaGenClassRefRefNameDef(NameDef nd,
774                                      SpeedoClass sc,
775                                      RdbGenClassMapping rgcm)
776             throws PException {
777         MetaObject mo = nd.getParent();
778         RdbTable table = rgcm.getRdbTable();
779         GenClassRef gcr = (GenClassRef) mo.getParent();
780         ClassRef cr = (ClassRef) mo;
781         SpeedoField sf = (SpeedoField) sc.jdoField.get(gcr.getName());
782         SpeedoClass tsc = sc.getSpeedoClassFromContext(cr.getMOClass().getFQName());
783         RdbClassMultiMapping trcm = (RdbClassMultiMapping)
784                 cr.getMOClass().getClassProject(rgcm.getProjectName())
785                 .getMapping(rgcm.getMapperName()).getClassMapping();
786         NameDef tclassnd = (NameDef) trcm.getIdentifierMapping().getLinkedMO();
787         if (isColocatedGCTable(sf)) {
788             //The columms match to the primary key of the target class
789
if (nd.isFieldName()) {
790                 PrimitiveElement pe = gcr.getHiddenField(nd.getFieldName());
791                 RdbPrimitiveElementMapping pem = getPEMOfField(tsc,
792                     rgcm.getProjectName(),
793                     rgcm.getMapperName(),
794                     tclassnd.getFieldName());
795                 //We must use the same column name
796
table.createPrimitiveElementMapping(pe, pem.getName());
797             } else {
798                 Map tclassndproj = tclassnd.getNameRef().getProjection();
799                 Iterator JavaDoc it = nd.getNameRef().getProjection().entrySet().iterator();
800                 while (it.hasNext()) {
801                     Map.Entry me = (Map.Entry) it.next();
802                     PrimitiveElement pe =
803                             gcr.getHiddenField((String JavaDoc) me.getValue());
804                     RdbPrimitiveElementMapping pem = getPEMOfField(tsc,
805                         rgcm.getProjectName(),
806                         rgcm.getMapperName(),
807                         (String JavaDoc) tclassndproj.get(me.getKey()));
808                     //We must use the same column name
809
table.createPrimitiveElementMapping(pe, pem.getName());
810                 }
811             }
812         } else {
813             //The columns are foreign key of the primary key of the
814
// target class.
815
SpeedoExtension se = sf.getExtension(VENDOR_NAME, TARGET_FK);
816             Map pk2fk = (se == null
817                     ? null // default mapping
818
: getPk2Fk(se.value));
819             if (nd.isFieldName()) {
820                 PrimitiveElement pe =
821                         gcr.getHiddenField(nd.getFieldName());
822                 String JavaDoc colname;
823                 if (pk2fk == null) {
824                     // default mapping
825
colname = pe.getName();
826                 } else {
827                     RdbPrimitiveElementMapping pem = getPEMOfField(tsc,
828                         rgcm.getProjectName(),
829                         rgcm.getMapperName(),
830                         tclassnd.getFieldName());
831                     colname = (String JavaDoc) pk2fk.get(pem.getName());
832                 }
833                 table.createPrimitiveElementMapping(pe, colname);
834             } else {
835                 Map tclassndproj = tclassnd.getNameRef().getProjection();
836                 Iterator JavaDoc it = nd.getNameRef().getProjection().entrySet().iterator();
837                 while (it.hasNext()) {
838                     Map.Entry me = (Map.Entry) it.next();
839                     PrimitiveElement pe =
840                             gcr.getHiddenField((String JavaDoc) me.getValue());
841                     String JavaDoc colname;
842                     if (pk2fk == null) {
843                         // default mapping
844
colname = pe.getName();
845                     } else {
846                         RdbPrimitiveElementMapping pem = getPEMOfField(tsc,
847                             rgcm.getProjectName(),
848                             rgcm.getMapperName(),
849                             (String JavaDoc) tclassndproj.get(me.getKey()));
850                         colname = (String JavaDoc) pk2fk.get(pem.getName());
851                     }
852                     table.createPrimitiveElementMapping(pe, colname);
853                 }
854             }
855         }
856     }
857
858     /**
859      * Calculates the main table name of a Class. First it looks in the meta
860      * information to find if it is not already defined. If it is not defined
861      * then the table name is built with the class name (not fully qualified).
862      */

863     private String JavaDoc getTableName(SpeedoClass sc) throws SpeedoException {
864         SpeedoExtension se = sc.getExtensionByKey(SQL_NAME);
865         if (se != null) {
866             return se.value;
867         }
868         if (sc.superClassName != null) {
869             se = sc.getExtensionByKey(INHERITANCE_MAPPING);
870             if (se == null) {
871                 throw new SpeedoException("No inheritance mapping defined for the class "
872                         + sc.getFQName() + " in the jdo file "
873                         + sc.getJDOFileName());
874             }
875             if (INHERITANCE_FILTERED_MAPPING.equals(se.value)) {
876                 return getTableName(sc.getSpeedoClassFromContext(sc.superClassName));
877             }
878         }
879
880         return sc.name;
881     }
882
883     private String JavaDoc getTableName(GenClassRef gcr) {
884         String JavaDoc t = gcr.getGenClassId();
885         int idx = t.lastIndexOf('.');
886         if (idx != -1) {
887             t = t.substring(idx + 1);
888         }
889         return t.replace(JormPathHelper.SEP, '_');
890     }
891
892     private String JavaDoc getColumnName(PrimitiveElement pe) {
893         String JavaDoc c = pe.getName();
894         int idx = c.lastIndexOf('.');
895         if (idx != -1) {
896             c = c.substring(idx +1);
897         }
898         return c;
899     }
900
901     private Map getPk2Fk(String JavaDoc fks) {
902         Map res = new HashMap JavaDoc();
903         StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(fks, "=,:;/", false);
904         String JavaDoc pk = null;
905         while(st.hasMoreTokens()) {
906             String JavaDoc tok = st.nextToken();
907             tok = tok.trim();
908             if (pk == null) {
909                 pk = tok;
910             } else {
911                 res.put(pk, tok);
912                 pk = null;
913             }
914         }
915         return res;
916     }
917
918     private Manager getManager(MetaObject mo) {
919         MetaObject m = mo;
920         while(m != null && !(m instanceof Manager)) {
921             m = m.getParent();
922         }
923         return (Manager) m;
924     }
925
926     private boolean isColocatedGCTable(SpeedoField sf) {
927         return sf.getExtension(VENDOR_NAME, JOIN_TABLE) == null
928                 && sf.getExtension(VENDOR_NAME, TARGET_FK) == null
929                 && sf.getExtension(VENDOR_NAME, SOURCE_FK) != null;
930     }
931 }
932
Popular Tags