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 < 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("..."); 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("..."); 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("..."); 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("..."); 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("...", "...", "..."); 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' -> '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("...", "..."); 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("..."); 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}