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 }