/******************************************************************************
* Copyright (c) 2009 - 2015 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
/**
*
*/
package com.ibm.wala.memsat.util;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import com.ibm.wala.util.graph.Graph;
import kodkod.util.collections.Containers;
/**
* A simple graph implementation based on a linked hash map.
* Best used for representing graphs with a small number of nodes.
*
* @author etorlak
*/
public final class LinkedHashGraph<T> implements Graph<T> {
private final Map<T, Set<T>> edges;
/**
* Constructs an empty hash graph.
*/
public LinkedHashGraph() {
edges = new LinkedHashMap<T, Set<T>>();
}
/** {@inheritDoc}
* @see com.ibm.wala.util.graph.Graph#removeNodeAndEdges(java.lang.Object)
*/
public void removeNodeAndEdges(T N) throws UnsupportedOperationException {
if (containsNode(N)) {
removeIncomingEdges(N);
edges.remove(N);
}
}
/** {@inheritDoc}
* @see com.ibm.wala.util.graph.NodeManager#addNode(java.lang.Object)
*/
public void addNode(T N) {
if (!containsNode(N)) {
edges.put(N, new LinkedHashSet<T>(3));
}
}
/** {@inheritDoc}
* @see com.ibm.wala.util.graph.NodeManager#containsNode(java.lang.Object)
*/
public boolean containsNode(T N) {
return edges.containsKey(N);
}
/** {@inheritDoc}
* @see com.ibm.wala.util.graph.NodeManager#getNumberOfNodes()
*/
public int getNumberOfNodes() {
return edges.size();
}
/** {@inheritDoc}
* @see com.ibm.wala.util.graph.NodeManager#iterator()
*/
public Iterator<T> iterator() {
return Collections.unmodifiableSet(edges.keySet()).iterator();
}
/** {@inheritDoc}
* @see com.ibm.wala.util.graph.NodeManager#removeNode(java.lang.Object)
*/
public void removeNode(T n) {
removeNodeAndEdges(n);
}
/** {@inheritDoc}
* @see com.ibm.wala.util.graph.EdgeManager#addEdge(java.lang.Object, java.lang.Object)
*/
public void addEdge(T src, T dst) {
addNode(src);
addNode(dst);
edges.get(src).add(dst);
}
/** {@inheritDoc}
* @see com.ibm.wala.util.graph.EdgeManager#getPredNodeCount(java.lang.Object)
*/
public int getPredNodeCount(T N) {
if (containsNode(N)) {
int p = 0;
for(Set<T> succs : edges.values()) {
if (succs.contains(N))
p++;
}
return p;
}
return 0;
}
/** {@inheritDoc}
* @see com.ibm.wala.util.graph.EdgeManager#getPredNodes(java.lang.Object)
*/
public Iterator<T> getPredNodes(final T N) {
if (containsNode(N)) {
return new Iterator<T>() {
final Iterator<T> itr = edges.keySet().iterator();
T next, last;
public boolean hasNext() {
while(next==null && itr.hasNext()) {
final T node = itr.next();
if (edges.get(node).contains(N)) {
next = node;
}
}
return next != null;
}
public T next() {
if (!hasNext()) throw new NoSuchElementException();
last = next;
next = null;
return last;
}
public void remove() {
if (last==null) throw new IllegalStateException();
removeAllIncidentEdges(last);
itr.remove();
last = null;
}
};
}
return Containers.emptyIterator();
}
/** {@inheritDoc}
* @see com.ibm.wala.util.graph.EdgeManager#getSuccNodeCount(java.lang.Object)
*/
public int getSuccNodeCount(T N) {
return containsNode(N) ? edges.get(N).size() : 0;
}
/** {@inheritDoc}
* @see com.ibm.wala.util.graph.EdgeManager#getSuccNodes(java.lang.Object)
*/
@SuppressWarnings("unchecked")
public Iterator<T> getSuccNodes(T N) {
return containsNode(N) ? edges.get(N).iterator() : Collections.EMPTY_SET.iterator();
}
/** {@inheritDoc}
* @see com.ibm.wala.util.graph.EdgeManager#hasEdge(java.lang.Object, java.lang.Object)
*/
public boolean hasEdge(T src, T dst) {
return containsNode(src) && edges.get(src).contains(dst);
}
/** {@inheritDoc}
* @see com.ibm.wala.util.graph.EdgeManager#removeAllIncidentEdges(java.lang.Object)
*/
public void removeAllIncidentEdges(T node) throws UnsupportedOperationException {
removeIncomingEdges(node);
removeOutgoingEdges(node);
}
/** {@inheritDoc}
* @see com.ibm.wala.util.graph.EdgeManager#removeEdge(java.lang.Object, java.lang.Object)
*/
public void removeEdge(T src, T dst) throws UnsupportedOperationException {
if (containsNode(src)) {
edges.get(src).remove(dst);
}
}
/** {@inheritDoc}
* @see com.ibm.wala.util.graph.EdgeManager#removeIncomingEdges(java.lang.Object)
*/
public void removeIncomingEdges(T node) throws UnsupportedOperationException {
if (containsNode(node)) {
for(Set<T> succs : edges.values()) {
succs.remove(node);
}
}
}
/** {@inheritDoc}
* @see com.ibm.wala.util.graph.EdgeManager#removeOutgoingEdges(java.lang.Object)
*/
public void removeOutgoingEdges(T node) throws UnsupportedOperationException {
if (containsNode(node)) {
edges.get(node).clear();
}
}
public String toString() {
return Strings.prettyPrint(this);
}
}