com.miravtech.SBGNUtils.SBGNUtils.java Source code

Java tutorial

Introduction

Here is the source code for com.miravtech.SBGNUtils.SBGNUtils.java

Source

/**
 *
 * Copyright (C) 2010 Razvan Popovici <rp@miravtech.com>
 * Copyright (C) 2010 Luca Beltrame <luca.beltrame@unifi.it>
 * Copyright (C) 2010 Enrica Calura <enrica.calura@gmail.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.miravtech.SBGNUtils;

import java.io.File;
import java.math.BigInteger;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;

import org.apache.commons.beanutils.BeanUtils;
import org.graphdrawing.graphml.xmlns.graphml.Data;
import org.graphdrawing.graphml.xmlns.graphml.Edge;
import org.graphdrawing.graphml.xmlns.graphml.Graph;
import org.graphdrawing.graphml.xmlns.graphml.GraphEdgedefaultType;
import org.graphdrawing.graphml.xmlns.graphml.Graphml;
import org.graphdrawing.graphml.xmlns.graphml.Key;
import org.graphdrawing.graphml.xmlns.graphml.KeyForType;
import org.graphdrawing.graphml.xmlns.graphml.Node;

import com.miravtech.sbgn.AndNodeType;
import com.miravtech.sbgn.ArcType;
import com.miravtech.sbgn.AssociationType;
import com.miravtech.sbgn.AuxiliaryUnitType;
import com.miravtech.sbgn.CatalysisArcType;
import com.miravtech.sbgn.CompartmentType;
import com.miravtech.sbgn.ComplexType;
import com.miravtech.sbgn.ConsumptionArcType;
import com.miravtech.sbgn.DissociationType;
import com.miravtech.sbgn.EntityPoolNodeType;
import com.miravtech.sbgn.InhibitionArcType;
import com.miravtech.sbgn.LogicArcType;
import com.miravtech.sbgn.LogicalOperatorNodeType;
import com.miravtech.sbgn.ModulationArcType;
import com.miravtech.sbgn.NecessaryStimulationArcType;
import com.miravtech.sbgn.NotNodeType;
import com.miravtech.sbgn.OmittedProcessType;
import com.miravtech.sbgn.OrNodeType;
import com.miravtech.sbgn.PhenotypeType;
import com.miravtech.sbgn.ProcessType;
import com.miravtech.sbgn.ProductionArcType;
import com.miravtech.sbgn.SBGNGlyphType;
import com.miravtech.sbgn.SBGNNodeType;
import com.miravtech.sbgn.SBGNPDL1Type;
import com.miravtech.sbgn.SBGNPDl1;
import com.miravtech.sbgn.SelectType;
import com.miravtech.sbgn.SinkType;
import com.miravtech.sbgn.SourceType;
import com.miravtech.sbgn.StateVariableType;
import com.miravtech.sbgn.StatefulEntiyPoolNodeType;
import com.miravtech.sbgn.SubmapType;
import com.miravtech.sbgn.TagType;
import com.miravtech.sbgn.UncertainProcessType;
import com.miravtech.sbgn.StatefulEntiyPoolNodeType.Organism;
import com.miravtech.sbgn.StatefulEntiyPoolNodeType.Organism.Annotation;
import com.miravtech.sbgn.graphics.PaintNode;
import com.miravtech.sbgn_graphics.GraphicType;
import com.yworks.xml.graphml.ArrowTypeType;
import com.yworks.xml.graphml.GeometryType;
import com.yworks.xml.graphml.GroupNode;
import com.yworks.xml.graphml.LineStyleType;
import com.yworks.xml.graphml.NodeLabelModelType;
import com.yworks.xml.graphml.NodeLabelPositionType;
import com.yworks.xml.graphml.NodeLabelType;
import com.yworks.xml.graphml.NodeType;
import com.yworks.xml.graphml.PolyLineEdge;
import com.yworks.xml.graphml.ProxyShapeNode;
import com.yworks.xml.graphml.ResourceType;
import com.yworks.xml.graphml.Resources;
import com.yworks.xml.graphml.SVGNode;
import com.yworks.xml.graphml.ShapeNode;
import com.yworks.xml.graphml.ShapeTypeType;
import com.yworks.xml.graphml.EdgeType.Arrows;
import com.yworks.xml.graphml.GroupNode.State;
import com.yworks.xml.graphml.NodeType.Fill;
import com.yworks.xml.graphml.ProxyShapeNodeType.Realizers;
import com.yworks.xml.graphml.SVGNode.SVGModel;
import com.yworks.xml.graphml.SVGNode.SVGModel.SVGContent;
import com.yworks.xml.graphml.ShapeNode.Shape;

public class SBGNUtils {

    private Map<String, SBGNNodeType> nodes = new HashMap<String, SBGNNodeType>();

    private Set<String> idSet = new HashSet<String>();
    private Set<String> assignedIDs = new HashSet<String>();

    public String getPossibleID(String begin) {
        String root = begin;
        // remove xml unfriendly chars
        root = root.replace('\"', '_');
        root = root.replace('>', '_');
        root = root.replace('\'', '_');
        root = root.replace('<', '_');
        if (!idSet.contains(root)) {
            idSet.add(root);
            return root;
        }
        int i = 1;
        while (true) {
            String id = root + "_" + i++;
            if (!idSet.contains(id)) {
                idSet.add(id);
                return id;
            }

        }
    }

    SBGNPDL1Type in;

    public SBGNUtils(SBGNPDL1Type in) {
        this.in = in;
    }

    public void removeAssignedIDs() {

        new SBGNIterator() {
            @Override
            public void iterateGlyph(SBGNGlyphType n) {
                if (assignedIDs.contains(n.getID())) {
                    n.setID(null);
                }
            }
        }.run(in);

    }

    public void fillRedundantData() throws JAXBException {
        setEmptyLabels();
        setEmptyIDs();
        expandClones();
    }

    public void setEmptyLabels() {
        // set empty labels, if ID is provided
        new SBGNIterator() {
            @Override
            public void iterateNode(SBGNNodeType n) {
                if (n.getLabel() == null && n.getID() != null)
                    n.setLabel(n.getID());
            }
        }.run(in);
    }

    public void setEmptyIDs() throws JAXBException {
        // save the ids in a map
        new SBGNIterator() {
            public void iterateNode(SBGNNodeType n) {
                if (n.getID() != null) // save the entry in the map
                    nodes.put(n.getID(), n);
                if (n.getID() != null)
                    idSet.add(n.getID());
            };
        }.run(in);

        // set the IDs
        new SBGNIterator() {
            @Override
            public void iterateGlyph(SBGNGlyphType n) {

                if (n.getID() != null)
                    return;

                // determine the beginning of the possible id
                String root = null;
                if (n instanceof SBGNNodeType) {
                    SBGNNodeType node = (SBGNNodeType) n;
                    if (node.getLabel() != null)
                        root = node.getLabel();
                }

                if (root == null)
                    root = n.getClass().getSimpleName();
                String id = getPossibleID(root);
                n.setID(id);
                assignedIDs.add(id);
            }
        }.run(in);

    }

    public void expandClones() {
        /*
         * // dump JAXBContext jaxbContext = JAXBContext
         * .newInstance("com.miravtech.sbgn:com.miravtech.sbgn_graphics"); //
         * Marshaller marshaller = jaxbContext.createMarshaller();
         * marshaller.marshal(in, new File("SBGNDEBUG.xml"));
         */
        // solve the clones

        while (true) {
            final boolean[] found = new boolean[1];
            new SBGNIterator() {
                public void iterateNode(SBGNNodeType n) {
                    if (n.getCloneref() != null) {
                        SBGNNodeType cloned = nodes.get(n.getCloneref());
                        if (cloned.getCloneref() == null) {
                            Clone(n, cloned);
                            found[0] = true;
                        }
                    }
                };
            }.run(in);
            if (!found[0])
                break; // no further clone resolved
        }
    }

    // private static int count = 0;

    /**
     * @return
     */
    public Graphml asGraphML() {
        final Graphml graphml = new Graphml();
        Key k;

        k = new Key();
        k.setFor(KeyForType.NODE);
        k.setId("d3");
        k.setYfilesType("nodegraphics");
        graphml.getKeies().add(k);

        k = new Key();
        k.setFor(KeyForType.EDGE);
        k.setId("d6");
        k.setYfilesType("edgegraphics");
        graphml.getKeies().add(k);

        k = new Key();
        k.setFor(KeyForType.GRAPHML);
        k.setId("d0");
        k.setYfilesType("resources");
        graphml.getKeies().add(k);

        final Resources res = new Resources();
        Data d0 = new Data();
        d0.getContent().add(res);
        d0.setKey("d0");

        final Graph main = new Graph();
        graphml.getGraphsAndDatas().add(main);
        main.setEdgedefault(GraphEdgedefaultType.DIRECTED);
        main.setId("MainGraph");

        // the graphical representation of each node
        final Map<SBGNNodeType, Graph> mapping = new HashMap<SBGNNodeType, Graph>();
        mapping.put(null, main);

        new SBGNIterator() {
            public void iterateNode(SBGNNodeType n) {
                GraphicType g = n.getGraphic();

                String textColor = PaintNode.toColorString(PaintNode.getNodeColor(g));
                String bgColor = PaintNode.toColorString(PaintNode.getNodeBgColor(g));
                String borderColor = PaintNode.toColorString(PaintNode.getBorderColor(g));

                Graph loc;
                if (stack.size() == 0) // base
                    loc = main;
                else {
                    loc = mapping.get(getLastNode());
                    if ((getLastNode() instanceof ComplexType))
                        return; // don't paint the inside of the complex
                    if ((n instanceof AuxiliaryUnitType))
                        return; // don't render them
                }

                Node theNode = new Node();
                Data dt = new Data();
                dt.setKey("d3");
                theNode.getDatasAndPorts().add(dt);

                if (n instanceof SinkType || n instanceof AuxiliaryUnitType || n instanceof SourceType
                        || (n instanceof EntityPoolNodeType || n instanceof TagType)) {
                    int sz = res.getResources().size();
                    String ID = "" + (sz + 1);
                    String xml = PaintNode.DrawNode(n);
                    ResourceType r = new ResourceType();
                    r.setId(ID);
                    r.setType("java.lang.String");
                    r.getContent().add(xml);
                    res.getResources().add(r);

                    SVGNode node = new SVGNode();
                    GeometryType gmt = new GeometryType();
                    gmt.setWidth(PaintNode.lastPoint.getX());
                    gmt.setHeight(PaintNode.lastPoint.getY());
                    node.setGeometry(gmt);
                    node.setSVGModel(new SVGModel());
                    node.getSVGModel().setSvgBoundsPolicy("0");
                    node.getSVGModel().setSVGContent(new SVGContent());
                    node.getSVGModel().getSVGContent().setRefid(ID);
                    dt.getContent().add(node);
                }

                NodeLabelType nlt = new NodeLabelType();
                String label = n.getLabel();
                if (n instanceof OmittedProcessType)
                    label = "\\\\";
                if (n instanceof UncertainProcessType)
                    label = "?";
                if (n instanceof DissociationType)
                    label = "O";
                if (n instanceof AndNodeType)
                    label = "AND";
                if (n instanceof OrNodeType)
                    label = "OR";
                if (n instanceof NotNodeType)
                    label = "NOT";
                if (n instanceof AssociationType)
                    label = "";
                if (n instanceof ComplexType) // no label for the complexes
                    label = "";

                nlt.setValue(label);
                nlt.setTextColor(textColor);

                if (n instanceof CompartmentType || n instanceof SubmapType) {
                    nlt.setModelName(NodeLabelModelType.INTERNAL);
                    nlt.setModelPosition(NodeLabelPositionType.TR);
                    ProxyShapeNode p = new ProxyShapeNode();
                    p.setRealizers(new Realizers());
                    p.getRealizers().setActive(new BigInteger("0"));

                    // -------
                    GroupNode gnt = new GroupNode();
                    gnt.setShape(new GroupNode.Shape());
                    if (n instanceof CompartmentType)
                        gnt.getShape().setType(ShapeTypeType.ROUNDRECTANGLE);
                    else
                        gnt.getShape().setType(ShapeTypeType.RECTANGLE); // submap
                    gnt.setFill(new Fill());
                    gnt.getFill().setHasColor(true);
                    gnt.getFill().setColor(bgColor);

                    LineStyleType lst = new LineStyleType();
                    gnt.setBorderStyle(lst);
                    lst.setHasColor(true);
                    lst.setColor(borderColor);
                    lst.setWidth(6.0); // compartiment is shown with ticker ink

                    nlt.setTextColor(textColor);
                    gnt.getNodeLabels().add(nlt);

                    State s = new State();
                    s.setClosed(false);
                    s.setInnerGraphDisplayEnabled(true);
                    gnt.setState(s);

                    p.getRealizers().getShapeNodesAndImageNodesAndGroupNodes().add(gnt);

                    try {
                        GroupNode n1 = (GroupNode) BeanUtils.cloneBean(gnt);
                        n1.getState().setClosed(true);
                        p.getRealizers().getShapeNodesAndImageNodesAndGroupNodes().add(n1);

                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }

                    dt.getContent().add(p);
                    Graph inner = new Graph();
                    inner.setEdgedefault(GraphEdgedefaultType.DIRECTED);

                    theNode.setGraph(inner);
                    mapping.put(n, inner);
                } else {
                    if (n instanceof ProcessType || n instanceof LogicalOperatorNodeType) {
                        // simple node
                        ShapeNode s = new ShapeNode();
                        s.setFill(new NodeType.Fill());
                        s.getFill().setHasColor(false);

                        Shape sh = new Shape();
                        sh.setType(ShapeTypeType.RECTANGLE);
                        if (n instanceof PhenotypeType)
                            sh.setType(ShapeTypeType.DIAMOND);
                        if (n instanceof AssociationType) {
                            sh.setType(ShapeTypeType.ELLIPSE);
                            s.getFill().setHasColor(true);
                            s.getFill().setColor(borderColor);
                        }
                        if (n instanceof DissociationType)
                            sh.setType(ShapeTypeType.ELLIPSE);
                        if (n instanceof LogicalOperatorNodeType)
                            sh.setType(ShapeTypeType.ELLIPSE);
                        s.setShape(sh);

                        if (n instanceof ProcessType) {
                            // processes are shown smaller
                            s.setGeometry(new GeometryType());
                            s.getGeometry().setHeight(15);
                            s.getGeometry().setWidth(15);
                        }

                        LineStyleType lst = new LineStyleType();
                        lst.setHasColor(true);
                        lst.setColor(borderColor);
                        s.setBorderStyle(lst);
                        s.getNodeLabels().add(nlt);
                        dt.getContent().add(s);
                    }
                }
                theNode.setId(n.getID());
                loc.getDatasAndNodesAndEdges().add(theNode);
            };
        }.run(in);

        new SBGNIterator() {
            public void iterateArc(ArcType n) {
                String borderColor = PaintNode.toColorString(PaintNode.getBorderColor(n.getGraphic()));

                SBGNNodeType n1 = nodes.get(n.getRefNode());
                SBGNNodeType n2 = getCurrentNode();

                if (n1 instanceof ProcessType) { // any arc goes to a process,
                    // except production
                    if (!(n instanceof ProductionArcType)) {
                        SBGNNodeType tmp = n1;
                        n1 = n2;
                        n2 = tmp;
                    }
                }
                if (n2 instanceof ProcessType) { // production - process to EPN
                    if (n instanceof ProductionArcType) {
                        SBGNNodeType tmp = n1;
                        n1 = n2;
                        n2 = tmp;
                    }
                }

                if (n2 instanceof EntityPoolNodeType) { // any arc goes from EPN
                    // to process
                    if (!(n instanceof ProductionArcType)) { // except
                        // production
                        SBGNNodeType tmp = n1;
                        n1 = n2;
                        n2 = tmp;
                    }
                }
                if (n1 instanceof EntityPoolNodeType) { // production goes from
                    // process to epn
                    if (n instanceof ProductionArcType) {
                        SBGNNodeType tmp = n1;
                        n1 = n2;
                        n2 = tmp;
                    }
                }
                if (n1 instanceof SinkType) { // Sink is always the target
                    if (n instanceof ConsumptionArcType) {
                        SBGNNodeType tmp = n1;
                        n1 = n2;
                        n2 = tmp;
                    }
                }

                if (n2 instanceof SourceType) { // Source is always the source
                    if (n instanceof ConsumptionArcType) {
                        SBGNNodeType tmp = n1;
                        n1 = n2;
                        n2 = tmp;
                    }
                }

                Edge e = new Edge();

                e.setSource(n1.getID());
                e.setTarget(n2.getID());
                Data dt = new Data();
                dt.setKey("d6");
                e.getDatas().add(dt);
                PolyLineEdge plet = new PolyLineEdge();
                dt.getContent().add(plet);
                Arrows a = new Arrows();
                a.setSource(ArrowTypeType.NONE);
                a.setTarget(ArrowTypeType.NONE);
                // determine the arrow ending type / start
                if (n instanceof ProductionArcType)
                    a.setTarget(ArrowTypeType.DELTA);
                if (n instanceof ModulationArcType)
                    a.setTarget(ArrowTypeType.DIAMOND);
                if (n instanceof CatalysisArcType)
                    a.setTarget(ArrowTypeType.TRANSPARENT_CIRCLE);
                if (n instanceof InhibitionArcType)
                    a.setTarget(ArrowTypeType.T_SHAPE);
                if (n instanceof NecessaryStimulationArcType)
                    a.setTarget(ArrowTypeType.CONCAVE);
                plet.setArrows(a);
                plet.setLineStyle(new LineStyleType());
                plet.getLineStyle().setColor(borderColor);

                main.getDatasAndNodesAndEdges().add(e);
            };
        }.run(in);

        graphml.getGraphsAndDatas().add(d0);

        return graphml;

    }

    // TODO this function does not work for a hierarchical AND/OR construction
    /**
     * Returns the list of inputs for this logic operator node
     * 
     * @param n
     *            the logic operator node
     * @return
     */
    public Set<SBGNNodeType> getInNodesOfLogic(LogicalOperatorNodeType n) {
        getEdges();
        Set<SBGNNodeType> ret = new HashSet<SBGNNodeType>();
        for (ArcType a : connections.get(n)) {
            if (a instanceof LogicArcType) {
                ret.add(getOtherNode(a, n));
            }
        }
        return ret;
    }

    public ArcType getOutArcOfLogic(LogicalOperatorNodeType n) {
        // TODO this function does not work for a hierarchical AND/OR
        // construction
        getEdges();
        for (ArcType a : connections.get(n)) {
            if (!(a instanceof LogicArcType)) {
                return a;
            }
        }
        throw new RuntimeException("Hierarchical AND/OR not implemented");
    }

    /**
     * Returns the output for this logic operator node
     * 
     * @param n
     *            the logic operator node
     * @return
     */
    public SBGNNodeType getOutNodeOfLogic(LogicalOperatorNodeType n) {
        return getOtherNode(getOutArcOfLogic(n), n);
    }

    public void expandSuppathways(SBGNNodeType model) throws Exception {
        // identify all submaps
        final JAXBContext jaxbContext = JAXBContext.newInstance("com.miravtech.sbgn:com.miravtech.sbgn_graphics"); //
        final Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();

        new SBGNIterator() {
            public void iterateNode(SBGNNodeType n) {
                if (n instanceof SubmapType) {
                    SubmapType st = (SubmapType) n;
                    File f = new File(st.getFileLocation());

                    // load the file
                    SBGNPDL1Type root = null;
                    try {
                        root = ((SBGNPDl1) unmarshaller.unmarshal(f)).getValue();
                    } catch (JAXBException e) {
                        throw new RuntimeException(e); // throws the exception as runtime exception
                    }
                    SBGNUtils sbgn = new SBGNUtils(root);
                    // get the submap inner connections

                    // get the submap file connections

                    // identify the connections

                    // add the content of the submap in the current container

                }
            }
        }.run(model);
    }

    /**
     * Copies the content of model to n1.
     * 
     * @param n1
     * @param model
     */
    static void CloneBeans(SBGNNodeType n1, SBGNNodeType model) {

        // TODO iterate all the getters!!
        if (n1.getLabel() == null)
            n1.setLabel(model.getLabel());

        n1.getFinding().addAll(model.getFinding());

        // if lists, append from model to n1

        // if bean objects, not null call recursively
        try {
            if (n1.getGraphic() == null)
                if (model.getGraphic() != null)
                    n1.setGraphic((GraphicType) BeanUtils.cloneBean(model.getGraphic()));

            if (n1 instanceof StatefulEntiyPoolNodeType) {
                StatefulEntiyPoolNodeType n1_epn = (StatefulEntiyPoolNodeType) n1;
                StatefulEntiyPoolNodeType model_epn = (StatefulEntiyPoolNodeType) model;
                n1_epn.getOrganism().addAll(model_epn.getOrganism());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        // if simple object, clone and copy if the n1 side is null

    }

    private SBGNNodeType cloneNode(SBGNNodeType n1) {
        try {

            SBGNNodeType ret = (SBGNNodeType) BeanUtils.cloneBean(n1);
            ret.getInnerNodes().clear();
            for (SBGNNodeType n2 : n1.getInnerNodes()) {
                ret.getInnerNodes().add(cloneNode(n2));
            }
            if (ret.getID() != null)
                ret.setID(getPossibleID(ret.getID()));
            return ret;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * Copy all node data from model to n1
     * 
     * @param target
     * @param model
     */
    void Clone(SBGNNodeType target, SBGNNodeType model) {
        // variables of n1

        if (target.getID() == null) {
            target.setID(getPossibleID(model.getID()));
        }

        // IDs have to be copied and changed to unique ones, since on
        // copying they become non-unique
        SBGNNodeType c = cloneNode(model);
        Map<String, StateVariableType> clonedvars = getNodeVariables(c); // skip
        // the
        // variables
        c.getInnerNodes().removeAll(clonedvars.values());
        target.getInnerNodes().addAll(c.getInnerNodes());

        // !! ids of the existing state vars must be kept unchanged !!
        Map<String, StateVariableType> target_vars = getNodeVariables(target);
        for (Map.Entry<String, StateVariableType> e : getNodeVariables(model).entrySet()) {
            StateVariableType sv = target_vars.get(e.getKey());
            if (sv == null) {
                // clone
                sv = new StateVariableType();
                Clone(sv, e.getValue());
                target.getInnerNodes().add(sv);
            } else {
                sv.setLabel(e.getValue().getLabel());
            }
        }

        // copy the data
        CloneBeans(target, model);

        target.setCloneref(null); // remove the clone attribute.
    }

    public static Map<String, StateVariableType> getNodeVariables(SBGNNodeType n) {
        Map<String, StateVariableType> ret = new HashMap<String, StateVariableType>();
        for (SBGNNodeType n1 : n.getInnerNodes()) {
            if (n1 instanceof StateVariableType) {
                StateVariableType var = (StateVariableType) n1;
                ret.put(var.getVariable(), var);
            }
        }
        return ret;
    }

    public static Map<String, SBGNNodeType> getInnerNodesOfType(SBGNNodeType n, Class<?> c) {
        Map<String, SBGNNodeType> ret = new HashMap<String, SBGNNodeType>();
        for (SBGNNodeType n1 : n.getInnerNodes()) {
            if (c.isInstance(c)) {
                ret.put(n1.getID(), n1);
            }
        }
        return ret;
    }

    /**
     * Returns the list of the symbols for node Goes recursively for the inner
     * nodes
     * 
     * @param organism
     * @param db
     * @param filterExcludedSelection
     * @param n
     * @return
     */
    public static Set<String> getSymbols(final String organism, final String db,
            final boolean filterExcludedSelection, SBGNNodeType n) {
        Set<String> ret = new HashSet<String>();
        if (n instanceof StatefulEntiyPoolNodeType) {
            StatefulEntiyPoolNodeType sepnt = (StatefulEntiyPoolNodeType) n;
            if (!(filterExcludedSelection && n.getSelected() == SelectType.EXCLUDE))
                ret.addAll(getSymbols(organism, db, sepnt));
            for (SBGNNodeType n1 : n.getInnerNodes()) {
                ret.addAll(getSymbols(organism, db, filterExcludedSelection, n1));
            }
        }
        return ret;
    }

    /**
     * Returns the list of the symbols for an organism and database
     * 
     * @param organism
     * @param db
     * @param filterExcludedSelection
     * @return
     */
    public Set<String> getSymbols(final String organism, final String db, final boolean filterExcludedSelection) {
        final Set<String> ret = new HashSet<String>();

        new SBGNIterator() {
            @Override
            public void iterateNode(SBGNNodeType n) {
                if (n instanceof StatefulEntiyPoolNodeType) {
                    StatefulEntiyPoolNodeType sepnt = (StatefulEntiyPoolNodeType) n;
                    if (!(filterExcludedSelection && n.getSelected() == SelectType.EXCLUDE))
                        ret.addAll(getSymbols(organism, db, sepnt));
                }
            }
        }.run(in);
        return ret;
    }

    public Map<String, String> getVariable(final String organism, final String db,
            final boolean filterExcludedSelection, final String variableName) {
        final Map<String, String> ret = new HashMap<String, String>();
        new SBGNIterator() {
            @Override
            public void iterateNode(SBGNNodeType n) {
                if (n instanceof StatefulEntiyPoolNodeType) {
                    StatefulEntiyPoolNodeType sepnt = (StatefulEntiyPoolNodeType) n;
                    if (!(filterExcludedSelection && n.getSelected() == SelectType.EXCLUDE)) {
                        Set<String> sym = getSymbols(organism, db, sepnt);
                        StateVariableType st = getNodeVariables(sepnt).get(variableName);
                        if (st != null) {
                            for (String s : sym)
                                ret.put(s, st.getLabel());
                        }
                    }
                }
            }
        }.run(in);
        return ret;
    }

    static private final String SBGNIDDatabase = "SBGNID";

    public static Set<String> getSymbols(String organism, String db, StatefulEntiyPoolNodeType node) {
        Set<String> ret = new HashSet<String>();
        if (db.equalsIgnoreCase(SBGNIDDatabase)) {
            if (node.getID() != null)
                ret.add(node.getID());
            return ret;
        }
        for (Organism o : node.getOrganism())
            if (organism.equalsIgnoreCase(o.getName()))
                for (Annotation a : o.getAnnotation())
                    if (db.equalsIgnoreCase(a.getDB()))
                        ret.add(a.getID());
        return ret;
    }

    Map<SBGNNodeType, Collection<ArcType>> connections = null;

    /**
     * Returns all the edges of an arch
     * 
     * @param node
     * @return
     */
    public Collection<ArcType> getEdges(SBGNNodeType node) {
        getEdges();
        Collection<ArcType> ret = connections.get(node);
        if (ret == null)
            ret = new HashSet<ArcType>();
        return ret;

    }

    public Set<SBGNNodeType> getRelatedNodes(SBGNNodeType node, Class<?> archType) {
        Set<SBGNNodeType> ret = new HashSet<SBGNNodeType>();
        for (ArcType a : getEdges(node)) {
            if (archType != null && !archType.isAssignableFrom(a.getClass()))
                continue;
            SBGNNodeType rel = getOtherNode(a, node);
            ret.add(rel);
        }
        return ret;
    }

    public SBGNNodeType getOtherNode(ArcType arc, SBGNNodeType node) {
        getEdges();
        for (Map.Entry<SBGNNodeType, Collection<ArcType>> e : connections.entrySet())
            if (e.getValue().contains(arc) && e.getKey() != node)
                return e.getKey();
        throw new RuntimeException("Other side of the arc not found!"); // should
        // not
        // happen
    }

    public Map<SBGNNodeType, Collection<ArcType>> getEdges() {
        // build a node-archs map and check the archs
        if (connections != null)
            return connections;
        connections = new HashMap<SBGNNodeType, Collection<ArcType>>();
        SBGNIterator it2 = new SBGNIterator() {

            @Override
            public void iterateNode(SBGNNodeType n) {
                if (!connections.containsKey(n)) {
                    connections.put(n, new HashSet<ArcType>());
                }
                for (ArcType a : n.getArcs()) {
                    SBGNGlyphType g = nodes.get(a.getRefNode());
                    if (g instanceof SBGNNodeType) {
                        SBGNNodeType n1 = (SBGNNodeType) g;
                        if (!connections.containsKey(n1)) {
                            connections.put(n1, new HashSet<ArcType>());
                        }
                        connections.get(n).add(a);
                        connections.get(n1).add(a);
                    }
                }
            }
        };
        it2.run(in);
        return connections;
    }

}