001/*
002 * Copyright 2006 - 2013
003 *     Stefan Balev     <stefan.balev@graphstream-project.org>
004 *     Julien Baudry    <julien.baudry@graphstream-project.org>
005 *     Antoine Dutot    <antoine.dutot@graphstream-project.org>
006 *     Yoann Pigné      <yoann.pigne@graphstream-project.org>
007 *     Guilhelm Savin   <guilhelm.savin@graphstream-project.org>
008 * 
009 * This file is part of GraphStream <http://graphstream-project.org>.
010 * 
011 * GraphStream is a library whose purpose is to handle static or dynamic
012 * graph, create them from scratch, file or any source and display them.
013 * 
014 * This program is free software distributed under the terms of two licenses, the
015 * CeCILL-C license that fits European law, and the GNU Lesser General Public
016 * License. You can  use, modify and/ or redistribute the software under the terms
017 * of the CeCILL-C license as circulated by CEA, CNRS and INRIA at the following
018 * URL <http://www.cecill.info> or under the terms of the GNU LGPL as published by
019 * the Free Software Foundation, either version 3 of the License, or (at your
020 * option) any later version.
021 * 
022 * This program is distributed in the hope that it will be useful, but WITHOUT ANY
023 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
024 * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
025 * 
026 * You should have received a copy of the GNU Lesser General Public License
027 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
028 * 
029 * The fact that you are presently reading this means that you have had
030 * knowledge of the CeCILL-C and LGPL licenses and that you accept their terms.
031 */
032package org.graphstream.graph;
033
034import java.io.IOException;
035
036import org.graphstream.stream.AttributeSink;
037import org.graphstream.stream.ElementSink;
038import org.graphstream.stream.GraphParseException;
039import org.graphstream.stream.Pipe;
040import org.graphstream.stream.file.FileSink;
041import org.graphstream.stream.file.FileSource;
042
043
044/**
045 * An Interface that advises general purpose methods for handling graphs.
046 * 
047 * <p>
048 * This interface is one of the main interfaces of GraphStream. It defines the
049 * services provided by a graph structure. Graphs implementations must at least
050 * implement this interface (but are free to provide more services).
051 * </p>
052 * 
053 * <p>
054 * With {@link org.graphstream.stream.Source},
055 * {@link org.graphstream.stream.Sink} and {@link org.graphstream.stream.Pipe},
056 * this interface is one of the most important. A graph is a
057 * {@link org.graphstream.stream.Pipe} that buffers the graph events and present
058 * the graph structure as it is actually.
059 * </p>
060 * 
061 * <p>
062 * In other words, it allows to browse the graph structure, to explore it, to
063 * modify it, and to implement algorithms on it. This class can be seen as a
064 * snapshot of a stream of event at current time.
065 * </p>
066 * 
067 * <p>
068 * With factories ({@link org.graphstream.graph.NodeFactory},
069 * {@link org.graphstream.graph.EdgeFactory}), users can define their own models
070 * of nodes or edges. Problem is that when you define such model, you want to
071 * access to elements with the valid type, without cast if possible. To improve
072 * the access to elements in such cases, Graph offers implicit genericity to
073 * access nodes or edges. The following is an example of an access without
074 * genericity :
075 * 
076 * <pre>
077 *      Graph g = ... ;
078 *      g.setNodeFactory( new MyNodeFactory() );
079 *  g.addNode("root");
080 *  
081 *  MyNode n = (MyNode) g.getNode("root");
082 *  
083 *  for( Node o : g.getEachNode() )
084 *  {
085 *      MyNode node = (MyNode) o;
086 *      // Do something with node
087 *  }
088 * </pre>
089 * 
090 * With implicit genericity offers by Graph, this can be done easier:
091 * 
092 * <pre>
093 *  Graph g = ... ;
094 *      g.setNodeFactory( new MyNodeFactory() );
095 *  g.addNode("root");
096 *  
097 *  MyNode n = g.getNode("root");
098 *  
099 *  for( MyNode node : g.getEachNode() )
100 *  {
101 *      // Do something with node
102 *  }
103 * </pre>
104 * 
105 * </p>
106 * 
107 * <p>
108 * Graph elements (nodes and edges) can be accessed using their identifier or
109 * their index. Each node / edge has a unique string identifier assigned when
110 * the element is created. Each element has an automatically maintained unique
111 * index between 0 and {@link #getNodeCount()} - 1 or {@link #getEdgeCount()} -
112 * 1. When a new element is added, its index is <code>getNodeCount() - 1</code>
113 * or <code>getEdgeCount() - 1</code>. When an element is removed, the element
114 * with the biggest index takes its place. Unlike identifiers, indices can
115 * change when the graph is modified, but they are always successive. A loop of
116 * the form
117 * 
118 * <pre>
119 * for (int i = 0; i &lt; g.getNodeCount(); i++) {
120 *      Node node = g.getNode(i);
121 *      // Do something with node
122 * }
123 * </pre>
124 * 
125 * will always iterate on all the nodes of <code>g</code>.
126 * </p>
127 */
128public interface Graph extends Element, Pipe, Iterable<Node>, Structure {
129        // Access
130
131        /**
132         * Get a node by its identifier. This method is implicitly generic and
133         * returns something which extends Node. The return type is the one of the
134         * left part of the assignment. For example, in the following call :
135         * 
136         * <pre>
137         * ExtendedNode node = graph.getNode(&quot;...&quot;);
138         * </pre>
139         * 
140         * the method will return an ExtendedNode node. If no left part exists,
141         * method will just return a Node.
142         * 
143         * @param id
144         *            Identifier of the node to find.
145         * @return The searched node or null if not found.
146         */
147        <T extends Node> T getNode(String id);
148
149        /**
150         * Get an edge by its identifier. This method is implicitly generic and
151         * returns something which extends Edge. The return type is the one of the
152         * left part of the assignment. For example, in the following call :
153         * 
154         * <pre>
155         * ExtendedEdge edge = graph.getEdge(&quot;...&quot;);
156         * </pre>
157         * 
158         * the method will return an ExtendedEdge edge. If no left part exists,
159         * method will just return an Edge.
160         * 
161         * @param id
162         *            Identifier of the edge to find.
163         * @return The searched edge or null if not found.
164         */
165        <T extends Edge> T getEdge(String id);
166
167        /**
168         * The factory used to create node instances. The factory can be changed to
169         * refine the node class generated for this graph.
170         * 
171         * @see #setNodeFactory(NodeFactory)
172         * @see #edgeFactory()
173         */
174        NodeFactory<? extends Node> nodeFactory();
175
176        /**
177         * The factory used to create edge instances. The factory can be changed to
178         * refine the edge class generated for this graph.
179         * 
180         * @see #setEdgeFactory(EdgeFactory)
181         * @see #nodeFactory()
182         */
183        EdgeFactory<? extends Edge> edgeFactory();
184
185        /**
186         * Is strict checking enabled? If strict checking is enabled the graph
187         * checks for name space conflicts (e.g. insertion of two nodes with the
188         * same name), removal of non-existing elements, use of non existing
189         * elements (create an edge between two non existing nodes). Graph
190         * implementations are free to respect strict checking or not.
191         * 
192         * @return True if enabled.
193         */
194        boolean isStrict();
195
196        /**
197         * Is the automatic creation of missing elements enabled?. If strict
198         * checking is disabled and auto-creation is enabled, when an edge is
199         * created and one or two of its nodes are not already present in the graph,
200         * the nodes are automatically created.
201         * 
202         * @return True if enabled.
203         */
204        boolean isAutoCreationEnabled();
205
206        /**
207         * If true, when accessing an attribute that does not exist (or is not of
208         * the expected type), a {@link NullAttributeException} is thrown. Else null
209         * is returned.
210         * 
211         * @return True if exceptions must be thrown when accessing a null
212         *         attribute.
213         */
214        boolean nullAttributesAreErrors();
215
216        /**
217         * The current step.
218         * 
219         * @return The step.
220         */
221        double getStep();
222
223        // Command
224
225        /**
226         * Should a {@link NullAttributeException} be thrown when one tries to
227         * access a non existing attribute, or an attribute whose type is not the
228         * expected one?.
229         * 
230         * @param on
231         *            if true, exceptions will be thrown when accessing a non
232         *            existing attribute.
233         */
234        void setNullAttributesAreErrors(boolean on);
235
236        /**
237         * Set the node factory used to create nodes.
238         * 
239         * @param nf
240         *            the new NodeFactory
241         */
242        void setNodeFactory(NodeFactory<? extends Node> nf);
243
244        /**
245         * Set the edge factory used to create edges.
246         * 
247         * @param ef
248         *            the new EdgeFactory
249         */
250        void setEdgeFactory(EdgeFactory<? extends Edge> ef);
251
252        /**
253         * Enable or disable strict checking.
254         * 
255         * @see #isStrict()
256         * @param on
257         *            True or false.
258         */
259        void setStrict(boolean on);
260
261        /**
262         * Enable or disable the automatic creation of missing elements.
263         * 
264         * @see #isAutoCreationEnabled()
265         * @param on
266         *            True or false.
267         */
268        void setAutoCreate(boolean on);
269
270        // Graph construction
271
272        /**
273         * Empty the graph completely by removing any references to nodes or edges.
274         * Every attribute is also removed. However, listeners are kept.
275         * 
276         * @see #clearSinks()
277         */
278        void clear();
279
280        /**
281         * Add a node in the graph.
282         * <p>
283         * This acts as a factory, creating the node instance automatically (and
284         * eventually using the node factory provided). An event is generated toward
285         * the listeners. If strict checking is enabled, and a node already exists
286         * with this identifier, an
287         * {@link org.graphstream.graph.IdAlreadyInUseException} is raised. Else the
288         * error is silently ignored and the already existing node is returned.
289         * </p>
290         * <p>
291         * This method is implicitly generic and returns something which extends
292         * Node. The return type is the one of the left part of the assignment. For
293         * example, in the following call :
294         * 
295         * <pre>
296         * ExtendedNode n = graph.addNode(&quot;...&quot;);
297         * </pre>
298         * 
299         * the method will return an ExtendedNode. If no left part exists, method
300         * will just return a Node.
301         * </p>
302         * 
303         * @param id
304         *            Arbitrary and unique string identifying the node.
305         * @return The created node (or the already existing node).
306         * @throws IdAlreadyInUseException
307         *             If strict checking is enabled the identifier is already used.
308         */
309        <T extends Node> T addNode(String id) throws IdAlreadyInUseException;
310
311        /**
312         * Remove a node using its identifier.
313         * <p>
314         * An event is generated toward the listeners. Note that removing a node may
315         * remove all edges it is connected to. In this case corresponding events
316         * will also be generated toward the listeners.
317         * </p>
318         * <p>
319         * This method is implicitly generic and return something which extends
320         * Node. The return type is the one of the left part of the assignment. For
321         * example, in the following call :
322         * 
323         * <pre>
324         * ExtendedNode n = graph.removeNode(&quot;...&quot;);
325         * </pre>
326         * 
327         * the method will return an ExtendedNode. If no left part exists, method
328         * will just return a Node.
329         * </p>
330         * 
331         * @param id
332         *            The unique identifier of the node to remove.
333         * @return The removed node. If strict checking is disabled, it can return
334         *         null if the node to remove does not exist.
335         * @throws ElementNotFoundException
336         *             If no node matches the given identifier and strict checking
337         *             is enabled.
338         */
339        <T extends Node> T removeNode(String id) throws ElementNotFoundException;
340
341        /**
342         * Adds an undirected edge between nodes.
343         * 
344         * <p>
345         * The behavior of this method depends on many conditions. It can be
346         * summarized as follows.
347         * </p>
348         * 
349         * <p>
350         * First of all, the method checks if the graph already contains an edge
351         * with the same id. If this is the case and strict checking is enabled,
352         * {@code IdAlreadyInUseException} is thrown. If the strict checking is
353         * disabled the method returns a reference to the existing edge if it has
354         * endpoints {@code node1} and {@code node2} (in the same order if the edge
355         * is directed) or {@code null} otherwise.
356         * </p>
357         * 
358         * <p>
359         * In the case when the graph does not contain an edge with the same id, the
360         * method checks if {@code node1} and {@code node2} exist. If one or both of
361         * them do not exist, and strict checking is enabled, {@code
362         * ElementNotFoundException} is thrown. Otherwise if auto-creation is
363         * disabled, the method returns {@code null}. If auto-creation is enabled,
364         * the method creates the missing endpoints.
365         * 
366         * <p>
367         * When the edge id is not already in use and the both endpoints exist (or
368         * created), the edge can still be rejected. It may happen for example when
369         * it connects two already connected nodes in a single graph. If the edge is
370         * rejected, the method throws {@code EdgeRejectedException} if strict
371         * checking is enabled or returns {@code null} otherwise. Finally, if the
372         * edge is accepted, it is created using the corresponding edge factory and
373         * a reference to it is returned.
374         * 
375         * <p>
376         * An edge creation event is sent toward the listeners. If new nodes are
377         * created, the corresponding events are also sent to the listeners.
378         * </p>
379         * 
380         * <p>
381         * This method is implicitly generic and return something which extends
382         * Edge. The return type is the one of the left part of the assignment. For
383         * example, in the following call :
384         * 
385         * <pre>
386         * ExtendedEdge e = graph.addEdge(&quot;...&quot;, &quot;...&quot;, &quot;...&quot;);
387         * </pre>
388         * 
389         * the method will return an ExtendedEdge. If no left part exists, method
390         * will just return an Edge.
391         * </p>
392         * 
393         * @param id
394         *            Unique and arbitrary string identifying the edge.
395         * @param node1
396         *            The first node identifier.
397         * @param node2
398         *            The second node identifier.
399         * 
400         * @return The newly created edge, an existing edge or {@code null} (see the
401         *         detailed description above)
402         * @throws IdAlreadyInUseException
403         *             If an edge with the same id already exists and strict
404         *             checking is enabled.
405         * @throws ElementNotFoundException
406         *             If strict checking is enabled, and 'node1' or 'node2' are not
407         *             registered in the graph.
408         * @throws EdgeRejectedException
409         *             If strict checking is enabled and the edge is not accepted.
410         */
411        <T extends Edge> T addEdge(String id, String node1, String node2)
412                        throws IdAlreadyInUseException, ElementNotFoundException,
413                        EdgeRejectedException;
414
415        /**
416         * Like {@link #addEdge(String, String, String)}, but this edge can be
417         * directed between the two given nodes. If directed, the edge goes in the
418         * 'from' -&gt; 'to' direction. An event is sent toward the listeners.
419         * 
420         * @param id
421         *            Unique and arbitrary string identifying the edge.
422         * @param node1
423         *            The first node identifier.
424         * @param node2
425         *            The second node identifier.
426         * @param directed
427         *            Is the edge directed?
428         * @return The newly created edge, an existing edge or {@code null} (see the
429         *         detailed description above)
430         * @throws IdAlreadyInUseException
431         *             If an edge with the same id already exists and strict
432         *             checking is enabled.
433         * @throws ElementNotFoundException
434         *             If strict checking is enabled, and 'node1' or 'node2' are not
435         *             registered in the graph.
436         * @throws EdgeRejectedException
437         *             If strict checking is enabled and the edge is not accepted.
438         * @see #addEdge(String, String, String)
439         */
440        <T extends Edge> T addEdge(String id, String from, String to,
441                        boolean directed) throws IdAlreadyInUseException,
442                        ElementNotFoundException;
443
444        /**
445         * Remove an edge given the identifiers of its two endpoints.
446         * <p>
447         * If the edge is directed it is removed only if its source and destination
448         * nodes are identified by 'from' and 'to' respectively. If the graph is a
449         * multi-graph and there are several edges between the two nodes, one of the
450         * edges at random is removed. An event is sent toward the listeners. If
451         * strict checking is enabled and at least one of the two given nodes does
452         * not exist or if they are not connected, a not found exception is raised.
453         * Else the error is silently ignored, and null is returned.
454         * </p>
455         * <p>
456         * This method is implicitly generic and return something which extends
457         * Edge. The return type is the one of the left part of the assignment. For
458         * example, in the following call :
459         * 
460         * <pre>
461         * ExtendedEdge e = graph.removeEdge(&quot;...&quot;, &quot;...&quot;);
462         * </pre>
463         * 
464         * the method will return an ExtendedEdge. If no left part exists, method
465         * will just return an Edge.
466         * </p>
467         * 
468         * @param from
469         *            The origin node identifier to select the edge.
470         * @param to
471         *            The destination node identifier to select the edge.
472         * @return The removed edge, or null if strict checking is disabled and at
473         *         least one of the two given nodes does not exist or there is no
474         *         edge between them
475         * @throws ElementNotFoundException
476         *             If the 'from' or 'to' node is not registered in the graph or
477         *             not connected and strict checking is enabled.
478         */
479        <T extends Edge> T removeEdge(String from, String to)
480                        throws ElementNotFoundException;
481
482        /**
483         * Removes an edge knowing its identifier. An event is sent toward the
484         * listeners. If strict checking is enabled and the edge does not exist,
485         * {@code ElementNotFoundException} is raised. Otherwise the error is
486         * silently ignored and null is returned.
487         * <p>
488         * This method is implicitly generic and returns something which extends
489         * Edge. The return type is the one of the left part of the assignment. For
490         * example, in the following call :
491         * 
492         * <pre>
493         * ExtendedEdge e = graph.removeEdge(&quot;...&quot;);
494         * </pre>
495         * 
496         * the method will return an ExtendedEdge. If no left part exists, method
497         * will just return an Edge.
498         * </p>
499         * 
500         * @param id
501         *            Identifier of the edge to remove.
502         * @return The removed edge, or null if strict checking is disabled and the
503         *         edge does not exist.
504         * @throws ElementNotFoundException
505         *             If no edge matches the identifier and strict checking is
506         *             enabled.
507         */
508        <T extends Edge> T removeEdge(String id) throws ElementNotFoundException;
509
510        /**
511         * <p>
512         * Since dynamic graphs are based on discrete event modifications, the
513         * notion of step is defined to simulate elapsed time between events. So a
514         * step is a event that occurs in the graph, it does not modify it but it
515         * gives a kind of timestamp that allows the tracking of the progress of the
516         * graph over the time.
517         * </p>
518         * <p>
519         * This kind of event is useful for dynamic algorithms that listen to the
520         * dynamic graph and need to measure the time in the graph's evolution.
521         * </p>
522         * 
523         * @param time
524         *            A numerical value that may give a timestamp to track the
525         *            evolution of the graph over the time.
526         */
527        void stepBegins(double time);
528
529        // Source
530        // XXX do we put the iterable attributeSinks and elementSinks in Source ?
531
532        /**
533         * Returns an "iterable" of {@link AttributeSink} objects registered to this
534         * graph.
535         * 
536         * @return the set of {@link AttributeSink} under the form of an iterable
537         *         object.
538         */
539        Iterable<AttributeSink> attributeSinks();
540
541        /**
542         * Returns an "iterable" of {@link ElementSink} objects registered to this
543         * graph.
544         * 
545         * @return the list of {@link ElementSink} under the form of an iterable
546         *         object.
547         */
548        Iterable<ElementSink> elementSinks();
549
550        // Utility shortcuts (should be mixins or traits, what are you doing Mr Java
551        // ?)
552        // XXX use a Readable/Writable/Displayable interface for this ?
553
554        /**
555         * Utility method to read a graph. This method tries to identify the graph
556         * format by itself and instantiates the corresponding reader automatically.
557         * If this process fails, a NotFoundException is raised.
558         * 
559         * @param filename
560         *            The graph filename (or URL).
561         * @throws ElementNotFoundException
562         *             If the file cannot be found or if the format is not
563         *             recognized.
564         * @throws GraphParseException
565         *             If there is a parsing error while reading the file.
566         * @throws IOException
567         *             If an input output error occurs during the graph reading.
568         */
569        void read(String filename) throws IOException, GraphParseException,
570                        ElementNotFoundException;
571
572        /**
573         * Utility method to read a graph using the given reader.
574         * 
575         * @param input
576         *            An appropriate reader for the filename.
577         * @param filename
578         *            The graph filename (or URL).
579         * @throws ElementNotFoundException
580         *             If the file cannot be found or if the format is not
581         *             recognised.
582         * @throws GraphParseException
583         *             If there is a parsing error while reading the file.
584         * @throws IOException
585         *             If an input/output error occurs during the graph reading.
586         */
587        void read(FileSource input, String filename) throws IOException,
588                        GraphParseException;
589
590        /**
591         * Utility method to write a graph in DGS format to a file.
592         * 
593         * @param filename
594         *            The file that will contain the saved graph (or URL).
595         * @throws IOException
596         *             If an input/output error occurs during the graph writing.
597         */
598        void write(String filename) throws IOException;
599
600        /**
601         * Utility method to write a graph in the chosen format to a file.
602         * 
603         * @param filename
604         *            The file that will contain the saved graph (or URL).
605         * @param output
606         *            The output format to use.
607         * @throws IOException
608         *             If an input/output error occurs during the graph writing.
609         */
610        void write(FileSink output, String filename) throws IOException;
611
612        /**
613         * Utility method that creates a new graph viewer, and register the graph in
614         * it. Notice that this method is a quick way to see a graph, and only this.
615         * It can be used to prototype a program, but may be limited. This method
616         * automatically launch a graph layout algorithm in its own thread to
617         * compute best node positions.
618         * 
619         * @see org.graphstream.ui.swingViewer.Viewer
620         * @see #display(boolean )
621         * @return a graph viewer that allows to command the viewer (it often run in
622         *         another thread).
623         */
624        org.graphstream.ui.swingViewer.Viewer display();
625
626        /**
627         * Utility method that creates a new graph viewer, and register the graph in
628         * it. Notice that this method is a quick way to see a graph, and only this.
629         * It can be used to prototype a program, but is very limited.
630         * 
631         * @param autoLayout
632         *            If true a layout algorithm is launched in its own thread to
633         *            compute best node positions.
634         * @see org.graphstream.ui.swingViewer.Viewer
635         * @see #display()
636         * @return a graph viewer that allows to command the viewer (it often run in
637         *         another thread).
638         */
639        org.graphstream.ui.swingViewer.Viewer display(boolean autoLayout);
640
641        // New methods
642
643        /**
644         * Get a node by its index. This method is implicitly generic and returns
645         * something which extends Node. The return type is the one of the left part
646         * of the assignment. For example, in the following call :
647         * 
648         * <pre>
649         * ExtendedNode node = graph.getNode(index);
650         * </pre>
651         * 
652         * the method will return an ExtendedNode node. If no left part exists,
653         * method will just return a Node.
654         * 
655         * @param index
656         *            Index of the node to find.
657         * @return The node with the given index
658         * @throws IndexOutOfBoundsException
659         *             If the index is negative or greater than {@code
660         *             getNodeCount() - 1}.
661         */
662        <T extends Node> T getNode(int index) throws IndexOutOfBoundsException;
663
664        /**
665         * Get an edge by its index. This method is implicitly generic and returns
666         * something which extends Edge. The return type is the one of the left part
667         * of the assignment. For example, in the following call :
668         * 
669         * <pre>
670         * ExtendedEdge edge = graph.getEdge(index);
671         * </pre>
672         * 
673         * the method will return an ExtendedEdge edge. If no left part exists,
674         * method will just return an Edge.
675         * 
676         * @param index
677         *            The index of the edge to find.
678         * @return The edge with the given index
679         * @throws IndexOutOfBoundsException
680         *             if the index is less than 0 or greater than {@code
681         *             getNodeCount() - 1}.
682         */
683        <T extends Edge> T getEdge(int index) throws IndexOutOfBoundsException;
684
685        /**
686         * Like {@link #addEdge(String, String, String)} but the nodes are
687         * identified by their indices.
688         * 
689         * @param id
690         *            Unique and arbitrary string identifying the edge.
691         * @param index1
692         *            The first node index
693         * @param index2
694         *            The second node index
695         * @return The newly created edge, an existing edge or {@code null}
696         * @throws IndexOutOfBoundsException
697         *             If node indices are negative or greater than {@code
698         *             getNodeCount() - 1}
699         * @throws IdAlreadyInUseException
700         *             If an edge with the same id already exists and strict
701         *             checking is enabled.
702         * @throws EdgeRejectedException
703         *             If strict checking is enabled and the edge is not accepted.
704         * @see #addEdge(String, String, String)
705         */
706        <T extends Edge> T addEdge(String id, int index1, int index2)
707                        throws IndexOutOfBoundsException, IdAlreadyInUseException,
708                        EdgeRejectedException;
709
710        /**
711         * Like {@link #addEdge(String, String, String, boolean)} but the nodes are
712         * identified by their indices.
713         * 
714         * @param id
715         *            Unique and arbitrary string identifying the edge.
716         * @param toIndex
717         *            The first node index
718         * @param fromIndex
719         *            The second node index
720         * @param directed
721         *            Is the edge directed?
722         * @return The newly created edge, an existing edge or {@code null}
723         * @throws IndexOutOfBoundsException
724         *             If node indices are negative or greater than {@code
725         *             getNodeCount() - 1}
726         * @throws IdAlreadyInUseException
727         *             If an edge with the same id already exists and strict
728         *             checking is enabled.
729         * @throws EdgeRejectedException
730         *             If strict checking is enabled and the edge is not accepted.
731         * @see #addEdge(String, String, String)
732         */
733        <T extends Edge> T addEdge(String id, int fromIndex, int toIndex,
734                        boolean directed) throws IndexOutOfBoundsException,
735                        IdAlreadyInUseException, EdgeRejectedException;
736
737        /**
738         * Like {@link #addEdge(String, String, String)} but the node references are
739         * given instead of node identifiers.
740         * 
741         * @param id
742         *            Unique and arbitrary string identifying the edge.
743         * @param node1
744         *            The first node
745         * @param node2
746         *            The second node
747         * @return The newly created edge, an existing edge or {@code null}
748         * @throws IdAlreadyInUseException
749         *             If an edge with the same id already exists and strict
750         *             checking is enabled.
751         * @throws EdgeRejectedException
752         *             If strict checking is enabled and the edge is not accepted.
753         * @see #addEdge(String, String, String)
754         */
755        <T extends Edge> T addEdge(String id, Node node1, Node node2)
756                        throws IdAlreadyInUseException, EdgeRejectedException;
757
758        /**
759         * Like {@link #addEdge(String, String, String, boolean)} but the node
760         * references are given instead of node identifiers.
761         * 
762         * @param id
763         *            Unique and arbitrary string identifying the edge.
764         * @param from
765         *            The first node
766         * @param to
767         *            The second node
768         * @param directed
769         *            Is the edge directed?
770         * @return The newly created edge, an existing edge or {@code null}
771         * @throws IdAlreadyInUseException
772         *             If an edge with the same id already exists and strict
773         *             checking is enabled.
774         * @throws EdgeRejectedException
775         *             If strict checking is enabled and the edge is not accepted.
776         * @see #addEdge(String, String, String)
777         */
778        <T extends Edge> T addEdge(String id, Node from, Node to, boolean directed)
779                        throws IdAlreadyInUseException, EdgeRejectedException;
780
781        /**
782         * Removes an edge with a given index. An event is sent toward the
783         * listeners.
784         * 
785         * <p>
786         * This method is implicitly generic and returns something which extends
787         * Edge. The return type is the one of the left part of the assignment. For
788         * example, in the following call :
789         * 
790         * <pre>
791         * ExtendedEdge edge = graph.removeEdge(i);
792         * </pre>
793         * 
794         * the method will return an ExtendedEdge edge. If no left part exists,
795         * method will just return an Edge.
796         * </p>
797         * 
798         * @param index
799         *            The index of the edge to be removed.
800         * @return The removed edge
801         * @throws IndexOutOfBoundsException
802         *             if the index is negative or greater than {@code
803         *             getEdgeCount() - 1}
804         */
805        <T extends Edge> T removeEdge(int index) throws IndexOutOfBoundsException;
806
807        /**
808         * Removes an edge between two nodes. Like
809         * {@link #removeEdge(String, String)} but the nodes are identified by their
810         * indices.
811         * 
812         * @param fromIndex
813         *            the index of the source node
814         * @param toIndex
815         *            the index of the target node
816         * @return the removed edge or {@code null} if no edge is removed
817         * @throws IndexOutOfBoundsException
818         *             If one of the node indices is negative or greater than
819         *             {@code getNodeCount() - 1}.
820         * @throws ElementNotFoundException
821         *             if strict checking is enabled and there is no edge between
822         *             the two nodes.
823         * @see #removeEdge(String, String)
824         */
825        <T extends Edge> T removeEdge(int fromIndex, int toIndex)
826                        throws IndexOutOfBoundsException, ElementNotFoundException;
827
828        /**
829         * Removes an edge between two nodes. Like
830         * {@link #removeEdge(String, String)} but node references are given instead
831         * of node identifiers.
832         * 
833         * @param node1
834         *            the first node
835         * @param node2
836         *            the second node
837         * @return the removed edge or {@code null} if no edge is removed
838         * @throws ElementNotFoundException
839         *             if strict checking is enabled and there is no edge between
840         *             the two nodes.
841         * @see #removeEdge(String, String)
842         */
843        <T extends Edge> T removeEdge(Node node1, Node node2)
844                        throws ElementNotFoundException;
845
846        /**
847         * Removes an edge. An event is sent toward the listeners.
848         * <p>
849         * This method is implicitly generic and returns something which extends
850         * Edge. The return type is the one of the left part of the assignment. For
851         * example, in the following call :
852         * 
853         * <pre>
854         * ExtendedEdge e = graph.removeEdge(...);
855         * </pre>
856         * 
857         * the method will return an ExtendedEdge. If no left part exists, method
858         * will just return an Edge.
859         * </p>
860         * 
861         * 
862         * 
863         * @param edge
864         *            The edge to be removed
865         * @return The removed edge
866         */
867        <T extends Edge> T removeEdge(Edge edge);
868
869        /**
870         * Removes a node with a given index.
871         * <p>
872         * An event is generated toward the listeners. Note that removing a node may
873         * remove all edges it is connected to. In this case corresponding events
874         * will also be generated toward the listeners.
875         * </p>
876         * <p>
877         * This method is implicitly generic and return something which extends
878         * Node. The return type is the one of the left part of the assignment. For
879         * example, in the following call :
880         * 
881         * <pre>
882         * ExtendedNode n = graph.removeNode(index);
883         * </pre>
884         * 
885         * the method will return an ExtendedNode. If no left part exists, method
886         * will just return a Node.
887         * </p>
888         * 
889         * @param index
890         *            The index of the node to be removed
891         * @return The removed node
892         * @throws IndexOutOfBoundsException
893         *             if the index is negative or greater than {@code
894         *             getNodeCount() - 1}.
895         */
896        <T extends Node> T removeNode(int index) throws IndexOutOfBoundsException;
897
898        /**
899         * Removes a node.
900         * <p>
901         * An event is generated toward the listeners. Note that removing a node may
902         * remove all edges it is connected to. In this case corresponding events
903         * will also be generated toward the listeners.
904         * </p>
905         * <p>
906         * This method is implicitly generic and return something which extends
907         * Node. The return type is the one of the left part of the assignment. For
908         * example, in the following call :
909         * 
910         * <pre>
911         * ExtendedNode n = graph.removeNode(...);
912         * </pre>
913         * 
914         * the method will return an ExtendedNode. If no left part exists, method
915         * will just return a Node.
916         * </p>
917         * 
918         * @param node
919         *            The node to be removed
920         * @return The removed node
921         */
922        <T extends Node> T removeNode(Node node);
923}