/*
Copyright 2008-2010 Gephi
Authors : Mathieu Bastian <mathieu.bastian@gephi.org>
Website : http://www.gephi.org
This file is part of Gephi.
Gephi is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
Gephi 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with Gephi. If not, see <http://www.gnu.org/licenses/>.
*/
package org.gephi.graph.api;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* Main interface for accessing the graph structure and develop algorithms.
* <p>
* A graph object belongs to a graph model, which really contains the data. Graph
* objects are therefore only accessors, with all convinient methods to read and
* modify the structure. Hence, <b>multiple</b> <code>Graph</code> objects can
* exists.
* <h3>Get current graph</h3>
* <pre>
* GraphController graphController = Lookup.getDefault().lookup(GraphController.class);
* GraphModel model = graphController.getModel();
* Graph graph = model.getGraph();
* </pre>
* <b>Note:</b> This shows how to get the complete graph, for getting only the
* currently visualized graph, call <code>model.getGraphVisible()</code> instead.
* <h3>Graph Locking</h3>
* Graph structure possess a locking mechanism that avoids multiple threads
* to modify the structure concurrently. However, several readers are allowed.
* <p>
* There is two different way to perform read locking:
* <ul><li>Manually by calling <code>readLock()</code> and <code>readUnlock()</code></li>
* <li>Structure is automatically locked when you read the various <code>NodeIterable</code>
* and <code>EdgeIterable</code></li></ul>
* Be always sure you don't leave the structure blocked. use <code>readUnlockAll()</code>
* to release all the locks.
* <p>
* <b>Note:</b> Write locking is automatically done when modifying th graph
* (add, remove, ...).
* @author Mathieu Bastian
*/
public interface Graph {
/**
* Add <code>edge</code> to the graph. Graph does not accept parallel edges.
* Fails if <code>edge</code> is already in the graph.
* @param edge the edge to add
* @return true if add is successful, false otherwise
* @throws IllegalArgumentException if <code>edge</code> is <code>null</code>,
* or if nodes are not legal nodes for this <code>edge</code>,
* or if <code>edge</code> is directed when the graph is undirected,
* or if <code>edge</code> is undirected when the graph is directed,
* @throws IllegalMonitorStateException if the current thread is holding a read lock
*/
public boolean addEdge(Edge edge);
/**
* Add a node to the graph.
* Fails if the node already exists.
* @param node the node to add
* @return true if add is successful, false otherwise
* @throws IllegalArgumentException if <code>node</code> is <code>null</code>
* @throws IllegalMonitorStateException if the current thread is holding a read lock
*/
public boolean addNode(Node node);
/**
* Remove <code>edge</code> from the graph.
* Fails if the edge doesn't exist.
* @param edge the edge to remove
* @return true if remove is successful, false otherwise
* @throws IllegalArgumentException if <code>edge</code> is <code>null</code> or nodes not legal in
* the graph
* @throws IllegalMonitorStateException if the current thread is holding a read lock
*/
public boolean removeEdge(Edge edge);
/**
* Remove <code>node</code> from the graph. All <code>node</code>'s children and incident edges will
* also be removed.
* @param node the node to remove
* @return true if remove is successful, false otherwise
* @throws IllegalArgumentException if <code>node</code> is <code>null</code>
* or not legal in the graph.
* @throws IllegalMonitorStateException if the current thread is holding a read lock
*/
public boolean removeNode(Node node);
/**
* Returns true if the graph contains <code>node</code>.
* <p><b>Warning:</b> This method is not thread safe, be sure to call it in a locked
* statement.
* @param node the node whose presence is required
* @return true if the graph contains <code>node</code>
* @throws IllegalArgumentException if <code>node</code> is <code>null</code>
*/
public boolean contains(Node node);
/**
* Returns true if the graph contains <code>edge</code>.
* <p><b>Warning:</b> This method is not thread safe, be sure to call it in a locked
* statement.
* @param edge the edge whose presence is required
* @return true if the graph contains <code>edge</code>
* @throws IllegalArgumentException if <code>edge</code> is <code>null</code>
*/
public boolean contains(Edge edge);
/**
* Returns the node with identifier equals to <code>id</code>. If not found,
* returns <code>null</code>. This id is generated and can be found in
* <code>Node.getId()</code>.
* <p><b>Warning:</b> This method is not thread safe, be sure to call it in a locked
* statement.
* @param id a positive number
* @return the node with given <code>id</code>, or <code>null</code> if not found
*/
public Node getNode(int id);
/**
* Returns the node with identifier equals to <code>id</code>. If not found,
* returns <code>null</code>. This id is set by user and can be found at
* <code>NodeData.getId()</code>. To set this Id, use <code>Graph.setId()</code>.
* <p>
* The node must be present in the view this graph is from.
* <p><b>Warning:</b> This method is not thread safe, be sure to call it in a locked
* statement.
* @param id the string identifier, unique
* @return the node with given <code>id</code>, or <code>null</code> if not found
*/
public Node getNode(String id);
/**
* Returns the edge with identifier equals to <code>id</code>. If not found,
* returns <code>null</code>. This id is generated and can be found in
* <code>Edge.getId()</code>.
* <p><b>Warning:</b> This method is not thread safe, be sure to call it in a locked
* statement.
* @param id a positive number
* @return the edge with given <code>id</code>, or <code>null</code> if not found
*/
public Edge getEdge(int id);
/**
* Returns the edge with identifier equals to <code>id</code>. If not found,
* returns <code>null</code>. This id is set by user and can be found at
* <code>EdgeData.getId()</code>. To set this Id, use <code>Graph.setId()</code>.
* <p><b>Warning:</b> This method is not thread safe, be sure to call it in a locked
* statement.
* @param id the string identifier, unique
* @return the edge with given <code>id</code>, or <code>null</code> if not found
*/
public Edge getEdge(String id);
/**
* Finds and returns a <b>directed</b> or <b>undirected</b> edge that connects <code>node1</code> and
* <code>node2</code>. Returns <code>null</code> if no such edge is found.
* <p><b>Warning:</b> This method is not thread safe, be sure to call it in a locked
* statement.
* @param node1 the first incident node of the queried edge
* @param node2 thge second incident node of the queried edge
* @return an edge that connects <code>node1</code> and <code>node2</code>
* or <code>null</code> if no such edge exists
* @throws IllegalArgumentException if <code>node1</code> or <code>node2</code>
* are <code>null</code> or not legal nodes in the graph
*/
public Edge getEdge(Node node1, Node node2);
/**
* Returns nodes contained in the graph.
* @return a node iterable of nodes contained in the graph.
*/
public NodeIterable getNodes();
/**
* Returns edges contained in the graph. Self-loops will be present only once.
* <p>
* If the graph is <b>undirected</b>, directed mutual edges will be present only once.
* @return an edge iterable of edges contained in the graph.
*/
public EdgeIterable getEdges();
/**
* Returns neighbors of <code>node</code>. Neighbors are nodes connected to
* <code>node</code> with any edge of the graph. Neighbors exclude <code>node</code> itself,
* therefore self-loops are ignored.
* @param node the node whose neighbors are to be returned
* @return a node iterable of <code>node</code>'s neighbors
* @throws IllegalArgumentException if <code>node</code> is <code>null</code>
* or not legal in the graph.
*/
public NodeIterable getNeighbors(Node node);
/**
* Returns edges incident to <code>node</code>.
* <p>
* For <b>directed</b> graph, note that self-loops are repeated only once. <b>Undirected</b>
* graphs repeats edges once by default.
* @param node the node whose incident edges are to be returned
* @return an edge iterable of edges incident to <code>node</code>
* @throws IllegalArgumentException if <code>node</code> is <code>null</code>
* or not legal in the graph.
*/
public EdgeIterable getEdges(Node node);
/**
* Returns the number of nodes in the graph.
* <p>
* Special case of interest:
* <ul><li>For <b>hierarchical</b> graph, returns the number of nodes in the
* current view only.</li>
* </ul>
* <p><b>Warning:</b> This method is not thread safe, be sure to call it in a locked
* statement.
* @return the number of nodes in the graph
*/
public int getNodeCount();
/**
* Returns the number of edges in the graph
* <p>
* Special case of interest:
* <ul><li>Count self-loops once only.</li>
* <li>For <b>hierarchical</b> graph, count edges incident only to nodes
* in the current view.</li></ul>
* <p><b>Warning:</b> This method is not thread safe, be sure to call it in a locked
* statement.
* @return the number of edges in the graph.
*/
public int getEdgeCount();
/**
* Return the current node version of the graph. When node structure is touched (i.e. add, remove...) the
* node version is <b>incremented</b>.
* <p>External modules can compare local copy of version to determine if update
* is necessary.
* @return the current node version of the graph
*/
public int getNodeVersion();
/**
* Return the current edge version of the graph. When edge structure is touched (i.e. add, remove...) the
* edge version is <b>incremented</b>.
* <p>External modules can compare local copy of version to determine if update
* is necessary.
* @return the current edge version of the graph
*/
public int getEdgeVersion();
/**
* Returns the adjacent node of <code>node</code> through <code>edge</code>.
* @param node the node whose adjacent node is to be returned
* @param edge the edge whose the opposite node is to be returned
* @return the adjacent node of <code>node</code> through <code>edge</code>
* @throws IllegalArgumentException if <code>node</code> or <code>edge</code> is <code>null</code>,
* or if <code>node</code> is not incident to <code>edge</code>
*/
public Node getOpposite(Node node, Edge edge);
/**
* Returns the degree of <code>node</code>. Self-loops are counted twice for <b>directed</b> graphs.
* @param node the node whose degree is to be returned
* <p><b>Warning:</b> This method is not thread safe, be sure to call it in a locked
* statement.
* @return the degree of <code>node</code>
* @throws IllegalArgumentException if <code>node</code> is <code>null</code> or not legal in the graph
*/
public int getDegree(Node node);
/**
* Returns <code>true</code> if <code>edge</code> is a self-loop.
* @param edge the edge to be queried
* @return <code>true</code> if <code>edge</code> is a self-loop, <code>false</code> otherwise
* @throws IllegalArgumentException if <code>edge</code> is <code>null</code> or adjacent nodes not
* legal in the graph
*/
public boolean isSelfLoop(Edge edge);
/**
* Returns <code>true</code> if <code>edge</code> is a directed edge in the current graph. Always
* returns <code>true</code> when the graph is <b>directed</b> and <code>false</code> when the graph
* is <b>undirected</b>. In case of a <b>mixed</b> graph returns </code>Edge.isDirected()</code>.
* @param edge
* @return <code>true</code> is <code>edge</code> is directed
* @throws IllegalArgumentException if <code>edge</code> is <code>null</code> or adjacent nodes not
* legal in the graph
*/
public boolean isDirected(Edge edge);
/**
* Returns <code>true</code> if <code>node1</code> is adjacent to <code>node2</code>. Is adjacent
* when an edge exists between <code>node1</code> and <code>node2</code>.
* <p><b>Warning:</b> This method is not thread safe, be sure to call it in a locked
* statement.
* @param node1 the first node to be queried
* @param node2 the seconde node to be queried
* @return <code>true</code> if <code>node1</code> is adjacent to <code>node2</code>
* @throws IllegalArgumentException if <code>node1</code> or <code>node2</code> is <code>null</code> of
* not legal in the graph
*/
public boolean isAdjacent(Node node1, Node node2);
/**
* Returns <code>true</code> if <code>edge1</code> is adjacent to <code>edge2</code>. Is adjacent
* when an node is incident to both edges.
* <p><b>Warning:</b> This method is not thread safe, be sure to call it in a locked
* statement.
* @param edge1 the first node to be queried
* @param edge2 the seconde node to be queried
* @return <code>true</code> if <code>edge1</code> is adjacent to <code>edge2</code>
* @throws IllegalArgumentException if <code>edge1</code> or <code>edge2</code> is <code>null</code> of
* not legal in the graph
*/
public boolean isAdjacent(Edge edge1, Edge edge2);
/**
* Removes all edges incident to <code>node</code>.
* @param node the node whose edges is to be cleared
* @throws IllegalArgumentException if <code>node</code> if null or not legal in the graph
* @throws IllegalMonitorStateException if the current thread is holding a read lock
*/
public void clearEdges(Node node);
/**
* Removes all nodes and edges in the graph.
* @throws IllegalMonitorStateException if the current thread is holding a read lock
*/
public void clear();
/**
* Removes all edges in the graph.
* @throws IllegalMonitorStateException if the current thread is holding a read lock
*/
public void clearEdges();
/**
* Sets the string identifier of <code>node</code>. This identifier can be set
* by users, in contrario of {@link Node#getId()} which is set by the system.
* @param id the id that is to be set for <code>node</code>
*/
public void setId(Node node, String id);
/**
* Sets the string identifier of <code>edge</code>. This identifier can be set
* by users, in contrario of {@link Edge#getId()} which is set by the system.
* @param id the id that is to be set for <code>edge</code>
*/
public void setId(Edge edge, String id);
/**
* Acquires a read lock on the graph. Calling thread will be blocked until all write locks are released.
* Several threads can read but only once can write.
* <p>
* A read lock can be acquired several times by a thread, but be sure to call <code>readUnlock()</code>
* the same number of time you called this method, or use <code>readUnlockAll()</code> to release all
* locks.
* @see ReentrantReadWriteLock
*/
public void readLock();
/**
* Releases the read lock on the graph. Must be called from the same thread that locked the graph.
* <p>
* Use <code>readUnlockAll()</code> if you ignore the number of times the read lock has been acquired.
*/
public void readUnlock();
/**
* Safe method that releases all read locks the calling thread has acquired. Use this method if you are
* cancelling a task and you don't know how many read locks have been acquired.
*/
public void readUnlockAll();
/**
* Acquires a write lock on the graph. Calling thread will be blocked until all read locks are released.
* Several threads can read but only once can write.
* @see ReentrantReadWriteLock
* @throws IllegalMonitorStateException if the current thread is holding a read lock
*/
public void writeLock();
/**
* Release the write lock on the graph. Must be called from the same thread that locked the graph.
*/
public void writeUnlock();
/**
* Returns the graph model this graph belongs to.
* @return the graph model this graph belongs to.
*/
public GraphModel getGraphModel();
/**
* Returns the graph view this graph belongs to.
* @return the graph view this graph belongs to.
*/
public GraphView getView();
}