KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cayenne > access > DataDomainDBDiffBuilder


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.access;
21
22 import java.util.HashMap JavaDoc;
23 import java.util.Iterator JavaDoc;
24 import java.util.Map JavaDoc;
25
26 import org.apache.cayenne.ObjectId;
27 import org.apache.cayenne.access.DataDomainSyncBucket.PropagatedValueFactory;
28 import org.apache.cayenne.graph.GraphChangeHandler;
29 import org.apache.cayenne.graph.GraphDiff;
30 import org.apache.cayenne.map.Attribute;
31 import org.apache.cayenne.map.DbEntity;
32 import org.apache.cayenne.map.DbJoin;
33 import org.apache.cayenne.map.DbRelationship;
34 import org.apache.cayenne.map.ObjAttribute;
35 import org.apache.cayenne.map.ObjEntity;
36 import org.apache.cayenne.map.ObjRelationship;
37
38 /**
39  * Processes object diffs, generating DB diffs. Can be used for both UPDATE and INSERT.
40  *
41  * @since 1.2
42  * @author Andrus Adamchik
43  */

44 class DataDomainDBDiffBuilder implements GraphChangeHandler {
45
46     private ObjEntity objEntity;
47     private DbEntity dbEntity;
48
49     // diff snapshot expressed in terms of object properties.
50
private Map JavaDoc currentPropertyDiff;
51     private Map JavaDoc currentArcDiff;
52     private Object JavaDoc currentId;
53
54     /**
55      * Resets the builder to process a new combination of objEntity/dbEntity.
56      */

57     void reset(ObjEntity objEntity, DbEntity dbEntity) {
58         this.objEntity = objEntity;
59         this.dbEntity = dbEntity;
60     }
61
62     /**
63      * Resets the builder to process a new object for the previously set combination of
64      * objEntity/dbEntity.
65      */

66     private void reset() {
67         currentPropertyDiff = null;
68         currentArcDiff = null;
69         currentId = null;
70     }
71
72     /**
73      * Processes GraphDiffs of a single object, converting them to DB diff.
74      */

75     Map JavaDoc buildDBDiff(GraphDiff singleObjectDiff) {
76
77         reset();
78         singleObjectDiff.apply(this);
79
80         if (currentPropertyDiff == null && currentArcDiff == null && currentId == null) {
81             return null;
82         }
83
84         Map JavaDoc dbDiff = new HashMap JavaDoc();
85
86         appendSimpleProperties(dbDiff);
87         appendForeignKeys(dbDiff);
88         appendPrimaryKeys(dbDiff);
89
90         return dbDiff.isEmpty() ? null : dbDiff;
91     }
92
93     private void appendSimpleProperties(Map JavaDoc dbDiff) {
94         // populate changed columns
95
if (currentPropertyDiff != null) {
96             Iterator JavaDoc it = currentPropertyDiff.entrySet().iterator();
97             while (it.hasNext()) {
98                 Map.Entry JavaDoc entry = (Map.Entry JavaDoc) it.next();
99                 ObjAttribute attribute = (ObjAttribute) objEntity.getAttribute(entry
100                         .getKey()
101                         .toString());
102
103                 // this takes care of the flattened attributes, as 'getDbAttributeName'
104
// returns the last path component...
105
Attribute dbAttribute = dbEntity.getAttribute(attribute
106                         .getDbAttributeName());
107                 dbDiff.put(dbAttribute.getName(), entry.getValue());
108             }
109         }
110     }
111
112     private void appendForeignKeys(Map JavaDoc dbDiff) {
113         // populate changed FKs
114
if (currentArcDiff != null) {
115             Iterator JavaDoc it = currentArcDiff.entrySet().iterator();
116             while (it.hasNext()) {
117                 Map.Entry JavaDoc entry = (Map.Entry JavaDoc) it.next();
118                 ObjRelationship relation = (ObjRelationship) objEntity
119                         .getRelationship(entry.getKey().toString());
120
121                 DbRelationship dbRelation = (DbRelationship) relation
122                         .getDbRelationships()
123                         .get(0);
124
125                 ObjectId targetId = (ObjectId) entry.getValue();
126                 Iterator JavaDoc joins = dbRelation.getJoins().iterator();
127                 while (joins.hasNext()) {
128                     DbJoin join = (DbJoin) joins.next();
129                     Object JavaDoc value = (targetId != null) ? new PropagatedValueFactory(
130                             targetId,
131                             join.getTargetName()) : null;
132
133                     dbDiff.put(join.getSourceName(), value);
134                 }
135             }
136         }
137     }
138
139     private void appendPrimaryKeys(Map JavaDoc dbDiff) {
140
141         // populate changed PKs; note that we might end up overriding some values taken
142
// from the object (e.g. zero PK's).
143
if (currentId != null) {
144             dbDiff.putAll(((ObjectId) currentId).getIdSnapshot());
145         }
146     }
147
148     // ==================================================
149
// GraphChangeHandler methods.
150
// ==================================================
151

152     public void nodePropertyChanged(
153             Object JavaDoc nodeId,
154             String JavaDoc property,
155             Object JavaDoc oldValue,
156             Object JavaDoc newValue) {
157         // note - no checking for phantom mod... assuming there is no phantom diffs
158

159         if (currentPropertyDiff == null) {
160             currentPropertyDiff = new HashMap JavaDoc();
161         }
162
163         currentPropertyDiff.put(property, newValue);
164     }
165
166     public void arcCreated(Object JavaDoc nodeId, Object JavaDoc targetNodeId, Object JavaDoc arcId) {
167
168         ObjRelationship relationship = (ObjRelationship) objEntity.getRelationship(arcId
169                 .toString());
170         if (!relationship.isSourceIndependentFromTargetChange()) {
171             if (currentArcDiff == null) {
172                 currentArcDiff = new HashMap JavaDoc();
173             }
174             currentArcDiff.put(arcId, targetNodeId);
175         }
176     }
177
178     public void arcDeleted(Object JavaDoc nodeId, Object JavaDoc targetNodeId, Object JavaDoc arcId) {
179
180         ObjRelationship relationship = (ObjRelationship) objEntity.getRelationship(arcId
181                 .toString());
182         if (!relationship.isSourceIndependentFromTargetChange()) {
183
184             if (currentArcDiff == null) {
185                 currentArcDiff = new HashMap JavaDoc();
186                 currentArcDiff.put(arcId, null);
187             }
188             // check for situation when a substitute arc was created prior to deleting the
189
// old arc...
190
else if (targetNodeId.equals(currentArcDiff.get(arcId))) {
191                 currentArcDiff.put(arcId, null);
192             }
193         }
194     }
195
196     public void nodeCreated(Object JavaDoc nodeId) {
197         // need to append PK columns
198
this.currentId = nodeId;
199     }
200
201     public void nodeRemoved(Object JavaDoc nodeId) {
202         // noop
203
}
204
205     public void nodeIdChanged(Object JavaDoc nodeId, Object JavaDoc newId) {
206         // noop
207
}
208 }
209
Popular Tags