KickJava   Java API By Example, From Geeks To Geeks.

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


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 org.apache.cayenne.DataChannelListener;
23 import org.apache.cayenne.ObjectId;
24 import org.apache.cayenne.PersistenceState;
25 import org.apache.cayenne.Persistent;
26 import org.apache.cayenne.access.ObjectStore.SnapshotEventDecorator;
27 import org.apache.cayenne.access.event.SnapshotEvent;
28 import org.apache.cayenne.graph.GraphChangeHandler;
29 import org.apache.cayenne.graph.GraphDiff;
30 import org.apache.cayenne.graph.GraphEvent;
31 import org.apache.cayenne.reflect.AttributeProperty;
32 import org.apache.cayenne.reflect.ClassDescriptor;
33 import org.apache.cayenne.reflect.Property;
34 import org.apache.cayenne.reflect.PropertyVisitor;
35 import org.apache.cayenne.reflect.ToManyProperty;
36 import org.apache.cayenne.reflect.ToOneProperty;
37 import org.apache.cayenne.util.Util;
38
39 /**
40  * A listener of GraphEvents sent by the DataChannel that merges changes to the
41  * DataContext.
42  *
43  * @since 1.2
44  * @author Andrus Adamchik
45  */

46 // TODO: andrus, 11/25/2006 - this logic is the same as the logic in DataRowUtils used to
47
// merge snapshot changes. Any way to reconclie the two? (in fact DataRowUtils is more
48
// comprehensive)
49
class DataContextMergeHandler implements GraphChangeHandler, DataChannelListener {
50
51     private boolean active;
52     private DataContext context;
53
54     DataContextMergeHandler(DataContext context) {
55         this.active = true;
56         this.context = context;
57     }
58
59     void setActive(boolean active) {
60         this.active = active;
61     }
62
63     /**
64      * Returns true if this object is active and an event came from our channel, but did
65      * not originate in it.
66      */

67     private boolean shouldProcessEvent(GraphEvent e) {
68
69         if (!active) {
70             return false;
71         }
72
73         // this effectively filters out all events that are not coming from peers or
74
// grandparents...
75
return e.getSource() == context.getChannel()
76                 && e.getPostedBy() != context
77                 && e.getPostedBy() != context.getChannel();
78
79         // the first condition (e.getSource() == context.getChannel()) is actually always
80
// 'true' because of how the listener is registered. Still keep it here as an
81
// extra safegurad
82
}
83
84     private Property propertyForId(Object JavaDoc nodeId, String JavaDoc propertyName) {
85         ClassDescriptor descriptor = context.getEntityResolver().getClassDescriptor(
86                 ((ObjectId) nodeId).getEntityName());
87         return descriptor.getProperty(propertyName);
88     }
89
90     // *** GraphEventListener methods
91

92     public void graphChanged(GraphEvent event) {
93         // parent received external change
94
if (shouldProcessEvent(event)) {
95
96             // temp kludge - see TODO in ObjectStore.snapshotsChanged(..)
97
GraphDiff diff = event.getDiff();
98             if (diff instanceof SnapshotEventDecorator) {
99                 SnapshotEvent decoratedEvent = ((SnapshotEventDecorator) diff).getEvent();
100                 context.getObjectStore().processSnapshotEvent(decoratedEvent);
101             }
102             else {
103                 synchronized (context.getObjectStore()) {
104                     diff.apply(this);
105                 }
106             }
107
108             // repost channel change event for our own children
109
context.fireDataChannelChanged(event.getPostedBy(), event.getDiff());
110         }
111     }
112
113     public void graphFlushed(GraphEvent event) {
114         // peer is committed
115
if (shouldProcessEvent(event)) {
116             event.getDiff().apply(this);
117
118             // repost as change event for our own children
119
context.fireDataChannelChanged(event.getPostedBy(), event.getDiff());
120         }
121     }
122
123     public void graphRolledback(GraphEvent event) {
124         // TODO: andrus, 3/26/2006 - enable this once all ObjectStore diffs implement
125
// working undo operation
126

127         // if(shouldProcessEvent(e)) {
128
// event.getDiff().undo(this);
129
// }
130
}
131
132     // *** GraphChangeHandler methods
133

134     public void nodeIdChanged(Object JavaDoc nodeId, Object JavaDoc newId) {
135         context.getObjectStore().processIdChange(nodeId, newId);
136     }
137
138     public void nodeCreated(Object JavaDoc nodeId) {
139         // noop
140
}
141
142     public void nodeRemoved(Object JavaDoc nodeId) {
143         ObjectStore os = context.getObjectStore();
144         synchronized (os) {
145             os.processDeletedID(nodeId);
146         }
147     }
148
149     public void nodePropertyChanged(
150             Object JavaDoc nodeId,
151             String JavaDoc property,
152             Object JavaDoc oldValue,
153             Object JavaDoc newValue) {
154
155         Persistent object = (Persistent) context.getGraphManager().getNode(nodeId);
156         if (object != null && object.getPersistenceState() != PersistenceState.HOLLOW) {
157
158             // do not override local changes....
159
Property p = propertyForId(nodeId, property);
160             if (Util.nullSafeEquals(p.readPropertyDirectly(object), oldValue)) {
161                 p.writePropertyDirectly(object, oldValue, newValue);
162             }
163         }
164     }
165
166     public void arcCreated(Object JavaDoc nodeId, Object JavaDoc targetNodeId, Object JavaDoc arcId) {
167         arcChanged(nodeId, targetNodeId, arcId);
168     }
169
170     public void arcDeleted(Object JavaDoc nodeId, Object JavaDoc targetNodeId, Object JavaDoc arcId) {
171         arcChanged(nodeId, targetNodeId, arcId);
172     }
173
174     // works the same for add and remove as long as we don't get too smart per TODO below.
175
private void arcChanged(Object JavaDoc nodeId, Object JavaDoc targetNodeId, Object JavaDoc arcId) {
176
177         final Persistent source = (Persistent) context.getGraphManager().getNode(nodeId);
178         if (source != null && source.getPersistenceState() != PersistenceState.HOLLOW) {
179
180             final int state = source.getPersistenceState();
181
182             Property p = propertyForId(nodeId, arcId.toString());
183             p.visit(new PropertyVisitor() {
184
185                 public boolean visitAttribute(AttributeProperty property) {
186                     return false;
187                 }
188
189                 public boolean visitToMany(ToManyProperty property) {
190                     if (state == PersistenceState.COMMITTED) {
191                         property.invalidate(source);
192                     }
193
194                     return false;
195                 }
196
197                 public boolean visitToOne(ToOneProperty property) {
198                     if (state == PersistenceState.COMMITTED) {
199                         property.invalidate(source);
200                     }
201                     // TODO: andrus, 11/25/2006 - handle replacement of clean properties
202
// of dirty objects. See DataRowUtils for details.
203
return false;
204                 }
205             });
206         }
207     }
208 }
209
Popular Tags