1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 package com.enspire.gemini.bidirectional;
25
26 import java.util.Collection;
27 import java.util.Iterator;
28
29 import com.enspire.collections.decorator.CollectionDecorator;
30 import com.enspire.collections.decorator.SetUniqueCollection;
31 import com.enspire.gemini.BidirectionalProperty;
32 import com.enspire.gemini.RelationshipUpdater;
33 import com.enspire.gemini.commands.BidirectionalCollectionAdd;
34 import com.enspire.gemini.commands.BidirectionalCollectionRemove;
35 import com.enspire.gemini.commands.Command;
36 import com.enspire.gemini.commands.CommandExecutor;
37 import com.enspire.gemini.commands.CommandExecutorImpl;
38
39 /***
40 * <p><a href="http://www.e-nspire.com">e-nspire site</a></p>
41 * This <code>Collection</code> updates the corresponding opposite property of
42 * its elements, both simple and container properties. It is intended
43 * to represent one end of a bidirectional association. It must be supplied
44 * with <code>RelationshipUpdater</code> to know which property of the
45 * containing objects represents the opposite end. It decorates another
46 * <code>Collection</code>.
47 *
48 * @author Dragan Djuric <dragand@dev.java.net>
49 * @since 1.0
50 **/
51 public class BidirectionalCollection extends CollectionDecorator
52 implements BidirectionalProperty {
53
54 private Collection decoratedCollection;
55 private RelationshipUpdater relationshipUpdater;
56 private Object owner;
57 private String oppositeName;
58
59 /***
60 * @see com.enspire.gemini.BidirectionalProperty#getRelationshipUpdater()
61 */
62 public RelationshipUpdater getRelationshipUpdater() {
63 return this.relationshipUpdater;
64 }
65
66 /***
67 * @see com.enspire.gemini.BidirectionalProperty#setRelationshipUpdater(com.enspire.gemini.RelationshipUpdater)
68 */
69 public void setRelationshipUpdater(RelationshipUpdater relationshipUpdater) {
70 this.relationshipUpdater = relationshipUpdater;
71 }
72
73 /***
74 * @see com.enspire.gemini.BidirectionalProperty#getOppositeName()
75 */
76 public String getOppositeName() {
77 return this.oppositeName;
78 }
79
80 /***
81 * @see com.enspire.gemini.BidirectionalProperty#setOppositeName(java.lang.String)
82 */
83 public void setOppositeName(
84 String oppositeName) {
85 this.oppositeName = oppositeName;
86 }
87
88 /***
89 * @see com.enspire.gemini.BidirectionalProperty#getOwner()
90 */
91 public Object getOwner() {
92 return this.owner;
93 }
94
95 /***
96 * @see com.enspire.gemini.BidirectionalProperty#setOwner(java.lang.Object)
97 */
98 public void setOwner(Object owner) {
99 this.owner = owner;
100 }
101
102 /***
103 * @see com.enspire.gemini.BidirectionalProperty#getPropertyValue()
104 */
105 public Object getPropertyValue() {
106 return this.getDecoratedCollection();
107 }
108
109 /***
110 * @see com.enspire.gemini.BidirectionalProperty#setPropertyValue(java.lang.String)
111 */
112 public void setPropertyValue(Object propertyValue) {
113 this.decoratedCollection =
114 SetUniqueCollection.decorate((Collection)propertyValue);
115 }
116
117 /***
118 * @see com.enspire.collections.decorator.ListDecorator#getDecoratedCollection()
119 */
120
121 protected Collection getDecoratedCollection() {
122 return this.decoratedCollection;
123 }
124
125 /***
126 * Adds the object to the collection and updates the opposite property
127 * of the added object.
128 *
129 * @see java.util.Collection#add(java.lang.Object)
130 */
131
132 public boolean add(Object object) {
133 if (super.add(object)) {
134 try {
135 getRelationshipUpdater().set(
136 object, getOppositeName(), getOwner());
137 return true;
138 } catch(RuntimeException e) {
139 super.remove(object);
140 throw e;
141 }
142 }
143 return false;
144 }
145
146 /***
147 * Removes the object from the collection and updates the opposite property
148 * of the removed object.
149 *
150 * @see java.util.Collection#remove(java.lang.Object)
151 */
152
153 public boolean remove(Object object) {
154 if (super.remove(object)) {
155 try {
156 getRelationshipUpdater().unset(
157 object, getOppositeName(), getOwner());
158 return true;
159 }catch(RuntimeException e) {
160 super.add(object);
161 throw e;
162 }
163 }
164 return false;
165 }
166
167 /***
168 * @see java.util.Collection#addAll(java.util.Collection)
169 */
170
171 public boolean addAll(Collection coll) {
172 int sizeBefore = size();
173 CommandExecutor executor = new CommandExecutorImpl();
174 try {
175 for (final Iterator it = coll.iterator(); it.hasNext();) {
176 Object object = it.next();
177 Command addCommand = new BidirectionalCollectionAdd(
178 this, this.getDecoratedCollection(), object);
179 executor.execute(addCommand);
180 }
181 return sizeBefore != size();
182 }catch(RuntimeException e) {
183 executor.undo();
184 throw e;
185 }
186 }
187
188 /***
189 * @see java.util.Collection#removeAll(java.util.Collection)
190 */
191
192 public boolean removeAll(Collection coll) {
193 int sizeBefore = size();
194 CommandExecutor executor = new CommandExecutorImpl();
195 try {
196 for (final Iterator it = coll.iterator(); it.hasNext();) {
197 Object object = it.next();
198 Command removeCommand = new BidirectionalCollectionRemove(
199 this, this.getDecoratedCollection(), object);
200 executor.execute(removeCommand);
201 }
202 return sizeBefore != size();
203 }catch(RuntimeException e) {
204 executor.undo();
205 throw e;
206 }
207 }
208
209 /***
210 * Unsupported operation.
211 *
212 * @see java.util.Collection#retainAll(java.util.Collection)
213 */
214
215 public boolean retainAll(Collection coll) {
216 throw new UnsupportedOperationException();
217 }
218
219 /***
220 * Unsupported operation.
221 *
222 * @see java.util.Collection#clear()
223 */
224 public void clear() {
225 throw new UnsupportedOperationException("clear() is not allowed.");
226 }
227
228 /***
229 * @see com.enspire.collections.decorator.CollectionDecorator#iterator()
230 */
231
232 public Iterator iterator() {
233 return new BidirectionalIterator(this, super.iterator());
234 }
235
236 }