KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cayenne > util > EntityMergeSupport


1 /*****************************************************************
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  ****************************************************************/

19
20 package org.apache.cayenne.util;
21
22 import java.util.ArrayList JavaDoc;
23 import java.util.Collection JavaDoc;
24 import java.util.Iterator JavaDoc;
25 import java.util.List JavaDoc;
26
27 import org.apache.cayenne.dba.TypesMapping;
28 import org.apache.cayenne.map.DataMap;
29 import org.apache.cayenne.map.DbAttribute;
30 import org.apache.cayenne.map.DbEntity;
31 import org.apache.cayenne.map.DbJoin;
32 import org.apache.cayenne.map.DbRelationship;
33 import org.apache.cayenne.map.Entity;
34 import org.apache.cayenne.map.ObjAttribute;
35 import org.apache.cayenne.map.ObjEntity;
36 import org.apache.cayenne.map.ObjRelationship;
37 import org.apache.cayenne.project.NamedObjectFactory;
38
39 /**
40  * Implements methods for entity merging.
41  *
42  * @author Andrus Adamchik
43  */

44 public class EntityMergeSupport {
45
46     protected DataMap map;
47     protected boolean removeMeaningfulFKs;
48
49     public EntityMergeSupport(DataMap map) {
50         this.map = map;
51         this.removeMeaningfulFKs = true;
52     }
53
54     /**
55      * Updates each one of the collection of ObjEntities, adding attributes and
56      * relationships based on the current state of its DbEntity.
57      *
58      * @since 1.2 changed signature to use Collection instead of List.
59      */

60     public boolean synchronizeWithDbEntities(Collection JavaDoc objEntities) {
61         boolean changed = false;
62         Iterator JavaDoc it = objEntities.iterator();
63         while (it.hasNext()) {
64             if (synchronizeWithDbEntity((ObjEntity) it.next())) {
65                 changed = true;
66             }
67         }
68
69         return changed;
70     }
71
72     /**
73      * Updates ObjEntity attributes and relationships based on the current state of its
74      * DbEntity.
75      *
76      * @return true if the ObjEntity has changed as a result of synchronization.
77      */

78     public boolean synchronizeWithDbEntity(ObjEntity entity) {
79
80         if (entity == null || entity.getDbEntity() == null) {
81             return false;
82         }
83
84         boolean changed = false;
85
86         // synchronization on DataMap is some (weak) protection
87
// against simulteneous modification of the map (like double-clicking on sync
88
// button)
89
synchronized (map) {
90
91             if (removeMeaningfulFKs) {
92
93                 // get rid of attributes that are now src attributes for relationships
94
Iterator JavaDoc rait = getMeaningfulFKs(entity).iterator();
95                 while (rait.hasNext()) {
96                     DbAttribute da = (DbAttribute) rait.next();
97                     ObjAttribute oa = entity.getAttributeForDbAttribute(da);
98                     while (oa != null) {
99                         String JavaDoc attrName = oa.getName();
100                         entity.removeAttribute(attrName);
101                         changed = true;
102                         oa = entity.getAttributeForDbAttribute(da);
103                     }
104                 }
105             }
106
107             List JavaDoc addAttributes = getAttributesToAdd(entity);
108
109             // add missing attributes
110
Iterator JavaDoc ait = addAttributes.iterator();
111             while (ait.hasNext()) {
112                 DbAttribute da = (DbAttribute) ait.next();
113                 String JavaDoc attrName = NameConverter.underscoredToJava(da.getName(), false);
114
115                 // avoid duplicate names
116
attrName = NamedObjectFactory.createName(
117                         ObjAttribute.class,
118                         entity,
119                         attrName);
120
121                 String JavaDoc type = TypesMapping.getJavaBySqlType(da.getType());
122
123                 ObjAttribute oa = new ObjAttribute(attrName, type, entity);
124                 oa.setDbAttribute(da);
125                 entity.addAttribute(oa);
126                 changed = true;
127             }
128
129             List JavaDoc addRelationships = getRelationshipsToAdd(entity);
130
131             // add missing relationships
132
Iterator JavaDoc rit = addRelationships.iterator();
133             while (rit.hasNext()) {
134                 DbRelationship dr = (DbRelationship) rit.next();
135                 DbEntity dbEntity = (DbEntity) dr.getTargetEntity();
136
137                 Iterator JavaDoc targets = map.getMappedEntities(dbEntity).iterator();
138                 if (targets.hasNext()) {
139
140                     Entity mappedTarget = (Entity) targets.next();
141
142                     // avoid duplicate names
143
String JavaDoc relationshipName = NameConverter.underscoredToJava(dr
144                             .getName(), false);
145                     relationshipName = NamedObjectFactory.createName(
146                             ObjRelationship.class,
147                             entity,
148                             relationshipName);
149
150                     ObjRelationship or = new ObjRelationship(relationshipName);
151                     or.addDbRelationship(dr);
152                     or.setSourceEntity(entity);
153                     or.setTargetEntity(mappedTarget);
154                     entity.addRelationship(or);
155                     changed = true;
156                 }
157             }
158         }
159
160         return changed;
161     }
162
163     /**
164      * Returns a list of ObjAttributes that are mapped to foreign keys.
165      *
166      * @since 1.2
167      */

168     public Collection JavaDoc getMeaningfulFKs(ObjEntity objEntity) {
169         List JavaDoc fks = new ArrayList JavaDoc(2);
170         Iterator JavaDoc it = objEntity.getAttributes().iterator();
171         while (it.hasNext()) {
172             ObjAttribute property = (ObjAttribute) it.next();
173             DbAttribute column = property.getDbAttribute();
174
175             // check if adding it makes sense at all
176
if (column != null && column.isForeignKey()) {
177                 fks.add(column);
178             }
179         }
180
181         return fks;
182     }
183
184     /**
185      * Returns a list of attributes that exist in the DbEntity, but are missing from the
186      * ObjEntity.
187      */

188     protected List JavaDoc getAttributesToAdd(ObjEntity objEntity) {
189         List JavaDoc missing = new ArrayList JavaDoc();
190         Iterator JavaDoc it = objEntity.getDbEntity().getAttributes().iterator();
191         Collection JavaDoc rels = objEntity.getDbEntity().getRelationships();
192
193         while (it.hasNext()) {
194             DbAttribute dba = (DbAttribute) it.next();
195             // already there
196
if (objEntity.getAttributeForDbAttribute(dba) != null) {
197                 continue;
198             }
199
200             // check if adding it makes sense at all
201
if (dba.getName() == null || dba.isPrimaryKey()) {
202                 continue;
203             }
204
205             // check FK's
206
boolean isFK = false;
207             Iterator JavaDoc rit = rels.iterator();
208             while (!isFK && rit.hasNext()) {
209                 DbRelationship rel = (DbRelationship) rit.next();
210                 Iterator JavaDoc jit = rel.getJoins().iterator();
211                 while (jit.hasNext()) {
212                     DbJoin join = (DbJoin) jit.next();
213                     if (join.getSource() == dba) {
214                         isFK = true;
215                         break;
216                     }
217                 }
218             }
219
220             if (isFK) {
221                 continue;
222             }
223
224             missing.add(dba);
225         }
226
227         return missing;
228     }
229
230     protected List JavaDoc getRelationshipsToAdd(ObjEntity objEntity) {
231         List JavaDoc missing = new ArrayList JavaDoc();
232         Iterator JavaDoc it = objEntity.getDbEntity().getRelationships().iterator();
233         while (it.hasNext()) {
234             DbRelationship dbrel = (DbRelationship) it.next();
235             // check if adding it makes sense at all
236
if (dbrel.getName() == null) {
237                 continue;
238             }
239
240             if (objEntity.getRelationshipForDbRelationship(dbrel) == null) {
241                 missing.add(dbrel);
242             }
243         }
244
245         return missing;
246     }
247
248     public DataMap getMap() {
249         return map;
250     }
251
252     public void setMap(DataMap map) {
253         this.map = map;
254     }
255
256     /**
257      * @since 1.2
258      */

259     public boolean isRemoveMeaningfulFKs() {
260         return removeMeaningfulFKs;
261     }
262
263     /**
264      * @since 1.2
265      */

266     public void setRemoveMeaningfulFKs(boolean removeMeaningfulFKs) {
267         this.removeMeaningfulFKs = removeMeaningfulFKs;
268     }
269 }
270
Popular Tags