1 /*
2
3 dsh-observable-graph Observable decorators for graph interfaces.
4 Copyright (c) 2008-2013 held jointly by the individual authors.
5
6 This library is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published
8 by the Free Software Foundation; either version 3 of the License, or (at
9 your option) any later version.
10
11 This library is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
14 License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with this library; if not, write to the Free Software Foundation,
18 Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
19
20 > http://www.fsf.org/licensing/licenses/lgpl.html
21 > http://www.opensource.org/licenses/lgpl-license.php
22
23 */
24 package org.dishevelled.observable.graph;
25
26 import org.dishevelled.graph.Edge;
27 import org.dishevelled.graph.Graph;
28 import org.dishevelled.graph.Node;
29
30 import org.dishevelled.graph.impl.AbstractGraphDecorator;
31
32 import org.dishevelled.observable.graph.event.GraphChangeListener;
33 import org.dishevelled.observable.graph.event.GraphChangeVetoException;
34 import org.dishevelled.observable.graph.event.ObservableGraphChangeSupport;
35 import org.dishevelled.observable.graph.event.VetoableGraphChangeListener;
36
37 /**
38 * Abstract implementation of an observable graph that decorates an
39 * instance of <code>Graph</code>.
40 *
41 * @param <N> node value type
42 * @param <E> edge value type
43 * @author Michael Heuer
44 * @version $Revision$ $Date$
45 */
46 public abstract class AbstractObservableGraph<N, E>
47 extends AbstractGraphDecorator<N, E>
48 implements ObservableGraph<N, E>
49 {
50 /** Observable graph change support. */
51 private final ObservableGraphChangeSupport<N, E> support;
52
53
54 /**
55 * Create a new abstract observable graph that
56 * decorates the specified graph.
57 *
58 * @param graph graph to decorate
59 */
60 protected AbstractObservableGraph(final Graph<N, E> graph)
61 {
62 super(graph);
63 support = new ObservableGraphChangeSupport<N, E>(this);
64 }
65
66
67 /**
68 * Return the <code>ObservableGraphChangeSupport</code>
69 * class backing this abstract observable graph.
70 *
71 * @return the <code>ObservableGraphChangeSupport</code>
72 * class backing this abstract observable graph
73 */
74 protected final ObservableGraphChangeSupport<N, E> getObservableGraphChangeSupport()
75 {
76 return support;
77 }
78
79 /** {@inheritDoc} */
80 public final void addGraphChangeListener(final GraphChangeListener<N, E> l)
81 {
82 support.addGraphChangeListener(l);
83 }
84
85 /** {@inheritDoc} */
86 public final void removeGraphChangeListener(final GraphChangeListener<N, E> l)
87 {
88 support.removeGraphChangeListener(l);
89 }
90
91 /** {@inheritDoc} */
92 public final void addVetoableGraphChangeListener(final VetoableGraphChangeListener<N, E> l)
93 {
94 support.addVetoableGraphChangeListener(l);
95 }
96
97 /** {@inheritDoc} */
98 public final void removeVetoableGraphChangeListener(final VetoableGraphChangeListener<N, E> l)
99 {
100 support.removeVetoableGraphChangeListener(l);
101 }
102
103 /** {@inheritDoc} */
104 public final GraphChangeListener<N, E>[] getGraphChangeListeners()
105 {
106 return support.getGraphChangeListeners();
107 }
108
109 /** {@inheritDoc} */
110 public final int getGraphChangeListenerCount()
111 {
112 return support.getGraphChangeListenerCount();
113 }
114
115 /** {@inheritDoc} */
116 public final VetoableGraphChangeListener<N, E>[] getVetoableGraphChangeListeners()
117 {
118 return support.getVetoableGraphChangeListeners();
119 }
120
121 /** {@inheritDoc} */
122 public final int getVetoableGraphChangeListenerCount()
123 {
124 return support.getVetoableGraphChangeListenerCount();
125 }
126
127 /**
128 * Fire a will clear change event to all registered
129 * <code>VetoableGraphChangeListener</code>s.
130 *
131 * @throws GraphChangeVetoException if any of the listeners veto the change
132 */
133 protected void fireWillClear()
134 throws GraphChangeVetoException
135 {
136 support.fireWillClear();
137 }
138
139 /**
140 * Fire a cleared change event to all registered <code>GraphChangeListener</code>s.
141 */
142 protected void fireCleared()
143 {
144 support.fireCleared();
145 }
146
147 /**
148 * Fire a will create node change event to all registered
149 * <code>VetoableGraphChangeListener</code>s.
150 *
151 * @param nodeValue node value for an about to be created node
152 * @throws GraphChangeVetoException if any of the listeners veto the change
153 */
154 protected void fireWillCreateNode(final N nodeValue)
155 throws GraphChangeVetoException
156 {
157 support.fireWillCreateNode(nodeValue);
158 }
159
160 /**
161 * Fire a will create edge change event to all registered
162 * <code>VetoableGraphChangeListener</code>s.
163 *
164 * @param sourceNode source node for an about to be created edge
165 * @param targetNode target node for an about to be created edge
166 * @param edgeValue edge value for an about to be created edge
167 * @throws GraphChangeVetoException if any of the listeners veto the change
168 */
169 protected void fireWillCreateEdge(final Node<N, E> sourceNode,
170 final Node<N, E> targetNode,
171 final E edgeValue)
172 throws GraphChangeVetoException
173 {
174 support.fireWillCreateEdge(sourceNode, targetNode, edgeValue);
175 }
176
177 /**
178 * Fire a will remove node change event to all registered
179 * <code>VetoableGraphChangeListener</code>s.
180 *
181 * @param node node about to be removed
182 * @throws GraphChangeVetoException if any of the listeners veto the change
183 */
184 protected void fireWillRemoveNode(final Node<N, E> node)
185 throws GraphChangeVetoException
186 {
187 support.fireWillRemoveNode(node);
188 }
189
190 /**
191 * Fire a will remove edge change event to all registered
192 * <code>VetoableGraphChangeListener</code>s.
193 *
194 * @param edge edge about to be removed
195 * @throws GraphChangeVetoException if any of the listeners veto the change
196 */
197 protected void fireWillRemoveEdge(final Edge<N, E> edge)
198 throws GraphChangeVetoException
199 {
200 support.fireWillRemoveEdge(edge);
201 }
202
203 /**
204 * Fire a node created change event to all registered <code>GraphChangeListener</code>s.
205 *
206 * @param node newly created node
207 */
208 protected void fireNodeCreated(final Node<N, E> node)
209 {
210 support.fireNodeCreated(node);
211 }
212
213 /**
214 * Fire a node removed change event to all registered <code>GraphChangeListener</code>s.
215 *
216 * @param node removed node
217 */
218 protected void fireNodeRemoved(final Node<N, E> node)
219 {
220 support.fireNodeRemoved(node);
221 }
222
223 /**
224 * Fire an edge created change event to all registered <code>GraphChangeListener</code>s.
225 *
226 * @param edge newly created edge
227 */
228 protected void fireEdgeCreated(final Edge<N, E> edge)
229 {
230 support.fireEdgeCreated(edge);
231 }
232
233 /**
234 * Fire an edge removed change event to all registered <code>GraphChangeListener</code>s.
235 *
236 * @param edge removed edge
237 */
238 protected void fireEdgeRemoved(final Edge<N, E> edge)
239 {
240 support.fireEdgeRemoved(edge);
241 }
242
243 /**
244 * Notify subclasses the <code>clear</code> method is about to
245 * be called on the wrapped graph.
246 * Return <code>true</code> to proceed with the change.
247 *
248 * @return true to proceed with the change
249 */
250 protected abstract boolean preClear();
251
252 /**
253 * Notify subclasses the <code>clear</code> method has just been
254 * called on the wrapped graph.
255 */
256 protected abstract void postClear();
257
258 /**
259 * Notify subclasses the <code>createNode</code> method is about to
260 * be called on the wrapped graph with the specified parameter.
261 * Return <code>true</code> to proceed with the change.
262 *
263 * @param value <code>createNode</code> method parameter
264 * @return true to proceed with the change
265 */
266 protected abstract boolean preCreateNode(N value);
267
268 /**
269 * Notify subclasses the <code>createNode</code> method has just been
270 * called on the wrapped graph with the specified parameter.
271 *
272 * @param value <code>createNode</code> method parameter
273 * @param node newly created node
274 */
275 protected abstract void postCreateNode(N value, Node<N, E> node);
276
277 /**
278 * Notify subclasses the <code>remove(Node<N, E>)</code> method is about to
279 * be called on the wrapped graph with the specified parameter.
280 * Return <code>true</code> to proceed with the change.
281 *
282 * @param node <code>remove(Node<N, E>)</code> method parameter
283 * @return true to proceed with the change
284 */
285 protected abstract boolean preRemove(Node<N, E> node);
286
287 /**
288 * Notify subclasses the <code>remove(Node<N, E>)</code> method has just been
289 * called on the wrapped graph with the specified parameter.
290 *
291 * @param node <code>remove(Node<N, E>)</code> method parameter
292 */
293 protected abstract void postRemove(Node<N, E> node);
294
295 /**
296 * Notify subclasses the <code>createEdge</code> method is about to
297 * be called on the wrapped graph with the specified parameters.
298 * Return <code>true</code> to proceed with the change.
299 *
300 * @param source <code>createEdge</code> method parameter
301 * @param target <code>createEdge</code> method parameter
302 * @param value <code>createEdge</code> method parameter
303 * @return true to proceed with the change
304 */
305 protected abstract boolean preCreateEdge(Node<N, E> source, Node<N, E> target, E value);
306
307 /**
308 * Notify subclasses the <code>createEdge</code> method has just been
309 * called on the wrapped graph with the specified parameters.
310 *
311 * @param source <code>createEdge</code> method parameter
312 * @param target <code>createEdge</code> method parameter
313 * @param value <code>createEdge</code> method parameter
314 * @param edge newly created edge
315 */
316 protected abstract void postCreateEdge(Node<N, E> source, Node<N, E> target, E value, Edge<N, E> edge);
317
318 /**
319 * Notify subclasses the <code>remove(Edge<N, E>)</code> method is about to
320 * be called on the wrapped graph with the specified parameter.
321 * Return <code>true</code> to proceed with the change.
322 *
323 * @param edge <code>remove(Edge<N, E>)</code> method parameter
324 * @return true to proceed with the change
325 */
326 protected abstract boolean preRemove(Edge<N, E> edge);
327
328 /**
329 * Notify subclasses the <code>remove(Edge<N, E>)</code> method has just been
330 * called on the wrapped graph with the specified parameter.
331 *
332 * @param edge <code>remove(Edge<N, E>)</code> method parameter
333 */
334 protected abstract void postRemove(Edge<N, E> edge);
335
336 /** {@inheritDoc} */
337 public void clear()
338 {
339 if (preClear())
340 {
341 super.clear();
342 postClear();
343 }
344 }
345
346 /** {@inheritDoc} */
347 public Node<N, E> createNode(final N value)
348 {
349 if (preCreateNode(value))
350 {
351 Node<N, E> node = super.createNode(value);
352 postCreateNode(value, node);
353 return node;
354 }
355 // TODO: explicitly document this behaviour
356 return null;
357 }
358
359 /** {@inheritDoc} */
360 public void remove(final Node<N, E> node)
361 {
362 if (preRemove(node))
363 {
364 super.remove(node);
365 postRemove(node);
366 }
367 }
368
369 /** {@inheritDoc} */
370 public Edge<N, E> createEdge(final Node<N, E> source, final Node<N, E> target, final E value)
371 {
372 if (preCreateEdge(source, target, value))
373 {
374 Edge<N, E> edge = super.createEdge(source, target, value);
375 postCreateEdge(source, target, value, edge);
376 return edge;
377 }
378 // TODO: explicitly document this behaviour
379 return null;
380 }
381
382 /** {@inheritDoc} */
383 public void remove(final Edge<N, E> edge)
384 {
385 if (preRemove(edge))
386 {
387 super.remove(edge);
388 postRemove(edge);
389 }
390 }
391 }