All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.graphstream.graph.Graph Maven / Gradle / Ivy

Go to download

The GraphStream library. With GraphStream you deal with graphs. Static and Dynamic. You create them from scratch, from a file or any source. You display and render them. This is the core package that contains the minimal needed to read and write a graph.

There is a newer version: 2.0
Show newest version
/*
 * Copyright 2006 - 2013
 *     Stefan Balev     
 *     Julien Baudry    
 *     Antoine Dutot    
 *     Yoann Pigné      
 *     Guilhelm Savin   
 * 
 * This file is part of GraphStream .
 * 
 * GraphStream is a library whose purpose is to handle static or dynamic
 * graph, create them from scratch, file or any source and display them.
 * 
 * This program is free software distributed under the terms of two licenses, the
 * CeCILL-C license that fits European law, and the GNU Lesser General Public
 * License. You can  use, modify and/ or redistribute the software under the terms
 * of the CeCILL-C license as circulated by CEA, CNRS and INRIA at the following
 * URL  or under the terms of the GNU LGPL as published by
 * the Free Software Foundation, either version 3 of the License, or (at your
 * option) any later version.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see .
 * 
 * The fact that you are presently reading this means that you have had
 * knowledge of the CeCILL-C and LGPL licenses and that you accept their terms.
 */
package org.graphstream.graph;

import java.io.IOException;

import org.graphstream.stream.AttributeSink;
import org.graphstream.stream.ElementSink;
import org.graphstream.stream.GraphParseException;
import org.graphstream.stream.Pipe;
import org.graphstream.stream.file.FileSink;
import org.graphstream.stream.file.FileSource;


/**
 * An Interface that advises general purpose methods for handling graphs.
 * 
 * 

* This interface is one of the main interfaces of GraphStream. It defines the * services provided by a graph structure. Graphs implementations must at least * implement this interface (but are free to provide more services). *

* *

* With {@link org.graphstream.stream.Source}, * {@link org.graphstream.stream.Sink} and {@link org.graphstream.stream.Pipe}, * this interface is one of the most important. A graph is a * {@link org.graphstream.stream.Pipe} that buffers the graph events and present * the graph structure as it is actually. *

* *

* In other words, it allows to browse the graph structure, to explore it, to * modify it, and to implement algorithms on it. This class can be seen as a * snapshot of a stream of event at current time. *

* *

* With factories ({@link org.graphstream.graph.NodeFactory}, * {@link org.graphstream.graph.EdgeFactory}), users can define their own models * of nodes or edges. Problem is that when you define such model, you want to * access to elements with the valid type, without cast if possible. To improve * the access to elements in such cases, Graph offers implicit genericity to * access nodes or edges. The following is an example of an access without * genericity : * *

 * 	Graph g = ... ;
 * 	g.setNodeFactory( new MyNodeFactory() );
 *  g.addNode("root");
 *  
 *  MyNode n = (MyNode) g.getNode("root");
 *  
 *  for( Node o : g.getEachNode() )
 *  {
 *  	MyNode node = (MyNode) o;
 *  	// Do something with node
 *  }
 * 
* * With implicit genericity offers by Graph, this can be done easier: * *
 *  Graph g = ... ;
 * 	g.setNodeFactory( new MyNodeFactory() );
 *  g.addNode("root");
 *  
 *  MyNode n = g.getNode("root");
 *  
 *  for( MyNode node : g.getEachNode() )
 *  {
 *  	// Do something with node
 *  }
 * 
* *

* *

* Graph elements (nodes and edges) can be accessed using their identifier or * their index. Each node / edge has a unique string identifier assigned when * the element is created. Each element has an automatically maintained unique * index between 0 and {@link #getNodeCount()} - 1 or {@link #getEdgeCount()} - * 1. When a new element is added, its index is getNodeCount() - 1 * or getEdgeCount() - 1. When an element is removed, the element * with the biggest index takes its place. Unlike identifiers, indices can * change when the graph is modified, but they are always successive. A loop of * the form * *

 * for (int i = 0; i < g.getNodeCount(); i++) {
 * 	Node node = g.getNode(i);
 * 	// Do something with node
 * }
 * 
* * will always iterate on all the nodes of g. *

*/ public interface Graph extends Element, Pipe, Iterable, Structure { // Access /** * Get a node by its identifier. This method is implicitly generic and * returns something which extends Node. The return type is the one of the * left part of the assignment. For example, in the following call : * *
	 * ExtendedNode node = graph.getNode("...");
	 * 
* * the method will return an ExtendedNode node. If no left part exists, * method will just return a Node. * * @param id * Identifier of the node to find. * @return The searched node or null if not found. */ T getNode(String id); /** * Get an edge by its identifier. This method is implicitly generic and * returns something which extends Edge. The return type is the one of the * left part of the assignment. For example, in the following call : * *
	 * ExtendedEdge edge = graph.getEdge("...");
	 * 
* * the method will return an ExtendedEdge edge. If no left part exists, * method will just return an Edge. * * @param id * Identifier of the edge to find. * @return The searched edge or null if not found. */ T getEdge(String id); /** * The factory used to create node instances. The factory can be changed to * refine the node class generated for this graph. * * @see #setNodeFactory(NodeFactory) * @see #edgeFactory() */ NodeFactory nodeFactory(); /** * The factory used to create edge instances. The factory can be changed to * refine the edge class generated for this graph. * * @see #setEdgeFactory(EdgeFactory) * @see #nodeFactory() */ EdgeFactory edgeFactory(); /** * Is strict checking enabled? If strict checking is enabled the graph * checks for name space conflicts (e.g. insertion of two nodes with the * same name), removal of non-existing elements, use of non existing * elements (create an edge between two non existing nodes). Graph * implementations are free to respect strict checking or not. * * @return True if enabled. */ boolean isStrict(); /** * Is the automatic creation of missing elements enabled?. If strict * checking is disabled and auto-creation is enabled, when an edge is * created and one or two of its nodes are not already present in the graph, * the nodes are automatically created. * * @return True if enabled. */ boolean isAutoCreationEnabled(); /** * If true, when accessing an attribute that does not exist (or is not of * the expected type), a {@link NullAttributeException} is thrown. Else null * is returned. * * @return True if exceptions must be thrown when accessing a null * attribute. */ boolean nullAttributesAreErrors(); /** * The current step. * * @return The step. */ double getStep(); // Command /** * Should a {@link NullAttributeException} be thrown when one tries to * access a non existing attribute, or an attribute whose type is not the * expected one?. * * @param on * if true, exceptions will be thrown when accessing a non * existing attribute. */ void setNullAttributesAreErrors(boolean on); /** * Set the node factory used to create nodes. * * @param nf * the new NodeFactory */ void setNodeFactory(NodeFactory nf); /** * Set the edge factory used to create edges. * * @param ef * the new EdgeFactory */ void setEdgeFactory(EdgeFactory ef); /** * Enable or disable strict checking. * * @see #isStrict() * @param on * True or false. */ void setStrict(boolean on); /** * Enable or disable the automatic creation of missing elements. * * @see #isAutoCreationEnabled() * @param on * True or false. */ void setAutoCreate(boolean on); // Graph construction /** * Empty the graph completely by removing any references to nodes or edges. * Every attribute is also removed. However, listeners are kept. * * @see #clearSinks() */ void clear(); /** * Add a node in the graph. *

* This acts as a factory, creating the node instance automatically (and * eventually using the node factory provided). An event is generated toward * the listeners. If strict checking is enabled, and a node already exists * with this identifier, an * {@link org.graphstream.graph.IdAlreadyInUseException} is raised. Else the * error is silently ignored and the already existing node is returned. *

*

* This method is implicitly generic and returns something which extends * Node. The return type is the one of the left part of the assignment. For * example, in the following call : * *

	 * ExtendedNode n = graph.addNode("...");
	 * 
* * the method will return an ExtendedNode. If no left part exists, method * will just return a Node. *

* * @param id * Arbitrary and unique string identifying the node. * @return The created node (or the already existing node). * @throws IdAlreadyInUseException * If strict checking is enabled the identifier is already used. */ T addNode(String id) throws IdAlreadyInUseException; /** * Remove a node using its identifier. *

* An event is generated toward the listeners. Note that removing a node may * remove all edges it is connected to. In this case corresponding events * will also be generated toward the listeners. *

*

* This method is implicitly generic and return something which extends * Node. The return type is the one of the left part of the assignment. For * example, in the following call : * *

	 * ExtendedNode n = graph.removeNode("...");
	 * 
* * the method will return an ExtendedNode. If no left part exists, method * will just return a Node. *

* * @param id * The unique identifier of the node to remove. * @return The removed node. If strict checking is disabled, it can return * null if the node to remove does not exist. * @throws ElementNotFoundException * If no node matches the given identifier and strict checking * is enabled. */ T removeNode(String id) throws ElementNotFoundException; /** * Adds an undirected edge between nodes. * *

* The behavior of this method depends on many conditions. It can be * summarized as follows. *

* *

* First of all, the method checks if the graph already contains an edge * with the same id. If this is the case and strict checking is enabled, * {@code IdAlreadyInUseException} is thrown. If the strict checking is * disabled the method returns a reference to the existing edge if it has * endpoints {@code node1} and {@code node2} (in the same order if the edge * is directed) or {@code null} otherwise. *

* *

* In the case when the graph does not contain an edge with the same id, the * method checks if {@code node1} and {@code node2} exist. If one or both of * them do not exist, and strict checking is enabled, {@code * ElementNotFoundException} is thrown. Otherwise if auto-creation is * disabled, the method returns {@code null}. If auto-creation is enabled, * the method creates the missing endpoints. * *

* When the edge id is not already in use and the both endpoints exist (or * created), the edge can still be rejected. It may happen for example when * it connects two already connected nodes in a single graph. If the edge is * rejected, the method throws {@code EdgeRejectedException} if strict * checking is enabled or returns {@code null} otherwise. Finally, if the * edge is accepted, it is created using the corresponding edge factory and * a reference to it is returned. * *

* An edge creation event is sent toward the listeners. If new nodes are * created, the corresponding events are also sent to the listeners. *

* *

* This method is implicitly generic and return something which extends * Edge. The return type is the one of the left part of the assignment. For * example, in the following call : * *

	 * ExtendedEdge e = graph.addEdge("...", "...", "...");
	 * 
* * the method will return an ExtendedEdge. If no left part exists, method * will just return an Edge. *

* * @param id * Unique and arbitrary string identifying the edge. * @param node1 * The first node identifier. * @param node2 * The second node identifier. * * @return The newly created edge, an existing edge or {@code null} (see the * detailed description above) * @throws IdAlreadyInUseException * If an edge with the same id already exists and strict * checking is enabled. * @throws ElementNotFoundException * If strict checking is enabled, and 'node1' or 'node2' are not * registered in the graph. * @throws EdgeRejectedException * If strict checking is enabled and the edge is not accepted. */ T addEdge(String id, String node1, String node2) throws IdAlreadyInUseException, ElementNotFoundException, EdgeRejectedException; /** * Like {@link #addEdge(String, String, String)}, but this edge can be * directed between the two given nodes. If directed, the edge goes in the * 'from' -> 'to' direction. An event is sent toward the listeners. * * @param id * Unique and arbitrary string identifying the edge. * @param node1 * The first node identifier. * @param node2 * The second node identifier. * @param directed * Is the edge directed? * @return The newly created edge, an existing edge or {@code null} (see the * detailed description above) * @throws IdAlreadyInUseException * If an edge with the same id already exists and strict * checking is enabled. * @throws ElementNotFoundException * If strict checking is enabled, and 'node1' or 'node2' are not * registered in the graph. * @throws EdgeRejectedException * If strict checking is enabled and the edge is not accepted. * @see #addEdge(String, String, String) */ T addEdge(String id, String from, String to, boolean directed) throws IdAlreadyInUseException, ElementNotFoundException; /** * Remove an edge given the identifiers of its two endpoints. *

* If the edge is directed it is removed only if its source and destination * nodes are identified by 'from' and 'to' respectively. If the graph is a * multi-graph and there are several edges between the two nodes, one of the * edges at random is removed. An event is sent toward the listeners. If * strict checking is enabled and at least one of the two given nodes does * not exist or if they are not connected, a not found exception is raised. * Else the error is silently ignored, and null is returned. *

*

* This method is implicitly generic and return something which extends * Edge. The return type is the one of the left part of the assignment. For * example, in the following call : * *

	 * ExtendedEdge e = graph.removeEdge("...", "...");
	 * 
* * the method will return an ExtendedEdge. If no left part exists, method * will just return an Edge. *

* * @param from * The origin node identifier to select the edge. * @param to * The destination node identifier to select the edge. * @return The removed edge, or null if strict checking is disabled and at * least one of the two given nodes does not exist or there is no * edge between them * @throws ElementNotFoundException * If the 'from' or 'to' node is not registered in the graph or * not connected and strict checking is enabled. */ T removeEdge(String from, String to) throws ElementNotFoundException; /** * Removes an edge knowing its identifier. An event is sent toward the * listeners. If strict checking is enabled and the edge does not exist, * {@code ElementNotFoundException} is raised. Otherwise the error is * silently ignored and null is returned. *

* This method is implicitly generic and returns something which extends * Edge. The return type is the one of the left part of the assignment. For * example, in the following call : * *

	 * ExtendedEdge e = graph.removeEdge("...");
	 * 
* * the method will return an ExtendedEdge. If no left part exists, method * will just return an Edge. *

* * @param id * Identifier of the edge to remove. * @return The removed edge, or null if strict checking is disabled and the * edge does not exist. * @throws ElementNotFoundException * If no edge matches the identifier and strict checking is * enabled. */ T removeEdge(String id) throws ElementNotFoundException; /** *

* Since dynamic graphs are based on discrete event modifications, the * notion of step is defined to simulate elapsed time between events. So a * step is a event that occurs in the graph, it does not modify it but it * gives a kind of timestamp that allows the tracking of the progress of the * graph over the time. *

*

* This kind of event is useful for dynamic algorithms that listen to the * dynamic graph and need to measure the time in the graph's evolution. *

* * @param time * A numerical value that may give a timestamp to track the * evolution of the graph over the time. */ void stepBegins(double time); // Source // XXX do we put the iterable attributeSinks and elementSinks in Source ? /** * Returns an "iterable" of {@link AttributeSink} objects registered to this * graph. * * @return the set of {@link AttributeSink} under the form of an iterable * object. */ Iterable attributeSinks(); /** * Returns an "iterable" of {@link ElementSink} objects registered to this * graph. * * @return the list of {@link ElementSink} under the form of an iterable * object. */ Iterable elementSinks(); // Utility shortcuts (should be mixins or traits, what are you doing Mr Java // ?) // XXX use a Readable/Writable/Displayable interface for this ? /** * Utility method to read a graph. This method tries to identify the graph * format by itself and instantiates the corresponding reader automatically. * If this process fails, a NotFoundException is raised. * * @param filename * The graph filename (or URL). * @throws ElementNotFoundException * If the file cannot be found or if the format is not * recognized. * @throws GraphParseException * If there is a parsing error while reading the file. * @throws IOException * If an input output error occurs during the graph reading. */ void read(String filename) throws IOException, GraphParseException, ElementNotFoundException; /** * Utility method to read a graph using the given reader. * * @param input * An appropriate reader for the filename. * @param filename * The graph filename (or URL). * @throws ElementNotFoundException * If the file cannot be found or if the format is not * recognised. * @throws GraphParseException * If there is a parsing error while reading the file. * @throws IOException * If an input/output error occurs during the graph reading. */ void read(FileSource input, String filename) throws IOException, GraphParseException; /** * Utility method to write a graph in DGS format to a file. * * @param filename * The file that will contain the saved graph (or URL). * @throws IOException * If an input/output error occurs during the graph writing. */ void write(String filename) throws IOException; /** * Utility method to write a graph in the chosen format to a file. * * @param filename * The file that will contain the saved graph (or URL). * @param output * The output format to use. * @throws IOException * If an input/output error occurs during the graph writing. */ void write(FileSink output, String filename) throws IOException; /** * Utility method that creates a new graph viewer, and register the graph in * it. Notice that this method is a quick way to see a graph, and only this. * It can be used to prototype a program, but may be limited. This method * automatically launch a graph layout algorithm in its own thread to * compute best node positions. * * @see org.graphstream.ui.swingViewer.Viewer * @see #display(boolean ) * @return a graph viewer that allows to command the viewer (it often run in * another thread). */ org.graphstream.ui.swingViewer.Viewer display(); /** * Utility method that creates a new graph viewer, and register the graph in * it. Notice that this method is a quick way to see a graph, and only this. * It can be used to prototype a program, but is very limited. * * @param autoLayout * If true a layout algorithm is launched in its own thread to * compute best node positions. * @see org.graphstream.ui.swingViewer.Viewer * @see #display() * @return a graph viewer that allows to command the viewer (it often run in * another thread). */ org.graphstream.ui.swingViewer.Viewer display(boolean autoLayout); // New methods /** * Get a node by its index. This method is implicitly generic and returns * something which extends Node. The return type is the one of the left part * of the assignment. For example, in the following call : * *
	 * ExtendedNode node = graph.getNode(index);
	 * 
* * the method will return an ExtendedNode node. If no left part exists, * method will just return a Node. * * @param index * Index of the node to find. * @return The node with the given index * @throws IndexOutOfBoundsException * If the index is negative or greater than {@code * getNodeCount() - 1}. */ T getNode(int index) throws IndexOutOfBoundsException; /** * Get an edge by its index. This method is implicitly generic and returns * something which extends Edge. The return type is the one of the left part * of the assignment. For example, in the following call : * *
	 * ExtendedEdge edge = graph.getEdge(index);
	 * 
* * the method will return an ExtendedEdge edge. If no left part exists, * method will just return an Edge. * * @param index * The index of the edge to find. * @return The edge with the given index * @throws IndexOutOfBoundsException * if the index is less than 0 or greater than {@code * getNodeCount() - 1}. */ T getEdge(int index) throws IndexOutOfBoundsException; /** * Like {@link #addEdge(String, String, String)} but the nodes are * identified by their indices. * * @param id * Unique and arbitrary string identifying the edge. * @param index1 * The first node index * @param index2 * The second node index * @return The newly created edge, an existing edge or {@code null} * @throws IndexOutOfBoundsException * If node indices are negative or greater than {@code * getNodeCount() - 1} * @throws IdAlreadyInUseException * If an edge with the same id already exists and strict * checking is enabled. * @throws EdgeRejectedException * If strict checking is enabled and the edge is not accepted. * @see #addEdge(String, String, String) */ T addEdge(String id, int index1, int index2) throws IndexOutOfBoundsException, IdAlreadyInUseException, EdgeRejectedException; /** * Like {@link #addEdge(String, String, String, boolean)} but the nodes are * identified by their indices. * * @param id * Unique and arbitrary string identifying the edge. * @param toIndex * The first node index * @param fromIndex * The second node index * @param directed * Is the edge directed? * @return The newly created edge, an existing edge or {@code null} * @throws IndexOutOfBoundsException * If node indices are negative or greater than {@code * getNodeCount() - 1} * @throws IdAlreadyInUseException * If an edge with the same id already exists and strict * checking is enabled. * @throws EdgeRejectedException * If strict checking is enabled and the edge is not accepted. * @see #addEdge(String, String, String) */ T addEdge(String id, int fromIndex, int toIndex, boolean directed) throws IndexOutOfBoundsException, IdAlreadyInUseException, EdgeRejectedException; /** * Like {@link #addEdge(String, String, String)} but the node references are * given instead of node identifiers. * * @param id * Unique and arbitrary string identifying the edge. * @param node1 * The first node * @param node2 * The second node * @return The newly created edge, an existing edge or {@code null} * @throws IdAlreadyInUseException * If an edge with the same id already exists and strict * checking is enabled. * @throws EdgeRejectedException * If strict checking is enabled and the edge is not accepted. * @see #addEdge(String, String, String) */ T addEdge(String id, Node node1, Node node2) throws IdAlreadyInUseException, EdgeRejectedException; /** * Like {@link #addEdge(String, String, String, boolean)} but the node * references are given instead of node identifiers. * * @param id * Unique and arbitrary string identifying the edge. * @param from * The first node * @param to * The second node * @param directed * Is the edge directed? * @return The newly created edge, an existing edge or {@code null} * @throws IdAlreadyInUseException * If an edge with the same id already exists and strict * checking is enabled. * @throws EdgeRejectedException * If strict checking is enabled and the edge is not accepted. * @see #addEdge(String, String, String) */ T addEdge(String id, Node from, Node to, boolean directed) throws IdAlreadyInUseException, EdgeRejectedException; /** * Removes an edge with a given index. An event is sent toward the * listeners. * *

* This method is implicitly generic and returns something which extends * Edge. The return type is the one of the left part of the assignment. For * example, in the following call : * *

	 * ExtendedEdge edge = graph.removeEdge(i);
	 * 
* * the method will return an ExtendedEdge edge. If no left part exists, * method will just return an Edge. *

* * @param index * The index of the edge to be removed. * @return The removed edge * @throws IndexOutOfBoundsException * if the index is negative or greater than {@code * getEdgeCount() - 1} */ T removeEdge(int index) throws IndexOutOfBoundsException; /** * Removes an edge between two nodes. Like * {@link #removeEdge(String, String)} but the nodes are identified by their * indices. * * @param fromIndex * the index of the source node * @param toIndex * the index of the target node * @return the removed edge or {@code null} if no edge is removed * @throws IndexOutOfBoundsException * If one of the node indices is negative or greater than * {@code getNodeCount() - 1}. * @throws ElementNotFoundException * if strict checking is enabled and there is no edge between * the two nodes. * @see #removeEdge(String, String) */ T removeEdge(int fromIndex, int toIndex) throws IndexOutOfBoundsException, ElementNotFoundException; /** * Removes an edge between two nodes. Like * {@link #removeEdge(String, String)} but node references are given instead * of node identifiers. * * @param node1 * the first node * @param node2 * the second node * @return the removed edge or {@code null} if no edge is removed * @throws ElementNotFoundException * if strict checking is enabled and there is no edge between * the two nodes. * @see #removeEdge(String, String) */ T removeEdge(Node node1, Node node2) throws ElementNotFoundException; /** * Removes an edge. An event is sent toward the listeners. *

* This method is implicitly generic and returns something which extends * Edge. The return type is the one of the left part of the assignment. For * example, in the following call : * *

	 * ExtendedEdge e = graph.removeEdge(...);
	 * 
* * the method will return an ExtendedEdge. If no left part exists, method * will just return an Edge. *

* * * * @param edge * The edge to be removed * @return The removed edge */ T removeEdge(Edge edge); /** * Removes a node with a given index. *

* An event is generated toward the listeners. Note that removing a node may * remove all edges it is connected to. In this case corresponding events * will also be generated toward the listeners. *

*

* This method is implicitly generic and return something which extends * Node. The return type is the one of the left part of the assignment. For * example, in the following call : * *

	 * ExtendedNode n = graph.removeNode(index);
	 * 
* * the method will return an ExtendedNode. If no left part exists, method * will just return a Node. *

* * @param index * The index of the node to be removed * @return The removed node * @throws IndexOutOfBoundsException * if the index is negative or greater than {@code * getNodeCount() - 1}. */ T removeNode(int index) throws IndexOutOfBoundsException; /** * Removes a node. *

* An event is generated toward the listeners. Note that removing a node may * remove all edges it is connected to. In this case corresponding events * will also be generated toward the listeners. *

*

* This method is implicitly generic and return something which extends * Node. The return type is the one of the left part of the assignment. For * example, in the following call : * *

	 * ExtendedNode n = graph.removeNode(...);
	 * 
* * the method will return an ExtendedNode. If no left part exists, method * will just return a Node. *

* * @param node * The node to be removed * @return The removed node */ T removeNode(Node node); }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy