KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectstyle > cayenne > wocompat > EOModelProcessor


1 /* ====================================================================
2  *
3  * The ObjectStyle Group Software License, version 1.1
4  * ObjectStyle Group - http://objectstyle.org/
5  *
6  * Copyright (c) 2002-2005, Andrei (Andrus) Adamchik and individual authors
7  * of the software. All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  *
16  * 2. Redistributions in binary form must reproduce the above copyright
17  * notice, this list of conditions and the following disclaimer in
18  * the documentation and/or other materials provided with the
19  * distribution.
20  *
21  * 3. The end-user documentation included with the redistribution, if any,
22  * must include the following acknowlegement:
23  * "This product includes software developed by independent contributors
24  * and hosted on ObjectStyle Group web site (http://objectstyle.org/)."
25  * Alternately, this acknowlegement may appear in the software itself,
26  * if and wherever such third-party acknowlegements normally appear.
27  *
28  * 4. The names "ObjectStyle Group" and "Cayenne" must not be used to endorse
29  * or promote products derived from this software without prior written
30  * permission. For written permission, email
31  * "andrus at objectstyle dot org".
32  *
33  * 5. Products derived from this software may not be called "ObjectStyle"
34  * or "Cayenne", nor may "ObjectStyle" or "Cayenne" appear in their
35  * names without prior written permission.
36  *
37  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40  * DISCLAIMED. IN NO EVENT SHALL THE OBJECTSTYLE GROUP OR
41  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
44  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
46  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
47  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48  * SUCH DAMAGE.
49  * ====================================================================
50  *
51  * This software consists of voluntary contributions made by many
52  * individuals and hosted on ObjectStyle Group web site. For more
53  * information on the ObjectStyle Group, please see
54  * <http://objectstyle.org/>.
55  */

56
57 package org.objectstyle.cayenne.wocompat;
58
59 import java.io.FileNotFoundException JavaDoc;
60 import java.io.InputStream JavaDoc;
61 import java.net.URL JavaDoc;
62 import java.util.ArrayList JavaDoc;
63 import java.util.Collection JavaDoc;
64 import java.util.Collections JavaDoc;
65 import java.util.Comparator JavaDoc;
66 import java.util.Iterator JavaDoc;
67 import java.util.List JavaDoc;
68 import java.util.Map JavaDoc;
69
70 import org.apache.commons.collections.CollectionUtils;
71 import org.apache.commons.collections.Predicate;
72 import org.apache.commons.collections.PredicateUtils;
73 import org.objectstyle.cayenne.CayenneRuntimeException;
74 import org.objectstyle.cayenne.dba.TypesMapping;
75 import org.objectstyle.cayenne.exp.Expression;
76 import org.objectstyle.cayenne.exp.parser.ASTDbPath;
77 import org.objectstyle.cayenne.map.DataMap;
78 import org.objectstyle.cayenne.map.DbEntity;
79 import org.objectstyle.cayenne.map.DbJoin;
80 import org.objectstyle.cayenne.map.DbRelationship;
81 import org.objectstyle.cayenne.map.ObjEntity;
82 import org.objectstyle.cayenne.map.ObjRelationship;
83 import org.objectstyle.cayenne.project.NamedObjectFactory;
84 import org.objectstyle.cayenne.query.Query;
85 import org.objectstyle.cayenne.util.ResourceLocator;
86 import org.objectstyle.cayenne.wocompat.parser.Parser;
87
88 /**
89  * Class for converting stored Apple EOModel mapping files to Cayenne DataMaps.
90  */

91 public class EOModelProcessor {
92
93     protected Predicate prototypeChecker;
94
95     public EOModelProcessor() {
96         prototypeChecker = new Predicate() {
97
98             public boolean evaluate(Object JavaDoc object) {
99                 if (object == null) {
100                     return false;
101                 }
102
103                 String JavaDoc entityName = object.toString();
104
105                 return entityName.startsWith("EO") && entityName.endsWith("Prototypes");
106             }
107         };
108     }
109
110     /**
111      * Returns index.eomodeld contents as a Map.
112      *
113      * @since 1.1
114      */

115     // TODO: refactor EOModelHelper to provide a similar method without loading
116
// all entity files in memory... here we simply copied stuff from EOModelHelper
117
public Map JavaDoc loadModeIndex(String JavaDoc path) throws Exception JavaDoc {
118
119         ResourceLocator locator = new ResourceLocator();
120         locator.setSkipClasspath(false);
121         locator.setSkipCurrentDirectory(false);
122         locator.setSkipHomeDirectory(true);
123         locator.setSkipAbsolutePath(false);
124
125         if (!path.endsWith(".eomodeld")) {
126             path += ".eomodeld";
127         }
128
129         URL JavaDoc base = locator.findDirectoryResource(path);
130         if (base == null) {
131             throw new FileNotFoundException JavaDoc("Can't find EOModel: " + path);
132         }
133
134         Parser plistParser = new Parser();
135         InputStream JavaDoc in = new URL JavaDoc(base, "index.eomodeld").openStream();
136
137         try {
138             plistParser.ReInit(in);
139             return (Map JavaDoc) plistParser.propertyList();
140         }
141         finally {
142             in.close();
143         }
144     }
145
146     /**
147      * Performs EOModel loading.
148      *
149      * @param path A path to ".eomodeld" directory. If path doesn't end with ".eomodeld",
150      * ".eomodeld" suffix is automatically assumed.
151      */

152     public DataMap loadEOModel(String JavaDoc path) throws Exception JavaDoc {
153         return loadEOModel(path, false);
154     }
155
156     /**
157      * Performs EOModel loading.
158      *
159      * @param path A path to ".eomodeld" directory. If path doesn't end with ".eomodeld",
160      * ".eomodeld" suffix is automatically assumed.
161      * @param generateClientClass if true then loading of EOModel is java client classes
162      * aware and the following processing will work with Java client class
163      * settings of the EOModel.
164      */

165     public DataMap loadEOModel(String JavaDoc path, boolean generateClientClass) throws Exception JavaDoc {
166         EOModelHelper helper = makeHelper(path, generateClientClass);
167
168         // create empty map
169
DataMap dataMap = helper.getDataMap();
170
171         // process enitities ... throw out prototypes ... for now
172
List JavaDoc modelNames = new ArrayList JavaDoc(helper.modelNamesAsList());
173         CollectionUtils.filter(modelNames, PredicateUtils.notPredicate(prototypeChecker));
174
175         Iterator JavaDoc it = modelNames.iterator();
176         while (it.hasNext()) {
177             String JavaDoc name = (String JavaDoc) it.next();
178
179             // create and register entity
180
makeEntity(helper, name, generateClientClass);
181         }
182
183         // now sort following inheritance hierarchy
184
Collections.sort(modelNames, new InheritanceComparator(dataMap));
185
186         // after all entities are loaded, process attributes
187
it = modelNames.iterator();
188         while (it.hasNext()) {
189             String JavaDoc name = (String JavaDoc) it.next();
190
191             EOObjEntity e = (EOObjEntity) dataMap.getObjEntity(name);
192             // process entity attributes
193
makeAttributes(helper, e);
194         }
195
196         // after all entities are loaded, process relationships
197
it = modelNames.iterator();
198         while (it.hasNext()) {
199             String JavaDoc name = (String JavaDoc) it.next();
200             makeRelationships(helper, dataMap.getObjEntity(name));
201         }
202
203         // after all normal relationships are loaded, process flattened relationships
204
it = modelNames.iterator();
205         while (it.hasNext()) {
206             String JavaDoc name = (String JavaDoc) it.next();
207             makeFlatRelationships(helper, dataMap.getObjEntity(name));
208         }
209
210         // now create missing reverse DB (but not OBJ) relationships
211
// since Cayenne requires them
212
it = modelNames.iterator();
213         while (it.hasNext()) {
214             String JavaDoc name = (String JavaDoc) it.next();
215             DbEntity dbEntity = dataMap.getObjEntity(name).getDbEntity();
216
217             if (dbEntity != null) {
218                 makeReverseDbRelationships(dbEntity);
219             }
220         }
221
222         // build SelectQueries out of EOFetchSpecifications...
223
it = modelNames.iterator();
224         while (it.hasNext()) {
225             String JavaDoc name = (String JavaDoc) it.next();
226             Iterator JavaDoc queries = helper.queryNames(name);
227             while (queries.hasNext()) {
228                 String JavaDoc queryName = (String JavaDoc) queries.next();
229                 System.out.println("Processing FetchSpecification: " + queryName);
230                 EOObjEntity entity = (EOObjEntity) dataMap.getObjEntity(name);
231                 makeQuery(helper, entity, queryName);
232             }
233         }
234
235         return dataMap;
236     }
237
238     /**
239      * Returns whether an Entity is an EOF EOPrototypes entity. According to EOF
240      * conventions EOPrototypes and EO[Adapter]Prototypes entities are considered to be
241      * prototypes.
242      *
243      * @since 1.1
244      */

245     protected boolean isPrototypesEntity(String JavaDoc entityName) {
246         return prototypeChecker.evaluate(entityName);
247     }
248
249     /**
250      * Creates an returns new EOModelHelper to process EOModel. Exists mostly for the
251      * benefit of subclasses.
252      */

253     protected EOModelHelper makeHelper(String JavaDoc path, boolean genereateClientClass)
254             throws Exception JavaDoc {
255         return new EOModelHelper(path);
256     }
257
258     /**
259      * Creates a Cayenne query out of EOFetchSpecification data.
260      *
261      * @since 1.1
262      */

263     protected Query makeQuery(EOModelHelper helper, EOObjEntity entity, String JavaDoc queryName) {
264
265         DataMap dataMap = helper.getDataMap();
266         Map JavaDoc queryPlist = helper.queryPListMap(entity.getName(), queryName);
267         if (queryPlist == null) {
268             return null;
269         }
270         
271         Query query;
272         if (queryPlist.containsKey("hints")) { // just a predefined SQL query
273
query = new EOSQLQuery(entity, queryPlist);
274         } else {
275                 query = new EOQuery(entity, queryPlist);
276         }
277         query.setName(entity.qualifiedQueryName(queryName));
278         dataMap.addQuery(query);
279         
280         return query;
281     }
282
283     /**
284      * Creates and returns a new ObjEntity linked to a corresponding DbEntity.
285      */

286     protected EOObjEntity makeEntity(
287             EOModelHelper helper,
288             String JavaDoc name,
289             boolean generateClientClass) {
290
291         DataMap dataMap = helper.getDataMap();
292         Map JavaDoc entityPlist = helper.entityPListMap(name);
293
294         // create ObjEntity
295
EOObjEntity objEntity = new EOObjEntity(name);
296         objEntity.setIsClientEntity(generateClientClass);
297         String JavaDoc parent = (String JavaDoc) entityPlist.get("parent");
298         objEntity.setClassName(helper.entityClass(name, generateClientClass));
299
300         if (parent != null) {
301             objEntity.setHasSuperClass(true);
302             objEntity.setSuperClassName(helper.entityClass(parent, generateClientClass));
303         }
304
305         // add flag whether this entity is set as abstract in the model
306
objEntity.setIsAbstractEntity("Y".equals(entityPlist.get("isAbstractEntity")));
307
308         // create DbEntity...since EOF allows the same table to be
309
// associated with multiple EOEntities, check for name duplicates
310
String JavaDoc dbEntityName = (String JavaDoc) entityPlist.get("externalName");
311         if (dbEntityName != null) {
312
313             // ... if inheritance is involved and parent hierarchy uses the same DBEntity,
314
// do not create a DbEntity...
315
boolean createDbEntity = true;
316             if (parent != null) {
317                 String JavaDoc parentName = parent;
318                 while (parentName != null) {
319                     Map JavaDoc parentData = helper.entityPListMap(parentName);
320                     if (parentData == null) {
321                         break;
322                     }
323
324                     String JavaDoc parentExternalName = (String JavaDoc) parentData.get("externalName");
325                     if (parentExternalName == null) {
326                         parentName = (String JavaDoc) parentData.get("parent");
327                         continue;
328                     }
329
330                     if (dbEntityName.equals(parentExternalName)) {
331                         createDbEntity = false;
332                     }
333
334                     break;
335                 }
336             }
337
338             if (createDbEntity) {
339                 int i = 0;
340                 String JavaDoc dbEntityBaseName = dbEntityName;
341                 while (dataMap.getDbEntity(dbEntityName) != null) {
342                     dbEntityName = dbEntityBaseName + i++;
343                 }
344
345                 objEntity.setDbEntityName(dbEntityName);
346                 DbEntity de = new DbEntity(dbEntityName);
347                 dataMap.addDbEntity(de);
348             }
349         }
350
351         // set various flags
352
objEntity.setReadOnly("Y".equals(entityPlist.get("isReadOnly")));
353         objEntity.setSuperEntityName((String JavaDoc) entityPlist.get("parent"));
354
355         dataMap.addObjEntity(objEntity);
356
357         return objEntity;
358     }
359
360     /**
361      * Create ObjAttributes of the specified entity, as well as DbAttributes of the
362      * corresponding DbEntity.
363      */

364     protected void makeAttributes(EOModelHelper helper, EOObjEntity objEntity) {
365         Map JavaDoc entityPlistMap = helper.entityPListMap(objEntity.getName());
366         List JavaDoc primaryKeys = (List JavaDoc) entityPlistMap.get("primaryKeyAttributes");
367
368         List JavaDoc classProperties;
369         if (objEntity.getIsClientEntity()) {
370             classProperties = (List JavaDoc) entityPlistMap.get("clientClassProperties");
371         }
372         else {
373             classProperties = (List JavaDoc) entityPlistMap.get("classProperties");
374         }
375
376         List JavaDoc attributes = (List JavaDoc) entityPlistMap.get("attributes");
377         DbEntity dbEntity = objEntity.getDbEntity();
378
379         if (primaryKeys == null) {
380             primaryKeys = Collections.EMPTY_LIST;
381         }
382
383         if (classProperties == null) {
384             classProperties = Collections.EMPTY_LIST;
385         }
386
387         if (attributes == null) {
388             attributes = Collections.EMPTY_LIST;
389         }
390
391         // detect single table inheritance
392
boolean singleTableInheritance = false;
393         String JavaDoc parentName = (String JavaDoc) entityPlistMap.get("parent");
394         while (parentName != null) {
395             Map JavaDoc parentData = helper.entityPListMap(parentName);
396             if (parentData == null) {
397                 break;
398             }
399
400             String JavaDoc parentExternalName = (String JavaDoc) parentData.get("externalName");
401             if (parentExternalName == null) {
402                 parentName = (String JavaDoc) parentData.get("parent");
403                 continue;
404             }
405
406             if (dbEntity.getName() != null
407                     && dbEntity.getName().equals(parentExternalName)) {
408                 singleTableInheritance = true;
409             }
410
411             break;
412         }
413
414         Iterator JavaDoc it = attributes.iterator();
415         while (it.hasNext()) {
416             Map JavaDoc attrMap = (Map JavaDoc) it.next();
417
418             String JavaDoc prototypeName = (String JavaDoc) attrMap.get("prototypeName");
419             Map JavaDoc prototypeAttrMap = helper.getPrototypeAttributeMapFor(prototypeName);
420
421             String JavaDoc dbAttrName = (String JavaDoc) attrMap.get("columnName");
422             if (null == dbAttrName) {
423                 dbAttrName = (String JavaDoc) prototypeAttrMap.get("columnName");
424             }
425
426             String JavaDoc attrName = (String JavaDoc) attrMap.get("name");
427             if (null == attrName) {
428                 attrName = (String JavaDoc) prototypeAttrMap.get("name");
429             }
430
431             String JavaDoc attrType = (String JavaDoc) attrMap.get("valueClassName");
432             if (null == attrType) {
433                 attrType = (String JavaDoc) prototypeAttrMap.get("valueClassName");
434             }
435
436             String JavaDoc valueType = (String JavaDoc) attrMap.get("valueType");
437             if (valueType == null) {
438                 valueType = (String JavaDoc) prototypeAttrMap.get("valueType");
439             }
440
441             String JavaDoc javaType = helper.javaTypeForEOModelerType(attrType, valueType);
442             EODbAttribute dbAttr = null;
443
444             if (dbAttrName != null && dbEntity != null) {
445
446                 // if inherited attribute, skip it for DbEntity...
447
if (!singleTableInheritance || dbEntity.getAttribute(dbAttrName) == null) {
448
449                     // create DbAttribute...since EOF allows the same column name for
450
// more than one Java attribute, we need to check for name duplicates
451
int i = 0;
452                     String JavaDoc dbAttributeBaseName = dbAttrName;
453                     while (dbEntity.getAttribute(dbAttrName) != null) {
454                         dbAttrName = dbAttributeBaseName + i++;
455                     }
456
457                     dbAttr = new EODbAttribute(dbAttrName, TypesMapping
458                             .getSqlTypeByJava(javaType), dbEntity);
459                     dbAttr.setEoAttributeName(attrName);
460                     dbEntity.addAttribute(dbAttr);
461
462                     Integer JavaDoc width = (Integer JavaDoc) attrMap.get("width");
463                     if (null == width)
464                         width = (Integer JavaDoc) prototypeAttrMap.get("width");
465
466                     if (width != null)
467                         dbAttr.setMaxLength(width.intValue());
468
469                     Integer JavaDoc scale = (Integer JavaDoc) attrMap.get("scale");
470                     if (null == scale)
471                         scale = (Integer JavaDoc) prototypeAttrMap.get("scale");
472
473                     if (scale != null)
474                         dbAttr.setPrecision(scale.intValue());
475
476                     if (primaryKeys.contains(attrName))
477                         dbAttr.setPrimaryKey(true);
478
479                     Object JavaDoc allowsNull = attrMap.get("allowsNull");
480                     // TODO: Unclear that allowsNull should be inherited from EOPrototypes
481
// if (null == allowsNull) allowsNull =
482
// prototypeAttrMap.get("allowsNull");;
483

484                     dbAttr.setMandatory(!"Y".equals(allowsNull));
485                 }
486             }
487
488             if (classProperties.contains(attrName)) {
489                 EOObjAttribute attr = new EOObjAttribute(attrName, javaType, objEntity);
490
491                 // set readOnly flag of Attribute if either attribute is read or
492
// if entity is readOnly
493
String JavaDoc entityReadOnlyString = (String JavaDoc) entityPlistMap.get("isReadOnly");
494                 String JavaDoc attributeReadOnlyString = (String JavaDoc) attrMap.get("isReadOnly");
495                 if ("Y".equals(entityReadOnlyString)
496                         || "Y".equals(attributeReadOnlyString)) {
497                     attr.setReadOnly(true);
498                 }
499
500                 // set name instead of the actual attribute, as it may be inherited....
501
attr.setDbAttributeName(dbAttrName);
502                 objEntity.addAttribute(attr);
503             }
504         }
505     }
506
507     /**
508      * Create ObjRelationships of the specified entity, as well as DbRelationships of the
509      * corresponding DbEntity.
510      */

511     protected void makeRelationships(EOModelHelper helper, ObjEntity objEntity) {
512         Map JavaDoc entityPlistMap = helper.entityPListMap(objEntity.getName());
513         List JavaDoc classProps = (List JavaDoc) entityPlistMap.get("classProperties");
514         List JavaDoc rinfo = (List JavaDoc) entityPlistMap.get("relationships");
515
516         Collection JavaDoc attributes = (Collection JavaDoc) entityPlistMap.get("attributes");
517
518         if (rinfo == null) {
519             return;
520         }
521
522         if (classProps == null) {
523             classProps = Collections.EMPTY_LIST;
524         }
525
526         if (attributes == null) {
527             attributes = Collections.EMPTY_LIST;
528         }
529
530         DbEntity dbSrc = objEntity.getDbEntity();
531         Iterator JavaDoc it = rinfo.iterator();
532         while (it.hasNext()) {
533             Map JavaDoc relMap = (Map JavaDoc) it.next();
534             String JavaDoc targetName = (String JavaDoc) relMap.get("destination");
535
536             // ignore flattened relationships for now
537
if (targetName == null) {
538                 continue;
539             }
540
541             String JavaDoc relName = (String JavaDoc) relMap.get("name");
542             boolean toMany = "Y".equals(relMap.get("isToMany"));
543             boolean toDependentPK = "Y".equals(relMap.get("propagatesPrimaryKey"));
544             ObjEntity target = helper.getDataMap().getObjEntity(targetName);
545
546             // target maybe null for cross-EOModel relationships
547
// ignoring those now.
548
if (target == null) {
549                 continue;
550             }
551
552             DbEntity dbTarget = target.getDbEntity();
553             Map JavaDoc targetPlistMap = helper.entityPListMap(targetName);
554             Collection JavaDoc targetAttributes = (Collection JavaDoc) targetPlistMap.get("attributes");
555             DbRelationship dbRel = null;
556
557             // process underlying DbRelationship
558
// Note: there is no flattened rel. support here....
559
// Note: source maybe null, e.g. an abstract entity.
560
if (dbSrc != null && dbTarget != null) {
561
562                 // in case of inheritance EOF stores duplicates of all inherited
563
// relationships, so we must skip this relationship in DB entity if it is
564
// already there...
565

566                 dbRel = (DbRelationship) dbSrc.getRelationship(relName);
567                 if (dbRel == null) {
568
569                     dbRel = new DbRelationship();
570                     dbRel.setSourceEntity(dbSrc);
571                     dbRel.setTargetEntity(dbTarget);
572                     dbRel.setToMany(toMany);
573                     dbRel.setName(relName);
574                     dbRel.setToDependentPK(toDependentPK);
575                     dbSrc.addRelationship(dbRel);
576
577                     List JavaDoc joins = (List JavaDoc) relMap.get("joins");
578                     Iterator JavaDoc jIt = joins.iterator();
579                     while (jIt.hasNext()) {
580                         Map JavaDoc joinMap = (Map JavaDoc) jIt.next();
581
582                         DbJoin join = new DbJoin(dbRel);
583
584                         // find source attribute dictionary and extract the column name
585
String JavaDoc sourceAttributeName = (String JavaDoc) joinMap
586                                 .get("sourceAttribute");
587                         join.setSourceName(columnName(attributes, sourceAttributeName));
588
589                         String JavaDoc targetAttributeName = (String JavaDoc) joinMap
590                                 .get("destinationAttribute");
591
592                         join.setTargetName(columnName(
593                                 targetAttributes,
594                                 targetAttributeName));
595                         dbRel.addJoin(join);
596                     }
597                 }
598             }
599
600             // only create obj relationship if it is a class property
601
if (classProps.contains(relName)) {
602                 ObjRelationship rel = new ObjRelationship();
603                 rel.setName(relName);
604                 rel.setSourceEntity(objEntity);
605                 rel.setTargetEntity(target);
606                 objEntity.addRelationship(rel);
607
608                 if (dbRel != null) {
609                     rel.addDbRelationship(dbRel);
610                 }
611             }
612         }
613     }
614
615     /**
616      * Create reverse DbRelationships that were not created so far, since Cayenne requires
617      * them.
618      *
619      * @since 1.0.5
620      */

621     protected void makeReverseDbRelationships(DbEntity dbEntity) {
622         if (dbEntity == null) {
623             throw new NullPointerException JavaDoc(
624                     "Attempt to create reverse relationships for the null DbEntity.");
625         }
626
627         // iterate over a copy of the collection, since in case of
628
// reflexive relationships, we may modify source entity relationship map
629
Collection JavaDoc clone = new ArrayList JavaDoc(dbEntity.getRelationships());
630         Iterator JavaDoc it = clone.iterator();
631         while (it.hasNext()) {
632             DbRelationship relationship = (DbRelationship) it.next();
633
634             if (relationship.getReverseRelationship() == null) {
635                 DbRelationship reverse = relationship.createReverseRelationship();
636
637                 String JavaDoc name = NamedObjectFactory.createName(DbRelationship.class, reverse
638                         .getSourceEntity(), relationship.getName() + "Reverse");
639                 reverse.setName(name);
640                 relationship.getTargetEntity().addRelationship(reverse);
641             }
642         }
643     }
644
645     /**
646      * Create Flattened ObjRelationships of the specified entity.
647      */

648     protected void makeFlatRelationships(EOModelHelper helper, ObjEntity e) {
649         Map JavaDoc info = helper.entityPListMap(e.getName());
650         List JavaDoc rinfo = (List JavaDoc) info.get("relationships");
651         if (rinfo == null) {
652             return;
653         }
654
655         Iterator JavaDoc it = rinfo.iterator();
656         while (it.hasNext()) {
657             Map JavaDoc relMap = (Map JavaDoc) it.next();
658             String JavaDoc targetPath = (String JavaDoc) relMap.get("definition");
659
660             // ignore normal relationships
661
if (targetPath == null) {
662                 continue;
663             }
664
665             ObjRelationship flatRel = new ObjRelationship();
666             flatRel.setName((String JavaDoc) relMap.get("name"));
667             flatRel.setSourceEntity(e);
668             e.addRelationship(flatRel);
669
670             DbEntity dbEntity = e.getDbEntity();
671             if (dbEntity == null) {
672                 // not ready to handle inheritance from abstract entities...
673
continue;
674             }
675
676             // determine DB relationship mapping...
677
Expression exp = new ASTDbPath(targetPath);
678             Iterator JavaDoc path = dbEntity.resolvePathComponents(exp);
679
680             DbRelationship firstRel = null;
681             DbRelationship lastRel = null;
682             while (path.hasNext()) {
683                 lastRel = (DbRelationship) path.next();
684                 flatRel.addDbRelationship(lastRel);
685
686                 if (firstRel == null) {
687                     firstRel = lastRel;
688                 }
689             }
690
691             if ((firstRel != null) && (lastRel != null)) {
692                 Collection JavaDoc potentialTargets = e.getDataMap().getMappedEntities(
693                         (DbEntity) lastRel.getTargetEntity());
694
695                 // sanity check
696
if (potentialTargets.size() != 1) {
697                     throw new CayenneRuntimeException(
698                             "One and only one entity should be mapped"
699                                     + " to "
700                                     + lastRel.getTargetEntity().getName()
701                                     + ". Instead found : "
702                                     + potentialTargets.size());
703                 }
704
705                 flatRel.setTargetEntity((ObjEntity) potentialTargets.iterator().next());
706             }
707             else {
708                 throw new CayenneRuntimeException("relationship in the path was null!");
709             }
710         }
711
712     }
713
714     /**
715      * Locates an attribute map matching the name and returns column name for this
716      * attribute.
717      *
718      * @since 1.1
719      */

720     String JavaDoc columnName(Collection JavaDoc entityAttributes, String JavaDoc attributeName) {
721         if (attributeName == null) {
722             return null;
723         }
724
725         Iterator JavaDoc it = entityAttributes.iterator();
726         while (it.hasNext()) {
727             Map JavaDoc map = (Map JavaDoc) it.next();
728             if (attributeName.equals(map.get("name"))) {
729                 return (String JavaDoc) map.get("columnName");
730             }
731         }
732
733         return null;
734     }
735
736     // sorts ObjEntities so that subentities in inheritance hierarchy are shown last
737
final class InheritanceComparator implements Comparator JavaDoc {
738
739         DataMap dataMap;
740
741         InheritanceComparator(DataMap dataMap) {
742             this.dataMap = dataMap;
743         }
744
745         public int compare(Object JavaDoc o1, Object JavaDoc o2) {
746             if (o1 == null) {
747                 return o2 != null ? -1 : 0;
748             }
749             else if (o2 == null) {
750                 return 1;
751             }
752
753             String JavaDoc name1 = o1.toString();
754             String JavaDoc name2 = o2.toString();
755
756             ObjEntity e1 = dataMap.getObjEntity(name1);
757             ObjEntity e2 = dataMap.getObjEntity(name2);
758
759             return compareEntities(e1, e2);
760         }
761
762         int compareEntities(ObjEntity e1, ObjEntity e2) {
763             if (e1 == null) {
764                 return e2 != null ? -1 : 0;
765             }
766             else if (e2 == null) {
767                 return 1;
768             }
769
770             // entity goes first if it is a direct or indirect superentity of another
771
// one
772
if (e1.isSubentityOf(e2)) {
773                 return 1;
774             }
775
776             if (e2.isSubentityOf(e1)) {
777                 return -1;
778             }
779
780             // sort alphabetically
781
return e1.getName().compareTo(e2.getName());
782         }
783     }
784 }
Popular Tags