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

org.apache.cayenne.ashwood.graph.MapDigraph Maven / Gradle / Ivy

There is a newer version: 4.2.1
Show newest version
/*****************************************************************
 *   Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you under the Apache License, Version 2.0 (the
 *  "License"); you may not use this file except in compliance
 *  with the License.  You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing,
 *  software distributed under the License is distributed on an
 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *  KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations
 *  under the License.
 ****************************************************************/
/* ====================================================================
 *
 * Copyright(c) 2003, Andriy Shapochka
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above
 *    copyright notice, this list of conditions and the following
 *    disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above
 *    copyright notice, this list of conditions and the following
 *    disclaimer in the documentation and/or other materials
 *    provided with the distribution.
 *
 * 3. Neither the name of the ASHWOOD nor the
 *    names of its contributors may be used to endorse or
 *    promote products derived from this software without
 *    specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * ====================================================================
 *
 * This software consists of voluntary contributions made by
 * individuals on behalf of the ASHWOOD Project and was originally
 * created by Andriy Shapochka.
 *
 */
package org.apache.cayenne.ashwood.graph;

import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

/**
 * @since 3.1
 */
public class MapDigraph implements Digraph {

    private Map> graph;
    private int size;

    public MapDigraph() {
        graph = new HashMap>();
    }

    public boolean addVertex(E vertex) {
        if (graph.containsKey(vertex)) {
            return false;
        }

        graph.put(vertex, new HashMap());
        return true;
    }

    public boolean addAllVertices(Collection vertices) {
        if (graph.keySet().containsAll(vertices)) {
            return false;
        }

        for (E vertex : vertices) {
            addVertex(vertex);
        }

        return true;
    }

    public V putArc(E origin, E destination, V arc) {
        Map destinations = graph.get(origin);
        if (destinations == null) {
            destinations = new HashMap();
            graph.put(origin, destinations);
        }

        addVertex(destination);
        V oldArc = destinations.put(destination, arc);
        if (oldArc == null) {
            size++;
        }

        return oldArc;
    }

    public V getArc(Object origin, Object destination) {
        Map destinations = graph.get(origin);
        if (destinations == null) {
            return null;
        }

        return destinations.get(destination);
    }

    public boolean removeVertex(E vertex) {
        Map destination = graph.remove(vertex);
        if (destination != null)
            size -= destination.size();
        else
            return false;

        removeIncoming(vertex);
        return true;
    }

    public boolean removeAllVertices(Collection vertices) {
        boolean modified = false;

        for (E vertex : vertices) {
            modified |= removeVertex(vertex);
        }

        return modified;
    }

    public Object removeArc(E origin, E destination) {
        Map destinations = graph.get(origin);
        if (destinations == null) {
            return null;
        }

        V arc = destinations.remove(destination);
        if (arc != null)
            size--;

        return arc;
    }

    public boolean removeIncoming(E vertex) {
        boolean modified = false;

        for (Map destinations : graph.values()) {
            Object arc = destinations.remove(vertex);
            if (arc != null)
                size--;
            modified |= (arc != null);
        }

        return modified;
    }

    public boolean removeOutgoing(E vertex) {

        Map destinations = graph.remove(vertex);
        if (destinations != null)
            size -= destinations.size();
        else
            return false;
        boolean modified = !destinations.isEmpty();
        destinations.clear();
        return modified;
    }

    public Iterator vertexIterator() {
        return graph.keySet().iterator();
    }

    public ArcIterator arcIterator() {
        return new AllArcIterator();
    }

    public ArcIterator outgoingIterator(E vertex) {
        if (!containsVertex(vertex)) {
            return ArcIterator.EMPTY_ITERATOR;
        }

        return new OutgoingArcIterator(vertex);
    }

    public ArcIterator incomingIterator(E vertex) {
        if (!containsVertex(vertex))
            return ArcIterator.EMPTY_ITERATOR;
        return new IncomingArcIterator(vertex);
    }

    public int order() {
        return graph.size();
    }

    public int size() {
        return size;
    }

    public int outgoingSize(E vertex) {
        Map destinations = graph.get(vertex);
        if (destinations == null)
            return 0;
        else
            return destinations.size();
    }

    public int incomingSize(E vertex) {
        int count = 0;
        if (!graph.containsKey(vertex))
            return 0;

        for (Map destinations : graph.values()) {
            count += (destinations.containsKey(vertex) ? 1 : 0);
        }

        return count;
    }

    public boolean containsVertex(E vertex) {
        return graph.containsKey(vertex);
    }

    public boolean containsAllVertices(Collection vertices) {
        return graph.keySet().containsAll(vertices);
    }

    public boolean hasArc(E origin, E destination) {
        Map destinations = graph.get(origin);
        if (destinations == null)
            return false;
        return destinations.containsKey(destination);
    }

    public boolean isEmpty() {
        return graph.isEmpty();
    }

    public boolean isOutgoingEmpty(E vertex) {
        return outgoingSize(vertex) == 0;
    }

    public boolean isIncomingEmpty(E vertex) {
        return incomingSize(vertex) == 0;
    }

    private class AllArcIterator implements ArcIterator {

        private Iterator>> originIterator;
        private Iterator> destinationIterator;
        private E origin, nextOrigin;
        private E destination, nextDst;
        private V arc, nextArc;

        private AllArcIterator() {
            originIterator = graph.entrySet().iterator();
            next();
        }

        public E getOrigin() {
            return origin;
        }

        public E getDestination() {
            return destination;
        }

        public boolean hasNext() {
            return nextArc != null;
        }

        public V next() {
            origin = nextOrigin;
            destination = nextDst;
            arc = nextArc;
            if (destinationIterator == null || !destinationIterator.hasNext()) {
                nextOrigin = null;
                nextDst = null;
                nextArc = null;

                while (originIterator.hasNext()) {
                    Entry> entry = originIterator.next();
                    destinationIterator = entry.getValue().entrySet().iterator();
                    if (destinationIterator.hasNext()) {
                        nextOrigin = entry.getKey();
                        Entry entry1 = destinationIterator.next();
                        nextDst = entry1.getKey();
                        nextArc = entry1.getValue();
                        break;
                    }
                }
            }
            else {
                Entry entry1 = destinationIterator.next();
                nextDst = entry1.getKey();
                nextArc = entry1.getValue();
            }

            return arc;
        }

        public void remove() {
            throw new UnsupportedOperationException(
                    "Method remove() not yet implemented.");
        }
    }

    private class OutgoingArcIterator implements ArcIterator {

        private E origin;
        private Iterator> dstIt;
        private Entry entry;

        private OutgoingArcIterator(E vertex) {
            origin = vertex;
            dstIt = graph.get(vertex).entrySet().iterator();
        }

        public E getOrigin() {
            return origin;
        }

        public E getDestination() {
            if (entry == null)
                return null;
            return entry.getKey();
        }

        public boolean hasNext() {
            return dstIt.hasNext();
        }

        public V next() {
            entry = dstIt.next();
            return entry.getValue();
        }

        public void remove() {
            throw new UnsupportedOperationException(
                    "Method remove() not yet implemented.");
        }
    }

    private class IncomingArcIterator implements ArcIterator {

        private E dst;
        private E origin, nextOrigin;
        private V arc, nextArc;
        private Iterator>> graphIt;

        private IncomingArcIterator(E vertex) {
            dst = vertex;
            graphIt = graph.entrySet().iterator();
            next();
        }

        public E getOrigin() {
            return origin;
        }

        public E getDestination() {
            return dst;
        }

        public boolean hasNext() {
            return (nextArc != null);
        }

        public V next() {
            origin = nextOrigin;
            arc = nextArc;
            nextArc = null;
            nextOrigin = null;
            while (graphIt.hasNext()) {
                Entry> entry = graphIt.next();
                Map destinations = entry.getValue();
                nextArc = destinations.get(dst);
                if (nextArc != null) {
                    nextOrigin = entry.getKey();
                    break;
                }
            }
            return arc;
        }

        public void remove() {
            throw new java.lang.UnsupportedOperationException(
                    "Method remove() not yet implemented.");
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy