/* 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.graph; import org.gephi.utils.collection.avl.ParamAVLIterator; import org.gephi.graph.api.Edge; import org.gephi.graph.api.EdgeIterable; import org.gephi.graph.api.HierarchicalDirectedGraph; import org.gephi.graph.api.MetaEdge; import org.gephi.graph.api.Node; import org.gephi.graph.api.NodeIterable; import org.gephi.graph.dhns.core.Dhns; import org.gephi.graph.dhns.core.GraphViewImpl; import org.gephi.graph.dhns.edge.AbstractEdge; import org.gephi.graph.dhns.edge.iterators.BiEdgeIterator; import org.gephi.graph.dhns.edge.iterators.EdgeAndMetaEdgeIterator; import org.gephi.graph.dhns.edge.iterators.EdgeIterator; import org.gephi.graph.dhns.edge.iterators.EdgeNodeIterator; import org.gephi.graph.dhns.edge.iterators.MetaEdgeIterator; import org.gephi.graph.dhns.edge.iterators.MetaEdgeNodeIterator; import org.gephi.graph.dhns.edge.iterators.RangeEdgeIterator; import org.gephi.graph.dhns.node.AbstractNode; import org.gephi.graph.dhns.node.iterators.NeighborIterator; import org.gephi.graph.dhns.node.iterators.TreeIterator; import org.gephi.graph.dhns.predicate.Tautology; import org.gephi.graph.dhns.utils.avl.EdgeOppositeTree; /** * * @author Mathieu Bastian */ public class HierarchicalDirectedGraphImpl extends HierarchicalGraphImpl implements HierarchicalDirectedGraph { public HierarchicalDirectedGraphImpl(Dhns dhns, GraphViewImpl view) { super(dhns, view); } //Graph public boolean addEdge(Edge edge) { AbstractEdge absEdge = checkEdge(edge); if (!edge.isDirected()) { throw new IllegalArgumentException("Can't add an undirected egde"); } if (checkEdgeExist(absEdge.getSource(view.getViewId()), absEdge.getTarget(view.getViewId()))) { //Edge already exist return false; } if (!absEdge.hasAttributes()) { absEdge.setAttributes(dhns.factory().newEdgeAttributes(edge.getEdgeData())); } view.getStructureModifier().addEdge(absEdge); dhns.touchDirected(); return true; } //Directed public boolean addEdge(Node source, Node target) { AbstractNode absSource = checkNode(source); AbstractNode absTarget = checkNode(target); if (checkEdgeExist(absSource, absTarget)) { //Edge already exist return false; } AbstractEdge edge = dhns.factory().newEdge(source, target); view.getStructureModifier().addEdge(edge); dhns.touchDirected(); return true; } //Directed public boolean removeEdge(Edge edge) { AbstractEdge absEdge = checkEdge(edge); return view.getStructureModifier().deleteEdge(absEdge); } //Directed public NodeIterable getSuccessors(Node node) { readLock(); AbstractNode absNode = checkNode(node); return dhns.newNodeIterable(new NeighborIterator(new EdgeNodeIterator(absNode, EdgeNodeIterator.EdgeNodeIteratorMode.OUT, false, enabledNodePredicate, Tautology.instance), absNode, Tautology.instance)); } //Directed public NodeIterable getPredecessors(Node node) { readLock(); AbstractNode absNode = checkNode(node); return dhns.newNodeIterable(new NeighborIterator(new EdgeNodeIterator(absNode, EdgeNodeIterator.EdgeNodeIteratorMode.IN, false, enabledNodePredicate, Tautology.instance), absNode, Tautology.instance)); } //Directed public boolean isSuccessor(Node node, Node successor) { return getEdge(node, successor) != null; } //Directed public boolean isPredecessor(Node node, Node predecessor) { return getEdge(predecessor, node) != null; } //Directed public int getInDegree(Node node) { AbstractNode absNode = checkNode(node); int count = absNode.getEnabledInDegree(); return count; } //Directed public int getOutDegree(Node node) { AbstractNode absNode = checkNode(node); int count = absNode.getEnabledOutDegree(); return count; } public int getMutualDegree(Node node) { AbstractNode absNode = checkNode(node); int count = absNode.getEnabledMutualDegree(); return count; } //Graph public boolean contains(Edge edge) { if (edge == null) { throw new NullPointerException(); } AbstractEdge absEdge = (AbstractEdge) edge; return getEdge(absEdge.getSource(view.getViewId()), absEdge.getTarget(view.getViewId())) != null; } //Graph public EdgeIterable getEdges() { readLock(); return dhns.newEdgeIterable(new EdgeIterator(structure, new TreeIterator(structure, true, Tautology.instance), false, enabledNodePredicate, Tautology.instance)); } //ClusteredGraph public EdgeIterable getEdgesTree() { readLock(); return dhns.newEdgeIterable(new EdgeIterator(structure, new TreeIterator(structure, true, Tautology.instance), false, Tautology.instance, Tautology.instance)); } //Directed public EdgeIterable getInEdges(Node node) { readLock(); AbstractNode absNode = checkNode(node); return dhns.newEdgeIterable(new EdgeNodeIterator(absNode, EdgeNodeIterator.EdgeNodeIteratorMode.IN, false, enabledNodePredicate, Tautology.instance)); } //Directed public EdgeIterable getOutEdges(Node node) { readLock(); AbstractNode absNode = checkNode(node); return dhns.newEdgeIterable(new EdgeNodeIterator(absNode, EdgeNodeIterator.EdgeNodeIteratorMode.OUT, false, enabledNodePredicate, Tautology.instance)); } //Graph public EdgeIterable getEdges(Node node) { readLock(); AbstractNode absNode = checkNode(node); return dhns.newEdgeIterable(new EdgeNodeIterator(absNode, EdgeNodeIterator.EdgeNodeIteratorMode.BOTH, false, enabledNodePredicate, Tautology.instance)); } //Graph public NodeIterable getNeighbors(Node node) { readLock(); AbstractNode absNode = checkNode(node); return dhns.newNodeIterable(new NeighborIterator(new EdgeNodeIterator(absNode, EdgeNodeIterator.EdgeNodeIteratorMode.BOTH, true, enabledNodePredicate, Tautology.instance), absNode, Tautology.instance)); } //Directed public Edge getEdge(Node source, Node target) { if (source == null || target == null) { return null; } AbstractNode sourceNode = checkNode(source); AbstractNode targetNode = checkNode(target); AbstractEdge res = sourceNode.getEdgesOutTree().getItem(targetNode.getNumber()); return res; } //Graph public int getEdgeCount() { return view.getEdgesCountEnabled(); } //ClusteredGraph public int getTotalEdgeCount() { return view.getEdgesCountEnabled() + view.getMetaEdgesCountTotal(); } //Graph public int getDegree(Node node) { AbstractNode absNode = checkNode(node); int count = absNode.getEdgesInTree().getCount() + absNode.getEdgesOutTree().getCount(); return count; } //Graph public boolean isAdjacent(Node node1, Node node2) { if (node1 == node2) { throw new IllegalArgumentException("Nodes can't be the same"); } return isSuccessor(node1, node2) || isPredecessor(node1, node2); } //Graph public boolean isDirected(Edge edge) { checkEdgeOrMetaEdge(edge); return true; } //ClusteredGraph public EdgeIterable getInnerEdges(Node nodeGroup) { readLock(); AbstractNode absNode = checkNode(nodeGroup); return dhns.newEdgeIterable(new RangeEdgeIterator(structure, view.getViewId(), absNode, absNode, true, false, Tautology.instance, Tautology.instance)); } //ClusteredGraph public EdgeIterable getOuterEdges(Node nodeGroup) { readLock(); AbstractNode absNode = checkNode(nodeGroup); return dhns.newEdgeIterable(new RangeEdgeIterator(structure, view.getViewId(), absNode, absNode, false, false, Tautology.instance, Tautology.instance)); } //ClusteredGraph public EdgeIterable getMetaEdges() { readLock(); return dhns.newEdgeIterable(new MetaEdgeIterator(structure, new TreeIterator(structure, true, Tautology.instance), false)); } public EdgeIterable getEdgesAndMetaEdges() { readLock(); return dhns.newEdgeIterable(new EdgeAndMetaEdgeIterator(structure, new TreeIterator(structure, true, Tautology.instance), false, enabledNodePredicate, Tautology.instance)); } //ClusteredGraph public EdgeIterable getMetaEdges(Node node) { readLock(); AbstractNode absNode = checkNode(node); return dhns.newEdgeIterable(new MetaEdgeNodeIterator(absNode.getMetaEdgesOutTree(), absNode.getMetaEdgesInTree(), MetaEdgeNodeIterator.EdgeNodeIteratorMode.BOTH, false)); } public EdgeIterable getEdgesAndMetaEdges(Node node) { readLock(); AbstractNode absNode = checkNode(node); EdgeNodeIterator std = new EdgeNodeIterator(absNode, EdgeNodeIterator.EdgeNodeIteratorMode.BOTH, false, enabledNodePredicate, Tautology.instance); MetaEdgeNodeIterator meta = new MetaEdgeNodeIterator(absNode.getMetaEdgesOutTree(), absNode.getMetaEdgesInTree(), MetaEdgeNodeIterator.EdgeNodeIteratorMode.BOTH, false); return dhns.newEdgeIterable(new BiEdgeIterator(std, meta)); } public boolean removeMetaEdge(Edge edge) { AbstractEdge absEdge = checkMetaEdge(edge); return view.getStructureModifier().deleteMetaEdge(absEdge); } //DirectedClusteredGraph public EdgeIterable getMetaInEdges(Node node) { readLock(); AbstractNode absNode = checkNode(node); return dhns.newEdgeIterable(new MetaEdgeNodeIterator(null, absNode.getMetaEdgesInTree(), MetaEdgeNodeIterator.EdgeNodeIteratorMode.IN, false)); } public EdgeIterable getInEdgesAndMetaInEdges(Node node) { readLock(); AbstractNode absNode = checkNode(node); EdgeNodeIterator std = new EdgeNodeIterator(absNode, EdgeNodeIterator.EdgeNodeIteratorMode.IN, false, enabledNodePredicate, Tautology.instance); MetaEdgeNodeIterator meta = new MetaEdgeNodeIterator(absNode.getMetaEdgesOutTree(), absNode.getMetaEdgesInTree(), MetaEdgeNodeIterator.EdgeNodeIteratorMode.IN, false); return dhns.newEdgeIterable(new BiEdgeIterator(std, meta)); } //DirectedClusteredGraph public EdgeIterable getMetaOutEdges(Node node) { readLock(); AbstractNode absNode = checkNode(node); return dhns.newEdgeIterable(new MetaEdgeNodeIterator(absNode.getMetaEdgesOutTree(), null, MetaEdgeNodeIterator.EdgeNodeIteratorMode.OUT, false)); } public EdgeIterable getOutEdgesAndMetaOutEdges(Node node) { readLock(); AbstractNode absNode = checkNode(node); EdgeNodeIterator std = new EdgeNodeIterator(absNode, EdgeNodeIterator.EdgeNodeIteratorMode.OUT, false, enabledNodePredicate, Tautology.instance); MetaEdgeNodeIterator meta = new MetaEdgeNodeIterator(absNode.getMetaEdgesOutTree(), absNode.getMetaEdgesInTree(), MetaEdgeNodeIterator.EdgeNodeIteratorMode.OUT, false); return dhns.newEdgeIterable(new BiEdgeIterator(std, meta)); } //DirectedClusteredGraph public int getMetaInDegree(Node node) { AbstractNode absNode = checkNode(node); int count = absNode.getMetaEdgesInTree().getCount(); return count; } public int getTotalInDegree(Node node) { AbstractNode absNode = checkNode(node); int count = absNode.getEnabledInDegree() + absNode.getMetaEdgesInTree().getCount(); return count; } //DirectedClusteredGraph public int getMetaOutDegree(Node node) { AbstractNode absNode = checkNode(node); int count = absNode.getMetaEdgesOutTree().getCount(); return count; } public int getTotalOutDegree(Node node) { AbstractNode absNode = checkNode(node); int count = absNode.getEnabledOutDegree() + absNode.getMetaEdgesOutTree().getCount(); return count; } //ClusteredGraph public int getMetaDegree(Node node) { AbstractNode absNode = checkNode(node); int count = absNode.getMetaEdgesInTree().getCount() + absNode.getMetaEdgesOutTree().getCount(); return count; } public int getTotalDegree(Node node) { AbstractNode absNode = checkNode(node); int count = absNode.getEdgesInTree().getCount() + absNode.getEdgesOutTree().getCount() + absNode.getMetaEdgesInTree().getCount() + absNode.getMetaEdgesOutTree().getCount(); return count; } //ClusteredDirected public MetaEdge getMetaEdge(Node source, Node target) { AbstractNode sourceNode = checkNode(source); AbstractNode targetNode = checkNode(target); return sourceNode.getMetaEdgesOutTree().getItem(targetNode.getNumber()); } @Override public HierarchicalDirectedGraphImpl copy(Dhns dhns, GraphViewImpl view) { return new HierarchicalDirectedGraphImpl(dhns, view); } public EdgeIterable getHierarchyEdges() { throw new UnsupportedOperationException("Not supported yet."); } }