qdg.StaticMixedSubIdGraph.java Source code

Java tutorial

Introduction

Here is the source code for qdg.StaticMixedSubIdGraph.java

Source

/*
 * Copyright (C) 2013, 2014 Marton Makai
 *
 * Licensed 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.
 */

package qdg;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Iterator;

import qdg.api.EntityMap;
import qdg.api.MixedIdGraph;
import qdg.api.bits.EdgeMutationHandler;
import qdg.api.bits.HasId;
import qdg.api.bits.NodeMutationHandler;
import qdg.bits.AbstractIdMap;
import qdg.bits.AbstractMixedGraph;
import qdg.bits.ArcLace;
import qdg.bits.ArcLace.ArcData;
import qdg.bits.ArcLace.NodeData;
import qdg.bits.ConcatIterator;

import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.collect.Iterables;
import com.google.common.collect.Iterators;

/**
 * Subgraph of a mixed graph with integer ids of the nodes and edges.
 * The node and edge objects are used from the underlying mixed graph.
 * 
 * Nodes and edges are stored in arrays with their ids corresponding to
 * indices, hence memory consumption is proportional to the maximum id.
 * 
 * @author Marton Makai
 */
public class StaticMixedSubIdGraph extends AbstractMixedGraph implements MixedIdGraph, Serializable {

    private static final long serialVersionUID = 4444550416599231556L;

    protected static class CombinedNodeData implements Serializable {

        private static final long serialVersionUID = 8855112085916381992L;

        protected NodeData arcData = new NodeData();

        protected NodeData uEdgeData = new NodeData();

        @Override
        public String toString() {
            return "CombinedNodeData [arcData=" + arcData + ", uEdgeData=" + uEdgeData + "]";
        }
    }

    protected MixedIdGraph graph;

    public StaticMixedSubIdGraph() {
    }

    public StaticMixedSubIdGraph(MixedIdGraph graph) {
        this.graph = graph;
    }

    public void setGraph(MixedIdGraph graph) {
        this.graph = graph;
    }

    public MixedIdGraph getGraph() {
        return graph;
    }

    @Override
    public boolean isDirected(Edge edge) {
        return graph.isDirected(edge);
    }

    protected StaticSparseArrayList<CombinedNodeData> nodes = new StaticSparseArrayList<CombinedNodeData>();

    private class ArcNodeMap implements EntityMap<Integer, NodeData> {

        @Override
        public NodeData put(Integer k, NodeData v) {
            CombinedNodeData c = nodes.get(k);
            if (c == null) {
                c = new CombinedNodeData();
            }
            c.arcData = v;
            return v;
        }

        @Override
        public NodeData get(Object k) {
            CombinedNodeData c = nodes.get(k);
            if (c == null) {
                return null;
            }
            return c.arcData;
        }
    }

    protected transient EntityMap<Integer, NodeData> arcNodes = new ArcNodeMap();

    private class UEdgeNodeMap implements EntityMap<Integer, NodeData> {

        @Override
        public NodeData put(Integer k, NodeData v) {
            CombinedNodeData c = nodes.get(k);
            if (c == null) {
                c = new CombinedNodeData();
            }
            c.uEdgeData = v;
            return v;
        }

        @Override
        public NodeData get(Object k) {
            CombinedNodeData c = nodes.get(k);
            if (c == null) {
                return null;
            }
            return c.uEdgeData;
        }
    }

    protected transient EntityMap<Integer, NodeData> uEdgeNodes = new UEdgeNodeMap();

    protected StaticSparseArrayList<ArcData<Integer>> arcData = new StaticSparseArrayList<ArcData<Integer>>();

    protected transient ArcLace<Integer> arcLace = new ArcLace<Integer>(arcNodes, arcData);

    protected StaticSparseArrayList<ArcData<Integer>> uEdgeData = new StaticSparseArrayList<ArcData<Integer>>();

    protected transient ArcLace<Integer> uEdgeLace = new ArcLace<Integer>(uEdgeNodes, uEdgeData);

    private Function<Integer, Node> constructNode = new Function<Integer, Node>() {

        @Override
        public Node apply(Integer id) {
            return graph.nodeFromId(id);
        }
    };

    private Function<Integer, Edge> constructArc = new Function<Integer, Edge>() {

        @Override
        public Edge apply(Integer id) {
            return graph.arcFromId(id);
        }
    };

    private Function<Integer, Edge> constructUEdge = new Function<Integer, Edge>() {

        @Override
        public Edge apply(Integer id) {
            return graph.uEdgeFromId(id);
        }
    };

    @Override
    public Node getSource(Edge edge) {
        if (graph.isDirected(edge)) {
            return graph.nodeFromId(arcLace.getSource(((HasId) edge).getId()));
        } else {
            return graph.nodeFromId(uEdgeLace.getSource(((HasId) edge).getId()));
        }
    }

    @Override
    public Node getTarget(Edge edge) {
        if (graph.isDirected(edge)) {
            return graph.nodeFromId(arcLace.getTarget(((HasId) edge).getId()));
        } else {
            return graph.nodeFromId(uEdgeLace.getTarget(((HasId) edge).getId()));
        }
    }

    @Override
    public Iterator<Node> getNodeIterator() {
        return Iterators.transform(nodes.keyIterator(), constructNode);
    }

    @Override
    public Iterator<Edge> getArcIterator() {
        return Iterators.transform(arcLace.getArcIterator(), constructArc);
    }

    @Override
    public Iterator<Edge> getUEdgeIterator() {
        return Iterators.transform(uEdgeLace.getArcIterator(), constructUEdge);
    }

    @Override
    public Iterator<Edge> getOutArcIterator(Node node) {
        return Iterators.transform(arcLace.getOutArcIterator(((HasId) node).getId()), constructArc);
    }

    @Override
    public Iterator<Edge> getInArcIterator(Node node) {
        return Iterators.transform(arcLace.getInArcIterator(((HasId) node).getId()), constructArc);
    }

    @Override
    public Iterator<Edge> getIncidentArcIterator(Node node) {
        return Iterators.transform(new ConcatIterator<Integer>(arcLace.getOutArcIterator(((HasId) node).getId()),
                arcLace.getInArcIterator(((HasId) node).getId())), constructArc);
    }

    @Override
    public Iterator<Edge> getIncidentUEdgeIterator(Node node) {
        return Iterators.transform(new ConcatIterator<Integer>(uEdgeLace.getOutArcIterator(((HasId) node).getId()),
                uEdgeLace.getInArcIterator(((HasId) node).getId())), constructUEdge);
    }

    public Node addNode(int id) {
        nodes.put(id, new CombinedNodeData());
        return graph.nodeFromId(id);
    }

    public void remove(Node node) {
        HasId n = (HasId) node;
        while (arcLace.getOutArcIterator(n.getId()).hasNext()) {
            Edge u = graph.arcFromId(arcLace.getOutArcIterator(n.getId()).next());
            remove(u);
        }
        while (arcLace.getInArcIterator(n.getId()).hasNext()) {
            Edge u = graph.arcFromId(arcLace.getInArcIterator(n.getId()).next());
            remove(u);
        }
        while (uEdgeLace.getOutArcIterator(n.getId()).hasNext()) {
            Edge u = graph.uEdgeFromId(uEdgeLace.getOutArcIterator(n.getId()).next());
            remove(u);
        }
        while (uEdgeLace.getInArcIterator(n.getId()).hasNext()) {
            Edge u = graph.uEdgeFromId(uEdgeLace.getInArcIterator(n.getId()).next());
            remove(u);
        }
        nodes.remove(n.getId());
    }

    public Edge addArc(int id, Node source, Node target) {
        HasId s = (HasId) source;
        HasId t = (HasId) target;
        arcData.put(id, new ArcData<Integer>(s.getId(), t.getId()));
        arcLace.laceArc(id, s.getId(), t.getId());
        return graph.arcFromId(id);
    }

    public Edge addUEdge(int id, Node source, Node target) {
        HasId s = (HasId) source;
        HasId t = (HasId) target;
        uEdgeData.put(id, new ArcData<Integer>(s.getId(), t.getId()));
        uEdgeLace.laceArc(id, s.getId(), t.getId());
        return graph.uEdgeFromId(id);
    }

    public void remove(Edge edge) {
        HasId e = (HasId) edge;
        if (graph.isDirected(edge)) {
            arcLace.remove(e.getId());
            arcData.remove(e.getId());
        } else {
            uEdgeLace.remove(e.getId());
            uEdgeData.remove(e.getId());
        }
    }

    protected class NodeMap<V> extends AbstractIdMap<Node, V> {

        private static final long serialVersionUID = 1167032365456389038L;

        @Override
        public String toString() {
            return "NodeMap [" + Joiner.on(", ").join(Iterables.transform(getNodes(), f)) + "]";
        }
    }

    @Override
    public <V> EntityMap<Node, V> createNodeMap() {
        return new NodeMap<V>();
    }

    protected class EdgeMap<V> implements EntityMap<Edge, V>, Serializable {

        private static final long serialVersionUID = -3899482894397129726L;

        protected ArcMap<V> arcMap = new ArcMap<V>();

        protected UEdgeMap<V> uEdgeMap = new UEdgeMap<V>();

        @Override
        public V put(Edge k, V v) {
            if (graph.isDirected(k)) {
                return arcMap.put((Edge) k, v);
            } else {
                return uEdgeMap.put((Edge) k, v);
            }
        }

        @Override
        public V get(Object k) {
            if (graph.isDirected((Edge) k)) {
                return arcMap.get((Edge) k);
            } else {
                return uEdgeMap.get((Edge) k);
            }
        }

        private class PrintEntry implements Function<Edge, String> {

            @Override
            public String apply(Edge k) {
                return "" + k + "=" + get(k);
            }
        };

        protected transient Function<Edge, String> f = new PrintEntry();

        @Override
        public String toString() {
            return "EdgeMap [" + Joiner.on(", ").join(Iterables.transform(getEdges(), f)) + "]";
        }

        @GwtIncompatible("ObjectInputStream")
        private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
            in.defaultReadObject();
            f = new PrintEntry();
        }

        @GwtIncompatible("ObjectOutputStream")
        private void writeObject(ObjectOutputStream out) throws IOException {
            out.defaultWriteObject();
        }
    }

    @Override
    public <V> EntityMap<Edge, V> createEdgeMap() {
        return new EdgeMap<V>();
    }

    protected class ArcMap<V> extends AbstractIdMap<Edge, V> {

        private static final long serialVersionUID = -5275110474745662141L;

        @Override
        public String toString() {
            return "ArcMap [" + Joiner.on(", ").join(Iterables.transform(getArcs(), f)) + "]";
        }
    }

    protected class UEdgeMap<V> extends AbstractIdMap<Edge, V> {

        private static final long serialVersionUID = 7117159471854014975L;

        @Override
        public String toString() {
            return "EdgeMap [" + Joiner.on(", ").join(Iterables.transform(getUEdges(), f)) + "]";
        }
    }

    @Override
    public <V> EntityMap<Edge, V> createUEdgeMap() {
        return new UEdgeMap<V>();
    }

    @Override
    public <V> EntityMap<Edge, V> createArcMap() {
        return new ArcMap<V>();
    }

    @GwtIncompatible("ObjectInputStream")
    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        in.defaultReadObject();
        arcLace = new ArcLace<Integer>(arcNodes, arcData);
        uEdgeLace = new ArcLace<Integer>(uEdgeNodes, uEdgeData);
        arcNodes = new ArcNodeMap();
        uEdgeNodes = new UEdgeNodeMap();
    }

    @GwtIncompatible("ObjectOutputStream")
    private void writeObject(ObjectOutputStream out) throws IOException {
        out.defaultWriteObject();
    }

    @Override
    public Node addNode() {
        throw new UnsupportedOperationException();
    }

    @Override
    public Edge addUEdge(Node source, Node target) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void addNodeMutationHandler(NodeMutationHandler handler) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void addEdgeMutationHandler(EdgeMutationHandler handler) {
        throw new UnsupportedOperationException();
    }

    @Override
    public Edge addArc(Node source, Node target) {
        throw new UnsupportedOperationException();
    }

    @Override
    public Node nodeFromId(int id) {
        return graph.nodeFromId(id);
    }

    @Override
    public Edge arcFromId(int id) {
        return graph.arcFromId(id);
    }

    @Override
    public Edge uEdgeFromId(int id) {
        return graph.uEdgeFromId(id);
    }
}