/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2002-2008, Open Source Geospatial Foundation (OSGeo)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library 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.
*/
package org.geotools.graph.structure.basic;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.geotools.graph.structure.DirectedEdge;
import org.geotools.graph.structure.DirectedNode;
import org.geotools.graph.structure.Edge;
import org.geotools.graph.structure.Node;
/**
* Basic implementation of DirectedNode.
*
* @author Justin Deoliveira, Refractions Research Inc, jdeolive@refractions.net
*
*
* @source $URL$
*/
public class BasicDirectedNode extends BasicGraphable implements DirectedNode {
/** In adjacency list **/
transient private ArrayList m_in;
/** Out adjacecy list **/
transient private ArrayList m_out;
/**
* Constructs a new BasicDirectedNode.
*/
public BasicDirectedNode() {
super();
m_in = new ArrayList();
m_out = new ArrayList();
}
/**
* Unsupported operation. Directed nodes classify edges as <B>in</B> and
* <B>out</B>. addIn(Edge) and addOut(Edge) should be used instead of this
* method.
*
* @throws UnsupportedOperationException
*
* @see DirectedNode#addIn(DirectedEdge)
* @see DirectedNode#addOut(DirectedEdge)
*
*/
public void add(Edge e) {
throw new UnsupportedOperationException(
"add(Edge)"
);
}
/**
* Adds an edge to the <B>in</B> adjacency list of the node which is an
* underlying List implementation. No checking is done on the edge
* (duplication, looping...), it is simply added to the list. It is also
* assumed that the edge being added has the node as its out node.
*
* @see DirectedNode#addIn(DirectedEdge)
* @see DirectedEdge#getOutNode()
*
*/
public void addIn(DirectedEdge e) {
m_in.add(e);
}
/**
* Adds an edge to the <B>ou</B> adjacency list of the node which is an
* underlying List implementation. No checking is done on the edge
* (duplication, looping...), it is simply added to the list. It is also
* assumed that the edge being added has the node as its in node.
*
* @see DirectedNode#addOut(DirectedEdge)
* @see DirectedEdge#getInNode()
*
*/
public void addOut(DirectedEdge e) {
m_out.add(e);
}
/**
* Removes the edge from both the in and out adjacency lists.
*
* @see Node#remove(Edge)
*/
public void remove(Edge e) {
m_in.remove(e);
m_out.remove(e);
}
/**
* @see DirectedNode#removeIn(DirectedEdge)
*/
public void removeIn(DirectedEdge e) {
m_in.remove(e);
}
/**
* @see DirectedNode#removeOut(DirectedEdge)
*/
public void removeOut(DirectedEdge e) {
m_out.remove(e);
}
/**
* First searches for an in edge with an out node == this, and in
* node == other. If none is found an edge with out node == other, and in
* node == this is searched for.
*
* @see Node#remove(Edge)
*/
public Edge getEdge(Node other) {
Edge e = getInEdge((DirectedNode)other);
if (e != null) return(e);
return(getOutEdge((DirectedNode)other));
}
/**
* @see DirectedNode#getInEdge(DirectedNode)
*/
public Edge getInEdge(DirectedNode other) {
//must explictley check that the edge has node other, and one node this,
// just checking other is not good enough because of loops
for (int i = 0; i < m_in.size(); i++) {
DirectedEdge edge = (DirectedEdge)m_in.get(i);
if (edge.getInNode().equals(other) && edge.getOutNode().equals(this))
return(edge);
}
return(null);
}
/**
* @see DirectedNode#getOutEdge(DirectedNode)
*/
public Edge getOutEdge(DirectedNode other) {
//must explictley check that the edge has node other, and one node this,
// just checking other is not good enough because of loops
for (int i = 0; i < m_out.size(); i++) {
DirectedEdge edge = (DirectedEdge)m_out.get(i);
if (edge.getOutNode().equals(other) && edge.getInNode().equals(this))
return(edge);
}
return(null);
}
/**
* Returns the combination of both the in and out adjacecy lists.
*/
public List getEdges() {
ArrayList edges = new ArrayList();
edges.addAll(m_in);
edges.addAll(m_out);
return(edges);
}
/**
* @see DirectedNode#getInEdges()
*/
public List getInEdges() {
return(m_in);
}
/**
* @see DirectedNode#getOutEdges()
*/
public List getOutEdges() {
return(m_out);
}
/**
* A combination of the results of getInEdges(Node) and getOutEdges(Node).
*
* @see Node#getEdges(Node)
* @see DirectedNode#getInEdges(DirectedNode)
* @see DirectedNode#getOutEdges(DirectedNode)
*/
public List getEdges(Node other) {
List edges = getInEdges((DirectedNode)other);
edges.addAll(getOutEdges((DirectedNode)other));
return(edges);
}
/**
* @see DirectedNode#getInEdges(DirectedNode)
*/
public List getInEdges(DirectedNode other) {
ArrayList edges = new ArrayList();
for (int i = 0; i < m_in.size(); i++) {
DirectedEdge edge = (DirectedEdge)m_in.get(i);
if (edge.getInNode().equals(other)) edges.add(edge);
}
return(edges);
}
/**
* @see DirectedNode#getOutEdges(DirectedNode)
*/
public List getOutEdges(DirectedNode other) {
ArrayList edges = new ArrayList();
for (int i = 0; i < m_out.size(); i++) {
DirectedEdge edge = (DirectedEdge)m_out.get(i);
if (edge.getOutNode().equals(other)) edges.add(edge);
}
return(edges);
}
/**
* Returns sum of sizes of in and out adjacency lists.
*
* @see Node#getDegree()
*/
public int getDegree() {
return(m_in.size() + m_out.size());
}
/**
* @see DirectedNode#getInDegree()
*/
public int getInDegree() {
return(m_in.size());
}
/**
* @see DirectedNode#getOutDegree()
*/
public int getOutDegree() {
return(m_out.size());
}
/**
* Returns an iterator over all out nodes of out edges and in nodes of in
* edges.
*
* @see org.geotools.graph.structure.Graphable#getRelated()
*/
public Iterator getRelated() {
ArrayList related = new ArrayList(m_out.size()+m_in.size());
for (int i = 0; i < m_in.size(); i++) {
DirectedEdge e = (DirectedEdge)m_in.get(i);
related.add(e.getInNode());
}
for (int i = 0; i < m_out.size(); i++) {
DirectedEdge e = (DirectedEdge)m_out.get(i);
related.add(e.getOutNode());
}
return(related.iterator());
}
/**
* Returns all in nodes of in edges.
*
* @see org.geotools.graph.structure.DirectedGraphable#getInRelated()
*/
public Iterator getInRelated() {
ArrayList related = new ArrayList(m_in.size());
for (int i = 0; i < m_in.size(); i++) {
DirectedEdge e = (DirectedEdge)m_in.get(i);
related.add(e.getInNode());
}
return(related.iterator());
}
/**
* Returns all out nodes of out edges.
*
* @see org.geotools.graph.structure.DirectedGraphable#getOutRelated()
*/
public Iterator getOutRelated() {
ArrayList related = new ArrayList(m_out.size());
for (int i = 0; i < m_out.size(); i++) {
DirectedEdge e = (DirectedEdge)m_out.get(i);
related.add(e.getOutNode());
}
return(related.iterator());
}
/**
* Overides the default deserialization operation. The edge adjacency lists
* of a BasicDirectedNode is not written out when the node is serialized so
* they must be recreated upon deserialization.
*
* @param in Object input stream containing serialized object.
*
* @throws IOException
* @throws ClassNotFoundException
*/
private void readObject(ObjectInputStream in)
throws IOException, ClassNotFoundException {
in.defaultReadObject();
//recreate edge adjacency lists
m_in = new ArrayList();
m_out = new ArrayList();
}
}