View Javadoc

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&lt;N, E&gt;)</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&lt;N, E&gt;)</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&lt;N, E&gt;)</code> method has just been
289      * called on the wrapped graph with the specified parameter.
290      *
291      * @param node <code>remove(Node&lt;N, E&gt;)</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&lt;N, E&gt;)</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&lt;N, E&gt;)</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&lt;N, E&gt;)</code> method has just been
330      * called on the wrapped graph with the specified parameter.
331      *
332      * @param edge <code>remove(Edge&lt;N, E&gt;)</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 }