KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cayenne > CayenneContextGraphManager


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;
21
22 import java.util.ArrayList JavaDoc;
23 import java.util.Collection JavaDoc;
24 import java.util.Iterator JavaDoc;
25
26 import org.apache.cayenne.event.EventManager;
27 import org.apache.cayenne.event.EventSubject;
28 import org.apache.cayenne.graph.ArcCreateOperation;
29 import org.apache.cayenne.graph.ArcDeleteOperation;
30 import org.apache.cayenne.graph.GraphChangeHandler;
31 import org.apache.cayenne.graph.GraphDiff;
32 import org.apache.cayenne.graph.GraphEvent;
33 import org.apache.cayenne.graph.GraphMap;
34 import org.apache.cayenne.graph.NodeCreateOperation;
35 import org.apache.cayenne.graph.NodeDeleteOperation;
36 import org.apache.cayenne.graph.NodeIdChangeOperation;
37 import org.apache.cayenne.graph.NodePropertyChangeOperation;
38
39 /**
40  * A GraphMap extension that works together with ObjectContext to track persistent object
41  * changes and send events.
42  *
43  * @since 1.2
44  * @author Andrus Adamchik
45  */

46 final class CayenneContextGraphManager extends GraphMap {
47
48     static final String JavaDoc COMMIT_MARKER = "commit";
49     static final String JavaDoc FLUSH_MARKER = "flush";
50
51     CayenneContext context;
52     Collection JavaDoc deadIds;
53     boolean changeEventsEnabled;
54     boolean lifecycleEventsEnabled;
55
56     ObjectContextStateLog stateLog;
57     ObjectContextChangeLog changeLog;
58
59     CayenneContextGraphManager(CayenneContext context, boolean changeEventsEnabled,
60             boolean lifecycleEventsEnabled) {
61
62         this.context = context;
63         this.changeEventsEnabled = changeEventsEnabled;
64         this.lifecycleEventsEnabled = lifecycleEventsEnabled;
65
66         this.stateLog = new ObjectContextStateLog(this);
67         this.changeLog = new ObjectContextChangeLog();
68     }
69
70     boolean hasChanges() {
71         return changeLog.size() > 0;
72     }
73
74     boolean hasChangesSinceLastFlush() {
75         int size = changeLog.hasMarker(FLUSH_MARKER) ? changeLog
76                 .sizeAfterMarker(FLUSH_MARKER) : changeLog.size();
77         return size > 0;
78     }
79
80     GraphDiff getDiffs() {
81         return changeLog.getDiffs();
82     }
83
84     GraphDiff getDiffsSinceLastFlush() {
85         return changeLog.hasMarker(FLUSH_MARKER) ? changeLog
86                 .getDiffsAfterMarker(FLUSH_MARKER) : changeLog.getDiffs();
87     }
88
89     Collection JavaDoc dirtyNodes() {
90         return stateLog.dirtyNodes();
91     }
92
93     Collection JavaDoc dirtyNodes(int state) {
94         return stateLog.dirtyNodes(state);
95     }
96
97     public synchronized Object JavaDoc unregisterNode(Object JavaDoc nodeId) {
98         Object JavaDoc node = super.unregisterNode(nodeId);
99
100         // remove node from other collections...
101
if (node != null) {
102             stateLog.unregisterNode(nodeId);
103             changeLog.unregisterNode(nodeId);
104             return node;
105         }
106
107         return null;
108     }
109
110     // ****** Sync Events API *****
111
/**
112      * Clears commit marker, but keeps all recorded operations.
113      */

114     void graphCommitAborted() {
115         changeLog.removeMarker(COMMIT_MARKER);
116     }
117
118     /**
119      * Sets commit start marker in the change log. If events are enabled, posts commit
120      * start event.
121      */

122     void graphCommitStarted() {
123         changeLog.setMarker(COMMIT_MARKER);
124     }
125
126     void graphCommitted(GraphDiff parentSyncDiff) {
127         if (parentSyncDiff != null) {
128             new CayenneContextMergeHandler(context).merge(parentSyncDiff);
129         }
130
131         if (lifecycleEventsEnabled) {
132             GraphDiff diff = changeLog.getDiffsAfterMarker(COMMIT_MARKER);
133
134             stateLog.graphCommitted();
135             reset();
136
137             // include all diffs after the commit start marker.
138
send(diff, DataChannel.GRAPH_FLUSHED_SUBJECT, context);
139         }
140         else {
141             stateLog.graphCommitted();
142             reset();
143         }
144     }
145
146     void graphFlushed() {
147         changeLog.setMarker(FLUSH_MARKER);
148     }
149
150     void graphReverted() {
151         GraphDiff diff = changeLog.getDiffs();
152
153         diff.undo(new NullChangeHandler());
154         stateLog.graphReverted();
155         reset();
156
157         if (lifecycleEventsEnabled) {
158             send(diff, DataChannel.GRAPH_ROLLEDBACK_SUBJECT, context);
159         }
160     }
161
162     // ****** GraphChangeHandler API ******
163
// =====================================================
164

165     public synchronized void nodeIdChanged(Object JavaDoc nodeId, Object JavaDoc newId) {
166         stateLog.nodeIdChanged(nodeId, newId);
167         processChange(new NodeIdChangeOperation(nodeId, newId));
168     }
169
170     public synchronized void nodeCreated(Object JavaDoc nodeId) {
171         stateLog.nodeCreated(nodeId);
172         processChange(new NodeCreateOperation(nodeId));
173     }
174
175     public synchronized void nodeRemoved(Object JavaDoc nodeId) {
176         stateLog.nodeRemoved(nodeId);
177         processChange(new NodeDeleteOperation(nodeId));
178     }
179
180     public synchronized void nodePropertyChanged(
181             Object JavaDoc nodeId,
182             String JavaDoc property,
183             Object JavaDoc oldValue,
184             Object JavaDoc newValue) {
185
186         stateLog.nodePropertyChanged(nodeId, property, oldValue, newValue);
187         processChange(new NodePropertyChangeOperation(
188                 nodeId,
189                 property,
190                 oldValue,
191                 newValue));
192     }
193
194     public synchronized void arcCreated(Object JavaDoc nodeId, Object JavaDoc targetNodeId, Object JavaDoc arcId) {
195         stateLog.arcCreated(nodeId, targetNodeId, arcId);
196         processChange(new ArcCreateOperation(nodeId, targetNodeId, arcId));
197     }
198
199     public synchronized void arcDeleted(Object JavaDoc nodeId, Object JavaDoc targetNodeId, Object JavaDoc arcId) {
200         stateLog.arcDeleted(nodeId, targetNodeId, arcId);
201         processChange(new ArcDeleteOperation(nodeId, targetNodeId, arcId));
202     }
203
204     // ****** helper methods ******
205
// =====================================================
206

207     private void processChange(GraphDiff diff) {
208         changeLog.addOperation(diff);
209
210         if (changeEventsEnabled) {
211             send(diff, DataChannel.GRAPH_CHANGED_SUBJECT, context);
212         }
213     }
214
215     /**
216      * Wraps GraphDiff in a GraphEvent and sends it via EventManager with specified
217      * subject.
218      */

219     void send(GraphDiff diff, EventSubject subject, Object JavaDoc eventSource) {
220         EventManager manager = (context.getChannel() != null) ? context
221                 .getChannel()
222                 .getEventManager() : null;
223
224         if (manager != null) {
225             GraphEvent e = new GraphEvent(context, eventSource, diff);
226             manager.postEvent(e, subject);
227         }
228     }
229
230     void reset() {
231         changeLog.reset();
232
233         if (deadIds != null) {
234             // unregister dead ids...
235
Iterator JavaDoc it = deadIds.iterator();
236             while (it.hasNext()) {
237                 nodes.remove(it.next());
238             }
239
240             deadIds = null;
241         }
242     }
243
244     Collection JavaDoc deadIds() {
245         if (deadIds == null) {
246             deadIds = new ArrayList JavaDoc();
247         }
248
249         return deadIds;
250     }
251
252     class NullChangeHandler implements GraphChangeHandler {
253
254         public void arcCreated(Object JavaDoc nodeId, Object JavaDoc targetNodeId, Object JavaDoc arcId) {
255         }
256
257         public void arcDeleted(Object JavaDoc nodeId, Object JavaDoc targetNodeId, Object JavaDoc arcId) {
258         }
259
260         public void nodeCreated(Object JavaDoc nodeId) {
261         }
262
263         public void nodeIdChanged(Object JavaDoc nodeId, Object JavaDoc newId) {
264         }
265
266         public void nodePropertyChanged(
267                 Object JavaDoc nodeId,
268                 String JavaDoc property,
269                 Object JavaDoc oldValue,
270                 Object JavaDoc newValue) {
271         }
272
273         public void nodeRemoved(Object JavaDoc nodeId) {
274         }
275     }
276 }
277
Popular Tags