Package org.gephi.graph.dhns.core

Source Code of org.gephi.graph.dhns.core.GraphStructure$GraphDictionnary$EdgeCounter

/*
Copyright 2008-2010 Gephi
Authors : Mathieu Bastian <mathieu.bastian@gephi.org>
Website : http://www.gephi.org

This file is part of Gephi.

Gephi is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.

Gephi is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with Gephi.  If not, see <http://www.gnu.org/licenses/>.
*/
package org.gephi.graph.dhns.core;

import gnu.trove.TIntObjectHashMap;
import gnu.trove.TObjectIntHashMap;
import java.lang.ref.WeakReference;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicInteger;
import org.gephi.utils.collection.avl.ParamAVLIterator;
import org.gephi.graph.api.GraphEvent.EventType;
import org.gephi.graph.dhns.edge.AbstractEdge;
import org.gephi.graph.dhns.event.ViewEvent;
import org.gephi.graph.dhns.node.AbstractNode;
import org.gephi.graph.dhns.node.NodeDataImpl;
import org.gephi.graph.dhns.node.iterators.TreeListIterator;

/**
*
* @author Mathieu Bastian
*/
public class GraphStructure {

    private final AtomicInteger viewId = new AtomicInteger(1);
    private final Dhns dhns;
    private final GraphViewImpl mainView;
    private final Queue<GraphViewImpl> views;
    private final GraphDictionnary dictionnary;
    private GraphViewImpl visibleView;
    //Destroy
    private final Object lock = new Object();
    private final ConcurrentLinkedQueue<GraphViewImpl> destroyQueue;

    public GraphStructure(Dhns dhns) {
        this.dhns = dhns;
        views = new ConcurrentLinkedQueue<GraphViewImpl>();
        dictionnary = new GraphDictionnary();

        //Main view
        mainView = new GraphViewImpl(dhns, 0);
        views.add(mainView);
        visibleView = mainView;

        //Destructor
        destroyQueue = new ConcurrentLinkedQueue<GraphViewImpl>();
        ViewDestructorThread viewDestructorThread = new ViewDestructorThread(this);
        viewDestructorThread.start();
    }

    public GraphViewImpl[] getViews() {
        return views.toArray(new GraphViewImpl[0]);
    }

    public GraphViewImpl getMainView() {
        return mainView;
    }

    public GraphViewImpl createView(int viewId) {   //used by deserializer
        this.viewId.set(Math.max(viewId + 1, this.viewId.get()));
        return new GraphViewImpl(dhns, viewId);
    }

    public GraphViewImpl getNewView() {
        return copyView(mainView);
    }

    public GraphViewImpl copyView(GraphViewImpl view) {
        GraphViewImpl viewCopy = new GraphViewImpl(dhns, viewId.getAndIncrement());
        TreeStructure newStructure = viewCopy.getStructure();
        dhns.writeLock();

        for (TreeListIterator itr = new TreeListIterator(view.getStructure().getTree(), 1); itr.hasNext();) {
            AbstractNode node = itr.next();
            AbstractNode nodeCopy = new AbstractNode(node.getNodeData(), viewCopy.getViewId());
            nodeCopy.setEnabled(node.isEnabled());
            nodeCopy.setEnabledInDegree(node.getEnabledInDegree());
            nodeCopy.setEnabledOutDegree(node.getEnabledOutDegree());
            nodeCopy.setEnabledMutualDegree(node.getEnabledMutualDegree());
            AbstractNode parentCopy = node.parent != null ? newStructure.getNodeAt(node.parent.getPre()) : null;
            newStructure.insertAsChild(nodeCopy, parentCopy);
        }

        //Edges
        ParamAVLIterator<AbstractEdge> edgeIterator = new ParamAVLIterator<AbstractEdge>();
        for (TreeListIterator itr = new TreeListIterator(view.getStructure().getTree(), 1); itr.hasNext();) {
            AbstractNode node = itr.next();
            if (!node.getEdgesOutTree().isEmpty()) {
                for (edgeIterator.setNode(node.getEdgesOutTree()); edgeIterator.hasNext();) {
                    AbstractEdge edge = edgeIterator.next();
                    AbstractNode sourceCopy = newStructure.getNodeAt(edge.getSource().getPre());
                    AbstractNode targetCopy = newStructure.getNodeAt(edge.getTarget().getPre());
                    sourceCopy.getEdgesOutTree().add(edge);
                    targetCopy.getEdgesInTree().add(edge);
                    addToDictionnary(edge);
                }
            }
        }
        viewCopy.setNodesEnabled(view.getNodesEnabled());
        viewCopy.setEdgesCountTotal(view.getEdgesCountTotal());
        viewCopy.setEdgesCountEnabled(view.getEdgesCountEnabled());
        viewCopy.setMutualEdgesTotal(view.getMutualEdgesTotal());
        viewCopy.setMutualEdgesEnabled(view.getMutualEdgesEnabled());

        //Metaedges
        viewCopy.getStructureModifier().getEdgeProcessor().computeMetaEdges();

        views.add(viewCopy);
        dhns.writeUnlock();
        dhns.getEventManager().fireEvent(new ViewEvent(EventType.NEW_VIEW, viewCopy));
        return viewCopy;
    }

    public void destroyView(final GraphViewImpl view) {
        if (views.contains(view)) {
            destroyQueue.add(view);
            synchronized (this.lock) {
                lock.notify();
            }
        }
    }

    public void addToDictionnary(AbstractNode node) {
        dictionnary.addNode(node);
    }

    public void removeFromDictionnary(AbstractNode node) {
        dictionnary.removeNode(node);
    }

    public void addToDictionnary(AbstractEdge edge) {
        dictionnary.addEdge(edge);
    }

    public void removeFromDictionnary(AbstractEdge edge) {
        dictionnary.removeEdge(edge);
    }

    public AbstractEdge getEdgeFromDictionnary(int id) {
        return dictionnary.getEdge(id);
    }

    public AbstractEdge getEdgeFromDictionnary(String id) {
        return dictionnary.getEdge(id);
    }

    public AbstractNode getNodeFromDictionnary(int id, int viewId) {
        return dictionnary.getNode(id, viewId);
    }

    public AbstractNode getNodeFromDictionnary(String id, int viewId) {
        return dictionnary.getNode(id, viewId);
    }

    public void setNodeId(NodeDataImpl node, String id) {
        String oldId = node.setId(id);
        dictionnary.setNodeId(oldId, id, node);
    }

    public void setEdgeId(AbstractEdge edge, String id) {
        String oldId = edge.getEdgeData().setId(id);
        dictionnary.setEdgeId(oldId, id, edge);
    }

    public GraphViewImpl getVisibleView() {
        return visibleView;
    }

    public void setVisibleView(GraphViewImpl visibleView) {
        if (this.visibleView == visibleView) {
            return;
        }
        if (visibleView == null) {
            this.visibleView = mainView;
        } else {
            this.visibleView = visibleView;
        }
        dhns.getEventManager().fireEvent(new ViewEvent(EventType.VISIBLE_VIEW, this.visibleView));
    }

    private static class ViewDestructorThread extends Thread {

        private final WeakReference<GraphStructure> structureReference;
        private final int STD_TIMER = 300;
        private final int UNDESTRO_TIMER = 2000;
        private boolean running = true;

        public ViewDestructorThread(GraphStructure graphStructure) {
            super("DHNS View Destructor");
            setDaemon(true);
            structureReference = new WeakReference<GraphStructure>(graphStructure);
        }

        @Override
        public void run() {
            GraphStructure structure = null;
            while (running && (structure = structureReference.get()) != null) {
                while (structure.destroyQueue.isEmpty()) {
                    try {
                        synchronized (structure.lock) {
                            structure.lock.wait();
                        }
                    } catch (InterruptedException ex) {
                        ex.printStackTrace();
                    }
                }
                boolean undestroyableViews = false;
                for (GraphViewImpl v : structure.destroyQueue.toArray(new GraphViewImpl[0])) {
                    if (!v.hasGraphReference()) {
                        destroyView(structure, v);
                        structure.destroyQueue.remove(v);
                    } else {
                        undestroyableViews = true;
                    }
                }
                try {
                    synchronized (structure.lock) {
                        structure.lock.wait(undestroyableViews ? UNDESTRO_TIMER : STD_TIMER);
                    }
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }
            }
        }

        private void destroyView(GraphStructure structure, GraphViewImpl view) {
            //Logger.getLogger("").log(Level.WARNING, "Destroy view {0}", view.getViewId());
            structure.dhns.writeLock();
            ParamAVLIterator<AbstractEdge> edgeIterator = new ParamAVLIterator<AbstractEdge>();
            for (TreeListIterator itr = new TreeListIterator(structure.mainView.getStructure().getTree(), 1); itr.hasNext();) {
                AbstractNode node = itr.next();
                AbstractNode nodeInView = node.getNodeData().getNodes().get(view.getViewId());
                if (nodeInView != null) {
                    node.getNodeData().getNodes().remove(view.getViewId());
                    if (!nodeInView.getEdgesOutTree().isEmpty()) {
                        for (edgeIterator.setNode(nodeInView.getEdgesOutTree()); edgeIterator.hasNext();) {
                            AbstractEdge edge = edgeIterator.next();
                            structure.removeFromDictionnary(edge);
                        }
                    }
                }
            }
            structure.views.remove(view);
            //System.out.println("Destroy view finished");          
            structure.dhns.writeUnlock();
            structure.dhns.getEventManager().fireEvent(new ViewEvent(EventType.DESTROY_VIEW, view));
            if (structure.visibleView == view) {
                structure.visibleView = structure.mainView;
                structure.dhns.getEventManager().fireEvent(new ViewEvent(EventType.VISIBLE_VIEW, structure.mainView));
            }
        }
    }

    private static class GraphDictionnary {

        private final TObjectIntHashMap<String> nodesMap;
        private final TIntObjectHashMap<NodeDataImpl> nodesIntMap;
        private final TIntObjectHashMap<EdgeCounter> edgesRefCount;
        private final TObjectIntHashMap<String> edgesMap;

        public GraphDictionnary() {
            nodesMap = new TObjectIntHashMap<String>();
            nodesIntMap = new TIntObjectHashMap<NodeDataImpl>();
            edgesRefCount = new TIntObjectHashMap<EdgeCounter>();
            edgesMap = new TObjectIntHashMap<String>();
        }

        public synchronized void addNode(AbstractNode node) {
            if (node.getNodeData().getId() != null) {
                nodesMap.put(node.getNodeData().getId(), node.getId());
            }
            nodesIntMap.put(node.getId(), node.getNodeData());
        }

        public synchronized void removeNode(AbstractNode node) {
            if (node.getNodeData().getNodes().getCount() == 1) {
                if (node.getNodeData().getId() != null) {
                    nodesMap.remove(node.getNodeData().getId());
                }
                nodesIntMap.remove(node.getId());
            }
        }

        public synchronized void addEdge(AbstractEdge edge) {

            EdgeCounter edgeCounter = edgesRefCount.get(edge.getId());
            if (edgeCounter != null) {
                edgeCounter.inc();
            } else {
                edgeCounter = new EdgeCounter(edge);
                edgesRefCount.put(edge.getId(), edgeCounter);
                String id = edge.getEdgeData().getId();
                if (id != null) {
                    edgesMap.put(id, edge.getId());
                }
            }
        }

        public synchronized void removeEdge(AbstractEdge edge) {
            EdgeCounter edgeCounter = edgesRefCount.get(edge.getId());
            int count = edgeCounter.decAndGet();
            if (count == 0) {
                edgesRefCount.remove(edge.getId());
                String id = edge.getEdgeData().getId();
                if (id != null) {
                    edgesMap.remove(id);
                }
            }
        }

        public synchronized AbstractNode getNode(int id, int viewId) {
            NodeDataImpl nodeDataImpl = nodesIntMap.get(id);
            if (nodeDataImpl != null) {
                return (AbstractNode) nodeDataImpl.getNode(viewId);
            }
            return null;
        }

        public synchronized AbstractNode getNode(String id, int viewId) {
            int natId = nodesMap.get(id);
            if (natId != 0) {
                return getNode(natId, viewId);
            }
            return null;
        }

        public synchronized AbstractEdge getEdge(int id) {
            EdgeCounter edgeCounter = edgesRefCount.get(id);
            if (edgeCounter != null) {
                return edgeCounter.edge;
            }
            return null;
        }

        public synchronized AbstractEdge getEdge(String id) {
            int natId = edgesMap.get(id);
            if (natId != 0) {
                return getEdge(natId);
            }
            return null;
        }

        public synchronized void setNodeId(String oldId, String newId, NodeDataImpl node) {
            if (oldId != null) {
                int val = nodesMap.remove(oldId);
                nodesMap.put(newId, val);
            } else {
                nodesMap.put(newId, node.getID());
            }
        }

        public synchronized void setEdgeId(String oldId, String newId, AbstractEdge edge) {
            if (oldId != null) {
                int val = edgesMap.remove(oldId);
                edgesMap.put(newId, val);
            } else {
                edgesMap.put(newId, edge.getId());
            }
        }

        private static class EdgeCounter {

            protected final AbstractEdge edge;
            private int counter = 1;

            public EdgeCounter(AbstractEdge edge) {
                this.edge = edge;
            }

            private void inc() {
                counter++;
            }

            private int decAndGet() {
                return --counter;
            }

            @Override
            public boolean equals(Object obj) {
                if (obj != null && obj instanceof EdgeCounter) {
                    EdgeCounter e = (EdgeCounter) obj;
                    return e.edge.equals(edge);
                } else if (obj != null && obj instanceof AbstractEdge) {
                    return obj.equals(edge);
                }
                return false;
            }

            @Override
            public int hashCode() {
                return edge.hashCode();
            }
        }
    }
}
TOP

Related Classes of org.gephi.graph.dhns.core.GraphStructure$GraphDictionnary$EdgeCounter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.