com.salesforce.jgrapht.graph.AbstractBaseGraph Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of AptSpringProcessor Show documentation
Show all versions of AptSpringProcessor Show documentation
This project contains the apt processor that implements all the checks enumerated in @Verify. It is a self contained, and
shaded jar.
/*
* (C) Copyright 2003-2017, by Barak Naveh and Contributors.
*
* JGraphT : a free Java graph-theory library
*
* This program and the accompanying materials are dual-licensed under
* either
*
* (a) the terms of the GNU Lesser General Public License version 2.1
* as published by the Free Software Foundation, or (at your option) any
* later version.
*
* or (per the licensee's choosing)
*
* (b) the terms of the Eclipse Public License v1.0 as published by
* the Eclipse Foundation.
*/
package com.salesforce.jgrapht.graph;
import java.io.*;
import java.util.*;
import com.salesforce.jgrapht.*;
import com.salesforce.jgrapht.graph.specifics.*;
import com.salesforce.jgrapht.util.*;
/**
* The most general implementation of the {@link com.salesforce.jgrapht.Graph} interface. Its subclasses add
* various restrictions to get more specific graphs. The decision whether it is directed or
* undirected is decided at construction time and cannot be later modified (see constructor for
* details).
*
*
* This graph implementation guarantees deterministic vertex and edge set ordering (via
* {@link LinkedHashMap} and {@link LinkedHashSet}).
*
*
* @param the graph vertex type
* @param the graph edge type
*
* @author Barak Naveh
* @since Jul 24, 2003
*/
public abstract class AbstractBaseGraph
extends AbstractGraph
implements Graph, Cloneable, Serializable
{
private static final long serialVersionUID = -1263088497616142427L;
private static final String LOOPS_NOT_ALLOWED = "loops not allowed";
private static final String GRAPH_SPECIFICS_MUST_NOT_BE_NULL =
"Graph specifics must not be null";
private boolean allowingLoops;
private EdgeFactory edgeFactory;
private Map edgeMap;
private transient Set unmodifiableEdgeSet = null;
private transient Set unmodifiableVertexSet = null;
private Specifics specifics;
private boolean allowingMultipleEdges;
/**
* Construct a new graph. The graph can either be directed or undirected, depending on the
* specified edge factory.
*
* @param ef the edge factory of the new graph.
* @param allowMultipleEdges whether to allow multiple edges or not.
* @param allowLoops whether to allow edges that are self-loops or not.
*
* @throws NullPointerException if the specified edge factory is
* null
.
*/
protected AbstractBaseGraph(
EdgeFactory ef, boolean allowMultipleEdges, boolean allowLoops)
{
Objects.requireNonNull(ef);
edgeMap = new LinkedHashMap<>();
edgeFactory = ef;
allowingLoops = allowLoops;
allowingMultipleEdges = allowMultipleEdges;
specifics = Objects.requireNonNull(createSpecifics(), GRAPH_SPECIFICS_MUST_NOT_BE_NULL);
}
/**
* {@inheritDoc}
*/
@Override
public Set getAllEdges(V sourceVertex, V targetVertex)
{
return specifics.getAllEdges(sourceVertex, targetVertex);
}
/**
* Returns true
if and only if self-loops are allowed in this graph. A self loop is
* an edge that its source and target vertices are the same.
*
* @return true
if and only if graph loops are allowed.
*/
public boolean isAllowingLoops()
{
return allowingLoops;
}
/**
* Returns true
if and only if multiple edges are allowed in this graph. The
* meaning of multiple edges is that there can be many edges going from vertex v1 to vertex v2.
*
* @return true
if and only if multiple edges are allowed.
*/
public boolean isAllowingMultipleEdges()
{
return allowingMultipleEdges;
}
/**
* {@inheritDoc}
*/
@Override
public E getEdge(V sourceVertex, V targetVertex)
{
return specifics.getEdge(sourceVertex, targetVertex);
}
/**
* {@inheritDoc}
*/
@Override
public EdgeFactory getEdgeFactory()
{
return edgeFactory;
}
/**
* {@inheritDoc}
*/
@Override
public E addEdge(V sourceVertex, V targetVertex)
{
assertVertexExist(sourceVertex);
assertVertexExist(targetVertex);
if (!allowingMultipleEdges && containsEdge(sourceVertex, targetVertex)) {
return null;
}
if (!allowingLoops && sourceVertex.equals(targetVertex)) {
throw new IllegalArgumentException(LOOPS_NOT_ALLOWED);
}
E e = edgeFactory.createEdge(sourceVertex, targetVertex);
if (containsEdge(e)) { // this restriction should stay!
return null;
} else {
IntrusiveEdge intrusiveEdge = createIntrusiveEdge(e, sourceVertex, targetVertex);
edgeMap.put(e, intrusiveEdge);
specifics.addEdgeToTouchingVertices(e);
return e;
}
}
/**
* {@inheritDoc}
*/
@Override
public boolean addEdge(V sourceVertex, V targetVertex, E e)
{
if (e == null) {
throw new NullPointerException();
} else if (containsEdge(e)) {
return false;
}
assertVertexExist(sourceVertex);
assertVertexExist(targetVertex);
if (!allowingMultipleEdges && containsEdge(sourceVertex, targetVertex)) {
return false;
}
if (!allowingLoops && sourceVertex.equals(targetVertex)) {
throw new IllegalArgumentException(LOOPS_NOT_ALLOWED);
}
IntrusiveEdge intrusiveEdge = createIntrusiveEdge(e, sourceVertex, targetVertex);
edgeMap.put(e, intrusiveEdge);
specifics.addEdgeToTouchingVertices(e);
return true;
}
private IntrusiveEdge createIntrusiveEdge(E e, V sourceVertex, V targetVertex)
{
IntrusiveEdge intrusiveEdge;
if (e instanceof IntrusiveEdge) {
intrusiveEdge = (IntrusiveEdge) e;
} else {
intrusiveEdge = new IntrusiveEdge();
}
intrusiveEdge.source = sourceVertex;
intrusiveEdge.target = targetVertex;
return intrusiveEdge;
}
/**
* {@inheritDoc}
*/
@Override
public boolean addVertex(V v)
{
if (v == null) {
throw new NullPointerException();
} else if (containsVertex(v)) {
return false;
} else {
specifics.addVertex(v);
return true;
}
}
/**
* {@inheritDoc}
*/
@Override
public V getEdgeSource(E e)
{
return TypeUtil.uncheckedCast(getIntrusiveEdge(e).source, null);
}
/**
* {@inheritDoc}
*/
@Override
public V getEdgeTarget(E e)
{
return TypeUtil.uncheckedCast(getIntrusiveEdge(e).target, null);
}
private IntrusiveEdge getIntrusiveEdge(E e)
{
if (e instanceof IntrusiveEdge) {
return (IntrusiveEdge) e;
}
return edgeMap.get(e);
}
/**
* Returns a shallow copy of this graph instance. Neither edges nor vertices are cloned.
*
* @return a shallow copy of this set.
*
* @throws RuntimeException in case the clone is not supported
*
* @see java.lang.Object#clone()
*/
@Override
public Object clone()
{
try {
AbstractBaseGraph newGraph = TypeUtil.uncheckedCast(super.clone(), null);
newGraph.edgeMap = new LinkedHashMap<>();
newGraph.edgeFactory = this.edgeFactory;
newGraph.unmodifiableEdgeSet = null;
newGraph.unmodifiableVertexSet = null;
// NOTE: it's important for this to happen in an object
// method so that the new inner class instance gets associated with
// the right outer class instance
newGraph.specifics = newGraph.createSpecifics();
Graphs.addGraph(newGraph, this);
return newGraph;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
throw new RuntimeException();
}
}
/**
* {@inheritDoc}
*/
@Override
public boolean containsEdge(E e)
{
return edgeMap.containsKey(e);
}
/**
* {@inheritDoc}
*/
@Override
public boolean containsVertex(V v)
{
return specifics.getVertexSet().contains(v);
}
/**
* Returns the degree of the specified vertex.
*
* @param vertex vertex whose degree is to be calculated.
* @return the degree of the specified vertex.
* @see UndirectedGraph#degreeOf(Object)
*/
public int degreeOf(V vertex)
{
return specifics.degreeOf(vertex);
}
/**
* {@inheritDoc}
*/
@Override
public Set edgeSet()
{
if (unmodifiableEdgeSet == null) {
unmodifiableEdgeSet = Collections.unmodifiableSet(edgeMap.keySet());
}
return unmodifiableEdgeSet;
}
/**
* {@inheritDoc}
*/
@Override
public Set edgesOf(V vertex)
{
assertVertexExist(vertex);
return specifics.edgesOf(vertex);
}
/**
* Returns the "in degree" of the specified vertex.
*
* @param vertex vertex whose in degree is to be calculated.
* @return the in degree of the specified vertex.
*
* @see DirectedGraph#inDegreeOf(Object)
*/
public int inDegreeOf(V vertex)
{
assertVertexExist(vertex);
return specifics.inDegreeOf(vertex);
}
/**
* Returns a set of all edges incoming into the specified vertex.
*
* @param vertex the vertex for which the list of incoming edges to be returned
* @return a set of all edges incoming into the specified vertex
* @see DirectedGraph#incomingEdgesOf(Object)
*/
public Set incomingEdgesOf(V vertex)
{
assertVertexExist(vertex);
return specifics.incomingEdgesOf(vertex);
}
/**
* Returns the "out degree" of the specified vertex.
*
* @param vertex vertex whose out degree is to be calculated
* @return the out degree of the specified vertex
* @see DirectedGraph#outDegreeOf(Object)
*/
public int outDegreeOf(V vertex)
{
assertVertexExist(vertex);
return specifics.outDegreeOf(vertex);
}
/**
* Returns a set of all edges outgoing from the specified vertex.
*
* @param vertex the vertex for which the list of outgoing edges to be returned
* @return a set of all edges outgoing from the specified vertex
* @see DirectedGraph#outgoingEdgesOf(Object)
*/
public Set outgoingEdgesOf(V vertex)
{
assertVertexExist(vertex);
return specifics.outgoingEdgesOf(vertex);
}
/**
* {@inheritDoc}
*/
@Override
public E removeEdge(V sourceVertex, V targetVertex)
{
E e = getEdge(sourceVertex, targetVertex);
if (e != null) {
specifics.removeEdgeFromTouchingVertices(e);
edgeMap.remove(e);
}
return e;
}
/**
* {@inheritDoc}
*/
@Override
public boolean removeEdge(E e)
{
if (containsEdge(e)) {
specifics.removeEdgeFromTouchingVertices(e);
edgeMap.remove(e);
return true;
} else {
return false;
}
}
/**
* {@inheritDoc}
*/
@Override
public boolean removeVertex(V v)
{
if (containsVertex(v)) {
Set touchingEdgesList = edgesOf(v);
// cannot iterate over list - will cause
// ConcurrentModificationException
removeAllEdges(new ArrayList<>(touchingEdgesList));
specifics.getVertexSet().remove(v); // remove the vertex itself
return true;
} else {
return false;
}
}
/**
* {@inheritDoc}
*/
@Override
public Set vertexSet()
{
if (unmodifiableVertexSet == null) {
unmodifiableVertexSet = Collections.unmodifiableSet(specifics.getVertexSet());
}
return unmodifiableVertexSet;
}
/**
* {@inheritDoc}
*/
@Override
public double getEdgeWeight(E e)
{
if (e instanceof DefaultWeightedEdge) {
return ((DefaultWeightedEdge) e).getWeight();
} else if (e == null) {
throw new NullPointerException();
} else {
return WeightedGraph.DEFAULT_EDGE_WEIGHT;
}
}
/**
* Assigns a weight to an edge.
*
* @param e edge on which to set weight
* @param weight new weight for edge
* @see WeightedGraph#setEdgeWeight(Object, double)
*/
public void setEdgeWeight(E e, double weight)
{
assert (e instanceof DefaultWeightedEdge) : e.getClass();
((DefaultWeightedEdge) e).weight = weight;
}
/**
* Create the specifics for this graph. Subclasses can override this method in order to adjust
* the specifics and thus the space-time tradeoffs of the graph implementation.
*
* @return the specifics used by this graph
*/
protected Specifics createSpecifics()
{
if (this instanceof DirectedGraph, ?>) {
return createDirectedSpecifics();
} else if (this instanceof UndirectedGraph, ?>) {
return createUndirectedSpecifics();
} else {
throw new IllegalArgumentException(
"must be instance of either DirectedGraph or UndirectedGraph");
}
}
/**
* Create undirected specifics for the graph
*
* @return undirected specifics for the graph
* @deprecated specifics can be changed by overriding directly {@link #createSpecifics()}.
*/
@Deprecated
protected Specifics createUndirectedSpecifics()
{
return new FastLookupUndirectedSpecifics<>(this);
}
/**
* Create directed specifics for the graph
*
* @return directed specifics for the graph
* @deprecated specifics can be changed by overriding directly {@link #createSpecifics()}.
*/
@Deprecated
protected Specifics createDirectedSpecifics()
{
return new FastLookupDirectedSpecifics<>(this);
}
}
// End AbstractBaseGraph.java
© 2015 - 2025 Weber Informatics LLC | Privacy Policy