org.jgrapht.graph.guava.BaseGraphAdapter Maven / Gradle / Ivy
/*
* (C) Copyright 2018-2018, by Dimitrios Michail 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 org.jgrapht.graph.guava;
import com.google.common.graph.*;
import org.jgrapht.*;
import org.jgrapht.Graph;
import org.jgrapht.graph.AbstractGraph;
import org.jgrapht.graph.*;
import java.io.*;
import java.util.*;
import java.util.function.*;
import static java.util.stream.Collectors.*;
/**
* A base abstract implementation for the graph adapter class using Guava's {@link Graph}. This is a
* helper class in order to support both mutable and immutable graphs.
*
* @author Dimitrios Michail
*
* @param the graph vertex type
* @param type of the underlying Guava's graph
*/
public abstract class BaseGraphAdapter>
extends
AbstractGraph>
implements
Graph>,
Cloneable,
Serializable
{
private static final long serialVersionUID = -6742507788742087708L;
protected static final String LOOPS_NOT_ALLOWED = "loops not allowed";
protected transient Set unmodifiableVertexSet = null;
protected transient Set> unmodifiableEdgeSet = null;
protected Supplier vertexSupplier;
protected Supplier> edgeSupplier;
protected transient G graph;
/**
* Create a new adapter.
*
* @param graph the graph
*/
public BaseGraphAdapter(G graph)
{
this(graph, null, null);
}
/**
* Create a new adapter.
*
* @param graph the graph
* @param vertexSupplier the vertex supplier
* @param edgeSupplier the edge supplier
*/
public BaseGraphAdapter(
G graph, Supplier vertexSupplier, Supplier> edgeSupplier)
{
this.vertexSupplier = vertexSupplier;
this.edgeSupplier = edgeSupplier;
this.graph = Objects.requireNonNull(graph);
}
@Override
public Supplier getVertexSupplier()
{
return vertexSupplier;
}
/**
* Set the vertex supplier that the graph uses whenever it needs to create new vertices.
*
*
* A graph uses the vertex supplier to create new vertex objects whenever a user calls method
* {@link Graph#addVertex()}. Users can also create the vertex in user code and then use method
* {@link Graph#addVertex(Object)} to add the vertex.
*
*
* In contrast with the {@link Supplier} interface, the vertex supplier has the additional
* requirement that a new and distinct result is returned every time it is invoked. More
* specifically for a new vertex to be added in a graph v
must not be equal
* to any other vertex in the graph. More formally, the graph must not contain any vertex
* v2
such that v2.equals(v)
.
*
* @param vertexSupplier the vertex supplier
*/
public void setVertexSupplier(Supplier vertexSupplier)
{
this.vertexSupplier = vertexSupplier;
}
@Override
public Supplier> getEdgeSupplier()
{
return edgeSupplier;
}
/**
* Set the edge supplier that the graph uses whenever it needs to create new edges.
*
*
* A graph uses the edge supplier to create new edge objects whenever a user calls method
* {@link Graph#addEdge(Object, Object)}. Users can also create the edge in user code and then
* use method {@link Graph#addEdge(Object, Object, Object)} to add the edge.
*
*
* In contrast with the {@link Supplier} interface, the edge supplier has the additional
* requirement that a new and distinct result is returned every time it is invoked. More
* specifically for a new edge to be added in a graph e
must not be equal to
* any other edge in the graph (even if the graph allows edge-multiplicity). More formally, the
* graph must not contain any edge e2
such that e2.equals(e)
.
*
* @param edgeSupplier the edge supplier
*/
public void setEdgeSupplier(Supplier> edgeSupplier)
{
this.edgeSupplier = edgeSupplier;
}
@Override
public EndpointPair getEdge(V sourceVertex, V targetVertex)
{
if (sourceVertex == null || targetVertex == null) {
return null;
} else if (!graph.hasEdgeConnecting(sourceVertex, targetVertex)) {
return null;
} else {
return createEdge(sourceVertex, targetVertex);
}
}
@Override
@Deprecated
public EdgeFactory> getEdgeFactory()
{
return null;
}
@Override
public Set vertexSet()
{
if (unmodifiableVertexSet == null) {
unmodifiableVertexSet = Collections.unmodifiableSet(graph.nodes());
}
return unmodifiableVertexSet;
}
@Override
public V getEdgeSource(EndpointPair e)
{
return e.nodeU();
}
@Override
public V getEdgeTarget(EndpointPair e)
{
return e.nodeV();
}
@Override
public GraphType getType()
{
return (graph.isDirected() ? new DefaultGraphType.Builder().directed()
: new DefaultGraphType.Builder().undirected())
.weighted(false).allowMultipleEdges(false).allowSelfLoops(graph.allowsSelfLoops())
.build();
}
@Override
public boolean containsEdge(EndpointPair e)
{
return graph.edges().contains(e);
}
@Override
public boolean containsVertex(V v)
{
return graph.nodes().contains(v);
}
@Override
public Set> edgeSet()
{
if (unmodifiableEdgeSet == null) {
unmodifiableEdgeSet = Collections.unmodifiableSet(graph.edges());
}
return unmodifiableEdgeSet;
}
@Override
public int degreeOf(V vertex)
{
return graph.degree(vertex);
}
@Override
public Set> edgesOf(V vertex)
{
return graph.incidentEdges(vertex);
}
@Override
public int inDegreeOf(V vertex)
{
return graph.inDegree(vertex);
}
@Override
public Set> incomingEdgesOf(V vertex)
{
return graph.predecessors(vertex).stream().map(other -> createEdge(other, vertex)).collect(
collectingAndThen(toSet(), Collections::unmodifiableSet));
}
@Override
public int outDegreeOf(V vertex)
{
return graph.outDegree(vertex);
}
@Override
public Set> outgoingEdgesOf(V vertex)
{
return graph.successors(vertex).stream().map(other -> createEdge(vertex, other)).collect(
collectingAndThen(toSet(), Collections::unmodifiableSet));
}
@Override
public double getEdgeWeight(EndpointPair e)
{
if (e == null) {
throw new NullPointerException();
} else if (!graph.hasEdgeConnecting(e.nodeU(), e.nodeV())) {
throw new IllegalArgumentException("no such edge in graph: " + e.toString());
} else {
return Graph.DEFAULT_EDGE_WEIGHT;
}
}
@Override
public Set> getAllEdges(V sourceVertex, V targetVertex)
{
if (sourceVertex == null || targetVertex == null || !graph.nodes().contains(sourceVertex)
|| !graph.nodes().contains(targetVertex))
{
return null;
} else if (!graph.hasEdgeConnecting(sourceVertex, targetVertex)) {
return Collections.emptySet();
} else {
return Collections.singleton(createEdge(sourceVertex, targetVertex));
}
}
/**
* Create an edge.
*
* @param s the source vertex
* @param t the target vertex
* @return the edge
*/
final EndpointPair createEdge(V s, V t)
{
return graph.isDirected() ? EndpointPair.ordered(s, t) : EndpointPair.unordered(s, t);
}
}