package ieg.prefuse.data;

import prefuse.data.Graph;
import prefuse.data.Table;
import prefuse.data.Tree;
import prefuse.data.tuple.TupleManager;

/**
 * Hierarchical structure where a node can have multiple parents and multiple
 * children. This is realized as a directed {@link Graph}, where inbound edges
 * connect a node to its children and outgoing edges connect it to its parents.
 * Note that edges direction is opposite in the {@link Tree} class.
 * 
 * <p>
 * The proxy tuple type {@link ParentChildNode} provides suitable convenience methods.
 * However, the tuple type needs to be set using
 * {@link #initTupleManagers(Class, Class)}. This is not done automatically under
 * the assumption that a subclass of {@link ParentChildNode} would be used more often.
 * 
 * @author Rind
 */
public class ParentChildGraph extends Graph {

    /**
     * Instances are always directed.
     */
    public ParentChildGraph() {
        super(true);
    }
    
    public ParentChildGraph(Table nodes) {
        super(nodes, true);
    }

    public ParentChildGraph(Table nodes, Table edges) {
        super(nodes, edges, true);
    }

    @SuppressWarnings("rawtypes")
    public void initTupleManagers(Class nodeType, Class edgeType) {
        TupleManager nodeTuples = new TupleManager(super.getNodeTable(), this,
                nodeType);
        TupleManager edgeTuples = new TupleManager(super.getEdgeTable(), this,
                edgeType);
        super.setTupleManagers(nodeTuples, edgeTuples);
        super.getNodeTable().setTupleManager(nodeTuples);
        super.getEdgeTable().setTupleManager(edgeTuples);
    }

    /**
     * Get the number of children of the given node id.
     * 
     * @param node
     *            a node id (node table row number)
     * @return the number of child nodes for the given node
     */
    public int getChildCount(int node) {
        return getInDegree(node);
    }

    /**
     * Get the child node id at the given index.
     * 
     * @param node
     *            the parent node id (node table row number)
     * @param idx
     *            the child index
     * @return the child node id (node table row number)
     */
    public int getChildRow(int node, int idx) {
        int cc = getChildCount(node);
        if (idx < 0 || idx >= cc)
            return -1;
        int[] links = (int[]) m_links.get(node, INLINKS);
        return getSourceNode(links[idx]);
    }

    /**
     * Get the number of parents of the given node id.
     * 
     * @param node
     *            a node id (node table row number)
     * @return the number of parent nodes for the given node
     */
    public int getParentCount(int node) {
        return getOutDegree(node);
    }

    /**
     * Get the parent node id at the given index.
     * 
     * @param node
     *            the child node id (node table row number)
     * @param idx
     *            the parent index
     * @return the parent node id (node table row number)
     */
    public int getParentRow(int node, int idx) {
        int cc = getParentCount(node);
        if (idx < 0 || idx >= cc)
            return -1;
        int[] links = (int[]) m_links.get(node, OUTLINKS);
        return getTargetNode(links[idx]);
    }

    // TODO implement depth using m_links as cache for such metadata

}

@@ -22,16 +22,43 @@
 ata;%0D%0A%0D%0A
+import prefuse.data.Edge;%0D%0A
 import p
@@ -128,24 +128,62 @@
 data.Tree;%0D%0A
+import prefuse.data.tuple.TableEdge;%0D%0A
 import prefu
@@ -635,224 +635,126 @@
 %0A * 
-However, the tuple type needs to be set using%0D%0A * %7B@link #initTupleManagers(Class, Class)%7D. This is not done automatically under%0D%0A * the assumption that a subclass of %7B@link ParentChildNode%7D would be used more often.
+%0D%0A * %3Cp%3E%0D%0A * Added:         201?-??-?? / AR%3Cbr%3E%0D%0A * Modifications: 2013-06-11 / AR / tuple manager intialized%0D%0A * %3C/p%3E
 %0D%0A *
@@ -935,24 +935,92 @@
 per(true);%0D%0A
+        initTupleManagers(ParentChildNode.class, TableEdge.class);%0D%0A
     %7D%0D%0A    %0D
@@ -1059,16 +1059,42 @@
 le nodes
+, boolean initTupleManager
 ) %7B%0D%0A   
@@ -1111,32 +1111,341 @@
 (nodes, true);%0D%0A
+        if (initTupleManager) %7B%0D%0A            initTupleManagers(ParentChildNode.class, TableEdge.class);%0D%0A        %7D%0D%0A    %7D%0D%0A%0D%0A    public ParentChildGraph(Table nodes,%0D%0A            Class%3C? extends ParentChildNode%3E nodeType) %7B%0D%0A        super(nodes, true);%0D%0A        initTupleManagers(nodeType, TableEdge.class);%0D%0A
     %7D%0D%0A%0D%0A    pub
@@ -1489,16 +1489,42 @@
 le edges
+, boolean initTupleManager
 ) %7B%0D%0A   
@@ -1564,103 +1564,453 @@
     
-%7D%0D%0A%0D%0A    @SuppressWarnings(%22rawtypes%22)%0D%0A    public void initTupleManagers(Class nodeType, Class
+    if (initTupleManager) %7B%0D%0A            initTupleManagers(ParentChildNode.class, TableEdge.class);%0D%0A        %7D%0D%0A    %7D%0D%0A%0D%0A    public ParentChildGraph(Table nodes, Table edges,%0D%0A            Class%3C? extends ParentChildNode%3E nodeType) %7B%0D%0A        super(nodes, edges, true);%0D%0A        initTupleManagers(nodeType, TableEdge.class);%0D%0A    %7D%0D%0A%0D%0A    public void initTupleManagers(Class%3C? extends ParentChildNode%3E nodeType,%0D%0A            Class%3C? extends Edge%3E
  edg
@@ -2227,32 +2227,193 @@
     edgeType);%0D%0A
+        initTupleManagers(nodeTuples, edgeTuples);%0D%0A    %7D%0D%0A%0D%0A    public void initTupleManagers(TupleManager nodeTuples,%0D%0A            TupleManager edgeTuples) %7B%0D%0A
         super.se

initialize tuple manager by default; offer alternative constructors