KickJava   Java API By Example, From Geeks To Geeks.

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


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.io.ObjectStreamException JavaDoc;
23 import java.io.Serializable JavaDoc;
24 import java.util.AbstractList JavaDoc;
25 import java.util.ArrayList JavaDoc;
26 import java.util.Collections JavaDoc;
27 import java.util.HashMap JavaDoc;
28 import java.util.Iterator JavaDoc;
29 import java.util.List JavaDoc;
30 import java.util.Map JavaDoc;
31
32 import org.apache.cayenne.graph.ArcCreateOperation;
33 import org.apache.cayenne.graph.ArcDeleteOperation;
34 import org.apache.cayenne.graph.CompoundDiff;
35 import org.apache.cayenne.graph.GraphDiff;
36 import org.apache.cayenne.graph.NodeDiff;
37
38 /**
39  * Stores graph operations in the order they were performed, optionally allowing to set
40  * named markers.
41  *
42  * @since 1.2
43  * @author Andrus Adamchik
44  */

45 class ObjectContextChangeLog {
46
47     List JavaDoc diffs;
48     Map JavaDoc markers;
49
50     ObjectContextChangeLog() {
51         reset();
52     }
53
54     void unregisterNode(Object JavaDoc nodeId) {
55         Iterator JavaDoc it = diffs.iterator();
56         while (it.hasNext()) {
57             Object JavaDoc next = it.next();
58
59             if (next instanceof NodeDiff) {
60
61                 if (nodeId.equals(((NodeDiff) next).getNodeId())) {
62                     it.remove();
63                 }
64                 else if (next instanceof ArcCreateOperation) {
65                     if (nodeId.equals(((ArcCreateOperation) next).getTargetNodeId())) {
66                         it.remove();
67                     }
68                 }
69                 else if (next instanceof ArcDeleteOperation) {
70                     if (nodeId.equals(((ArcDeleteOperation) next).getTargetNodeId())) {
71                         it.remove();
72                     }
73                 }
74             }
75         }
76     }
77
78     void setMarker(String JavaDoc markerTag) {
79         markers.put(markerTag, new Integer JavaDoc(diffs.size()));
80     }
81
82     void removeMarker(String JavaDoc markerTag) {
83         markers.remove(markerTag);
84     }
85
86     /**
87      * Returns a combined GraphDiff for all recorded operations.
88      */

89     GraphDiff getDiffs() {
90         return new CompoundDiff(immutableList(0, diffs.size()));
91     }
92
93     GraphDiff getDiffsAfterMarker(String JavaDoc markerTag) {
94         Integer JavaDoc pos = (Integer JavaDoc) markers.get(markerTag);
95         int marker = (pos == null) ? -1 : pos.intValue();
96         if (marker < 0) {
97             throw new IllegalStateException JavaDoc("No marked position for tag '"
98                     + markerTag
99                     + "'");
100         }
101
102         return new CompoundDiff(immutableList(marker, diffs.size()));
103     }
104
105     boolean hasMarker(String JavaDoc markerTag) {
106         return markers.containsKey(markerTag);
107     }
108
109     /**
110      * "Forgets" all stored operations.
111      */

112     void reset() {
113         // must create a new list instead of clearing an existing one, as the original
114
// list may have been exposed via events or "getDiffs", and trimming it is
115
// undesirable.
116
this.diffs = new ArrayList JavaDoc();
117         this.markers = new HashMap JavaDoc();
118     }
119
120     int size() {
121         return diffs.size();
122     }
123
124     int sizeAfterMarker(String JavaDoc markerTag) {
125         Integer JavaDoc pos = (Integer JavaDoc) markers.get(markerTag);
126         int marker = (pos == null) ? -1 : pos.intValue();
127         if (marker < 0) {
128             throw new IllegalStateException JavaDoc("No marked position for tag '"
129                     + markerTag
130                     + "'");
131         }
132
133         return diffs.size() - marker;
134     }
135
136     /**
137      * Adds an operation to the list.
138      */

139     void addOperation(GraphDiff diff) {
140         diffs.add(diff);
141     }
142
143     /**
144      * Returns a sublist of the diffs list that shouldn't change when OperationRecorder is
145      * cleared or new operations are added.
146      */

147     private List JavaDoc immutableList(int fromIndex, int toIndex) {
148         if (toIndex - fromIndex == 0) {
149             return Collections.EMPTY_LIST;
150         }
151
152         // Assuming that internal diffs list can only grow and can never be trimmed,
153
// return sublist will never change - something that callers are expecting
154
return Collections.unmodifiableList(new SubList(diffs, fromIndex, toIndex));
155     }
156
157     // moded Sublist from JDK that doesn't check for co-modification, as the underlying
158
// list is guaranteed to only grow and never shrink or be replaced.
159
static class SubList extends AbstractList JavaDoc implements Serializable JavaDoc {
160
161         private List JavaDoc list;
162         private int offset;
163         private int size;
164
165         SubList(List JavaDoc list, int fromIndex, int toIndex) {
166             if (fromIndex < 0)
167                 throw new IndexOutOfBoundsException JavaDoc("fromIndex = " + fromIndex);
168             if (toIndex > list.size()) {
169                 throw new IndexOutOfBoundsException JavaDoc("toIndex = " + toIndex);
170             }
171             if (fromIndex > toIndex) {
172                 throw new IllegalArgumentException JavaDoc("fromIndex("
173                         + fromIndex
174                         + ") > toIndex("
175                         + toIndex
176                         + ")");
177             }
178             this.list = list;
179             offset = fromIndex;
180             size = toIndex - fromIndex;
181         }
182
183         public Object JavaDoc get(int index) {
184             rangeCheck(index);
185             return list.get(index + offset);
186         }
187
188         public int size() {
189             return size;
190         }
191
192         private void rangeCheck(int index) {
193             if (index < 0 || index >= size) {
194                 throw new IndexOutOfBoundsException JavaDoc("Index: " + index + ",Size: " + size);
195             }
196         }
197
198         // serialization method...
199
private Object JavaDoc writeReplace() throws ObjectStreamException JavaDoc {
200             return new ArrayList JavaDoc(list.subList(offset, offset + size));
201         }
202     }
203
204 }
205
Popular Tags