org.jgrapht.graph.guava.BaseValueGraphAdapter.java Source code

Java tutorial

Introduction

Here is the source code for org.jgrapht.graph.guava.BaseValueGraphAdapter.java

Source

/*
 * (C) Copyright 2018-2018, by Dimitrios Michail and Contributors.
 *
 * JGraphT : a free Java graph-theory library
 *
 * See the CONTRIBUTORS.md file distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0, or the
 * GNU Lesser General Public License v2.1 or later
 * which is available at
 * http://www.gnu.org/licenses/old-licenses/lgpl-2.1-standalone.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR LGPL-2.1-or-later
 */
package org.jgrapht.graph.guava;

import com.google.common.graph.*;
import org.jgrapht.Graph;
import org.jgrapht.*;
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.collectingAndThen;
import static java.util.stream.Collectors.toSet;

/**
 * A base abstract implementation for the graph adapter class using Guava's {@link ValueGraph}. This
 * is a helper class in order to support both mutable and immutable value graphs.
 * 
 * @author Dimitrios Michail
 *
 * @param <V> the graph vertex type
 * @param <W> the value type
 * @param <VG> type of the underlying Guava's value graph
 */
public abstract class BaseValueGraphAdapter<V, W, VG extends ValueGraph<V, W>>
        extends AbstractGraph<V, EndpointPair<V>> implements Graph<V, EndpointPair<V>>, Cloneable, Serializable {
    private static final long serialVersionUID = 3833510139696864917L;

    protected static final String LOOPS_NOT_ALLOWED = "loops not allowed";

    protected transient Set<V> unmodifiableVertexSet = null;
    protected transient Set<EndpointPair<V>> unmodifiableEdgeSet = null;

    protected Supplier<V> vertexSupplier;
    protected Supplier<EndpointPair<V>> edgeSupplier;
    protected ToDoubleFunction<W> valueConverter;
    protected transient VG valueGraph;

    /**
     * Create a new adapter.
     * 
     * @param valueGraph the mutable value graph
     * @param valueConverter a function that converts a value to a double
     */
    public BaseValueGraphAdapter(VG valueGraph, ToDoubleFunction<W> valueConverter) {
        this(valueGraph, valueConverter, null, null);
    }

    /**
     * Create a new adapter.
     * 
     * @param valueGraph the mutable value graph
     * @param valueConverter a function that converts a value to a double
     * @param vertexSupplier the vertex supplier
     * @param edgeSupplier the edge supplier
     */
    public BaseValueGraphAdapter(VG valueGraph, ToDoubleFunction<W> valueConverter, Supplier<V> vertexSupplier,
            Supplier<EndpointPair<V>> edgeSupplier) {
        this.vertexSupplier = vertexSupplier;
        this.edgeSupplier = edgeSupplier;
        this.valueGraph = Objects.requireNonNull(valueGraph);
        this.valueConverter = Objects.requireNonNull(valueConverter);
    }

    @Override
    public Supplier<V> getVertexSupplier() {
        return vertexSupplier;
    }

    /**
     * Set the vertex supplier that the graph uses whenever it needs to create new vertices.
     * 
     * <p>
     * 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.
     * 
     * <p>
     * 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 <code>v</code> must <i>not</i> be equal
     * to any other vertex in the graph. More formally, the graph must not contain any vertex
     * <code>v2</code> such that <code>v2.equals(v)</code>.
     * 
     * @param vertexSupplier the vertex supplier
     */
    public void setVertexSupplier(Supplier<V> vertexSupplier) {
        this.vertexSupplier = vertexSupplier;
    }

    @Override
    public Supplier<EndpointPair<V>> getEdgeSupplier() {
        return edgeSupplier;
    }

    /**
     * Set the edge supplier that the graph uses whenever it needs to create new edges.
     * 
     * <p>
     * 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.
     * 
     * <p>
     * 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 <code>e</code> must <i>not</i> 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 <code>e2</code> such that <code>e2.equals(e)</code>.
     * 
     * @param edgeSupplier the edge supplier
     */
    public void setEdgeSupplier(Supplier<EndpointPair<V>> edgeSupplier) {
        this.edgeSupplier = edgeSupplier;
    }

    @Override
    public EndpointPair<V> getEdge(V sourceVertex, V targetVertex) {
        if (sourceVertex == null || targetVertex == null) {
            return null;
        } else if (!valueGraph.hasEdgeConnecting(sourceVertex, targetVertex)) {
            return null;
        } else {
            return createEdge(sourceVertex, targetVertex);
        }
    }

    @Override
    public Set<V> vertexSet() {
        if (unmodifiableVertexSet == null) {
            unmodifiableVertexSet = Collections.unmodifiableSet(valueGraph.nodes());
        }
        return unmodifiableVertexSet;
    }

    @Override
    public V getEdgeSource(EndpointPair<V> e) {
        return e.nodeU();
    }

    @Override
    public V getEdgeTarget(EndpointPair<V> e) {
        return e.nodeV();
    }

    @Override
    public GraphType getType() {
        return (valueGraph.isDirected() ? new DefaultGraphType.Builder().directed()
                : new DefaultGraphType.Builder().undirected()).weighted(true).allowMultipleEdges(false)
                        .allowSelfLoops(valueGraph.allowsSelfLoops()).build();
    }

    @Override
    public boolean containsEdge(EndpointPair<V> e) {
        return valueGraph.edges().contains(e);
    }

    @Override
    public boolean containsVertex(V v) {
        return valueGraph.nodes().contains(v);
    }

    @Override
    public Set<EndpointPair<V>> edgeSet() {
        if (unmodifiableEdgeSet == null) {
            unmodifiableEdgeSet = Collections.unmodifiableSet(valueGraph.edges());
        }
        return unmodifiableEdgeSet;
    }

    @Override
    public int degreeOf(V vertex) {
        return valueGraph.degree(vertex);
    }

    @Override
    public Set<EndpointPair<V>> edgesOf(V vertex) {
        return valueGraph.incidentEdges(vertex);
    }

    @Override
    public int inDegreeOf(V vertex) {
        return valueGraph.inDegree(vertex);
    }

    @Override
    public Set<EndpointPair<V>> incomingEdgesOf(V vertex) {
        return valueGraph.predecessors(vertex).stream().map(other -> createEdge(other, vertex))
                .collect(collectingAndThen(toSet(), Collections::unmodifiableSet));
    }

    @Override
    public int outDegreeOf(V vertex) {
        return valueGraph.outDegree(vertex);
    }

    @Override
    public Set<EndpointPair<V>> outgoingEdgesOf(V vertex) {
        return valueGraph.successors(vertex).stream().map(other -> createEdge(vertex, other))
                .collect(collectingAndThen(toSet(), Collections::unmodifiableSet));
    }

    @Override
    public double getEdgeWeight(EndpointPair<V> e) {
        if (e == null) {
            throw new NullPointerException();
        } else if (!valueGraph.hasEdgeConnecting(e.nodeU(), e.nodeV())) {
            throw new IllegalArgumentException("no such edge in graph: " + e.toString());
        } else {
            return valueGraph.edgeValue(e.nodeU(), e.nodeV()).map(valueConverter::applyAsDouble)
                    .orElse(Graph.DEFAULT_EDGE_WEIGHT);
        }
    }

    @Override
    public Set<EndpointPair<V>> getAllEdges(V sourceVertex, V targetVertex) {
        if (sourceVertex == null || targetVertex == null || !valueGraph.nodes().contains(sourceVertex)
                || !valueGraph.nodes().contains(targetVertex)) {
            return null;
        } else if (!valueGraph.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<V> createEdge(V s, V t) {
        return valueGraph.isDirected() ? EndpointPair.ordered(s, t) : EndpointPair.unordered(s, t);
    }

}