All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.salesforce.jgrapht.graph.specifics.DirectedSpecifics Maven / Gradle / Ivy

Go to download

This project contains the apt processor that implements all the checks enumerated in @Verify. It is a self contained, and shaded jar.

There is a newer version: 2.0.7
Show newest version
/*
 * (C) Copyright 2015-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.specifics;

import java.io.*;
import java.util.*;

import com.salesforce.jgrapht.graph.*;
import com.salesforce.jgrapht.util.*;

/**
 * Plain implementation of DirectedSpecifics. This implementation requires the least amount of
 * memory, at the expense of slow edge retrievals. Methods which depend on edge retrievals, e.g.
 * getEdge(V u, V v), containsEdge(V u, V v), addEdge(V u, V v), etc may be relatively slow when the
 * average degree of a vertex is high (dense graphs). For a fast implementation, use
 * {@link FastLookupDirectedSpecifics}.
 * 
 * @param  the graph vertex type
 * @param  the graph edge type
 *
 * @author Barak Naveh
 * @author Joris Kinable
 */
public class DirectedSpecifics
    implements Specifics, Serializable
{
    private static final long serialVersionUID = 8971725103718958232L;
    private static final String NOT_IN_DIRECTED_GRAPH = "no such operation in a directed graph";

    protected AbstractBaseGraph abstractBaseGraph;
    protected Map> vertexMapDirected;
    protected EdgeSetFactory edgeSetFactory;

    /**
     * Construct a new directed specifics.
     * 
     * @param abstractBaseGraph the graph for which these specifics are for
     */
    public DirectedSpecifics(AbstractBaseGraph abstractBaseGraph)
    {
        this(abstractBaseGraph, new LinkedHashMap<>(), new ArrayUnenforcedSetEdgeSetFactory<>());
    }

    /**
     * Construct a new directed specifics.
     * 
     * @param abstractBaseGraph the graph for which these specifics are for
     * @param vertexMap map for the storage of vertex edge sets
     */
    public DirectedSpecifics(
        AbstractBaseGraph abstractBaseGraph, Map> vertexMap)
    {
        this(abstractBaseGraph, vertexMap, new ArrayUnenforcedSetEdgeSetFactory<>());
    }

    /**
     * Construct a new directed specifics.
     * 
     * @param abstractBaseGraph the graph for which these specifics are for
     * @param vertexMap map for the storage of vertex edge sets
     * @param edgeSetFactory factory for the creation of vertex edge sets
     */
    public DirectedSpecifics(
        AbstractBaseGraph abstractBaseGraph, Map> vertexMap,
        EdgeSetFactory edgeSetFactory)
    {
        this.abstractBaseGraph = abstractBaseGraph;
        this.vertexMapDirected = vertexMap;
        this.edgeSetFactory = edgeSetFactory;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void addVertex(V v)
    {
        // add with a lazy edge container entry
        vertexMapDirected.put(v, null);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Set getVertexSet()
    {
        return vertexMapDirected.keySet();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Set getAllEdges(V sourceVertex, V targetVertex)
    {
        Set edges = null;

        if (abstractBaseGraph.containsVertex(sourceVertex)
            && abstractBaseGraph.containsVertex(targetVertex))
        {
            edges = new ArrayUnenforcedSet<>();

            DirectedEdgeContainer ec = getEdgeContainer(sourceVertex);

            for (E e : ec.outgoing) {
                if (abstractBaseGraph.getEdgeTarget(e).equals(targetVertex)) {
                    edges.add(e);
                }
            }
        }

        return edges;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public E getEdge(V sourceVertex, V targetVertex)
    {
        if (abstractBaseGraph.containsVertex(sourceVertex)
            && abstractBaseGraph.containsVertex(targetVertex))
        {
            DirectedEdgeContainer ec = getEdgeContainer(sourceVertex);

            for (E e : ec.outgoing) {
                if (abstractBaseGraph.getEdgeTarget(e).equals(targetVertex)) {
                    return e;
                }
            }
        }

        return null;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void addEdgeToTouchingVertices(E e)
    {
        V source = abstractBaseGraph.getEdgeSource(e);
        V target = abstractBaseGraph.getEdgeTarget(e);

        getEdgeContainer(source).addOutgoingEdge(e);
        getEdgeContainer(target).addIncomingEdge(e);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int degreeOf(V vertex)
    {
        throw new UnsupportedOperationException(NOT_IN_DIRECTED_GRAPH);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Set edgesOf(V vertex)
    {
        ArrayUnenforcedSet inAndOut =
            new ArrayUnenforcedSet<>(getEdgeContainer(vertex).incoming);
        inAndOut.addAll(getEdgeContainer(vertex).outgoing);

        // we have two copies for each self-loop - remove one of them.
        if (abstractBaseGraph.isAllowingLoops()) {
            Set loops = getAllEdges(vertex, vertex);

            for (int i = 0; i < inAndOut.size();) {
                E e = inAndOut.get(i);

                if (loops.contains(e)) {
                    inAndOut.remove(i);
                    loops.remove(e); // so we remove it only once
                } else {
                    i++;
                }
            }
        }

        return Collections.unmodifiableSet(inAndOut);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int inDegreeOf(V vertex)
    {
        return getEdgeContainer(vertex).incoming.size();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Set incomingEdgesOf(V vertex)
    {
        return getEdgeContainer(vertex).getUnmodifiableIncomingEdges();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int outDegreeOf(V vertex)
    {
        return getEdgeContainer(vertex).outgoing.size();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Set outgoingEdgesOf(V vertex)
    {
        return getEdgeContainer(vertex).getUnmodifiableOutgoingEdges();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void removeEdgeFromTouchingVertices(E e)
    {
        V source = abstractBaseGraph.getEdgeSource(e);
        V target = abstractBaseGraph.getEdgeTarget(e);

        getEdgeContainer(source).removeOutgoingEdge(e);
        getEdgeContainer(target).removeIncomingEdge(e);
    }

    /**
     * A lazy build of edge container for specified vertex.
     *
     * @param vertex a vertex in this graph.
     *
     * @return an edge container
     */
    protected DirectedEdgeContainer getEdgeContainer(V vertex)
    {
        // abstractBaseGraph.assertVertexExist(vertex); //JK: I don't think we need this here. This
        // should have been verified upstream

        DirectedEdgeContainer ec = vertexMapDirected.get(vertex);

        if (ec == null) {
            ec = new DirectedEdgeContainer<>(edgeSetFactory, vertex);
            vertexMapDirected.put(vertex, ec);
        }

        return ec;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy