<%@page contentType="text/html;charset=UTF-8" pageEncoding="ISO-8859-1" session="true"
%><%@page errorPage="Exception.jsp"
%><%@page import="com.fujitsu.iflow.common.JSConversions"
%><%@page import="com.fujitsu.iflow.common.DOMUtils"
%><%@page import="com.fujitsu.iflow.model.bpm.BPMSession"
%><%@page import="com.fujitsu.iflow.model.bpmcore.BPMSessionImpl"
%><%@page import="com.fujitsu.iflow.model.util.QuickForm"
%><%@page import="com.fujitsu.iflow.model.util.URLEncoder"
%><%@page import="com.fujitsu.iflow.model.workflow.Arrow"
%><%@page import="com.fujitsu.iflow.model.workflow.BranchSpec"
%><%@page import="com.fujitsu.iflow.model.workflow.ConditionSpec"
%><%@page import="com.fujitsu.iflow.model.workflow.DataItemRef"
%><%@page import="com.fujitsu.iflow.model.workflow.Filter"
%><%@page import="com.fujitsu.iflow.model.workflow.FormRef"
%><%@page import="com.fujitsu.iflow.model.workflow.JavaAction"
%><%@page import="com.fujitsu.iflow.model.workflow.JavaActionSet"
%><%@page import="com.fujitsu.iflow.model.workflow.Node"
%><%@page import="com.fujitsu.iflow.model.workflow.Plan"
%><%@page import="com.fujitsu.iflow.model.workflow.PlanVersionHistoryElement"
%><%@page import="com.fujitsu.iflow.model.workflow.TimerAction"
%><%@page import="com.fujitsu.iflow.model.workflow.TimerDef"
%><%@page import="com.fujitsu.iflow.model.workflow.TriggerDef"
%><%@page import="java.awt.Point"
%><%@page import="java.io.Writer"
%><%@page import="java.util.Arrays"
%><%@page import="java.util.Enumeration"
%><%@page import="java.util.Hashtable"
%><%@page import="org.w3c.dom.Element"
%><%@page import="org.w3c.dom.NodeList"
%><%
    request.setCharacterEncoding("UTF-8");request.getParameterNames(); //Need dummy call for WL9.1
    BPMSession bps = (BPMSession) session.getAttribute("BPMSession");
    if (bps == null) {
        %><jsp:include page="PasswordPanel.jsp" flush="true"/><%
        return;
    }


    selectedPlanID = (String)request.getParameter("planID");
    if (selectedPlanID == null) {
        // Try with 'planId' - becoz when request comes from XPDLGenerator.
        selectedPlanID = (String)request.getParameter("planId");
        if (selectedPlanID == null)
            throw new Exception("ProcessDefintion.jsp requires the process definition id to be specified as a 'planID' paramater.  No such parameter was found on this invocation.");
    }

    Plan selPlan = bps.getPlan(Integer.parseInt(selectedPlanID));
    String desc = selPlan.getDesc();
    showEditButtons = selPlan.isInEditMode();
    session.setAttribute("TabIndex","2");
    StringBuffer reqURL = request.getRequestURL();
    reqURL.append("?");
    if (request.getQueryString() != null) {
        reqURL.append(request.getQueryString());
    }
%>

<!-- added for floating menu
<%
//    String selectedPlanID = (String)request.getParameter("planId");
    String editMode = (String) request.getParameter("editMode");
    String isEditableStr = (String) request.getParameter("isEditable");

    boolean isEditMode = false;
    if(editMode!=null && editMode.equalsIgnoreCase("true")) isEditMode = true;

    boolean isEditable = false;
    if(isEditableStr!=null && isEditableStr.equalsIgnoreCase("true")) isEditable = true;

    String xpdlURL = "XPDLGenerator.jsp?planId="+selectedPlanID  + "&fromConsole=true";
    String bpelURL = "BPELGenerator.jsp?planId="+selectedPlanID;
    String exportXpdlURL = "ExportXPDL.jsp?planId="+selectedPlanID;
    String graphicalURL = "PDGraphic.jsp?planId="+selectedPlanID;
    String commandURL = "TemplateCommands.jsp?pdId="+selectedPlanID+"&mode=";

%>
-->


<HTML>
<HEAD>
<title>Interstage Business Process Manager | Process Definition</TITLE>
<jsp:include page="StyleSheet.jsp" flush="true"/>
<script language="javascript" src="styles/clockscripts.js"></script>
<style>
.divdhtmlcontent{display:none;}
.divdhtmlcontentshow{display:show;}
</style>
</HEAD>
<body class="bodyClass" onLoad="goforit();">

      <jsp:include page="Header.jsp" flush="true"/>
      <jsp:include page="TemplateMenu.jsp">
          <jsp:param name="planId" value="<%=String.valueOf(selPlan.getId()) %>" />
          <jsp:param name="editMode" value="<%=String.valueOf(selPlan.isInEditMode()) %>" />
          <jsp:param name="referralURL" value="<%=reqURL.toString() %>" />
      </jsp:include>
<table border="0" cellpadding="2" cellspacing="1" class="tableClass"
           bgcolor="#CCCCCC" align="center" width="90%">
    <tr class="headrow"><td colspan="4"><font class="arialfonts" color="#FFFFFF">
        <b>Java calls to Model API</b></td></tr>
    <tr><td>
    <pre>
    Plan plan = ???
<%
    singleParamMethod(out, "plan", "setName", selPlan.getName());
    singleParamMethod(out, "plan", "setTitle", selPlan.getTitle());
    singleParamMethod(out, "plan", "setDesc", selPlan.getDesc());
    singleParamMethod(out, "plan", "setOwner", selPlan.getOwner());
    singleParamMethod(out, "plan", "setProcOwnerRoleScript", selPlan.getProcOwnerRoleScript());
    singleParamMethod(out, "plan", "setInitScript", selPlan.getInitScript());
    singleParamMethod(out, "plan", "getCommitScript", selPlan.getCommitScript());

    writeAction1(out, "plan", "setProcOwnerRoleJavaActionSet", selPlan.getProcOwnerRoleJavaActionSet());
    writeAction1(out, "plan", "setInitJavaActionSet",          selPlan.getInitJavaActionSet());
    writeAction1(out, "plan", "setCommitJavaActionSet",        selPlan.getCommitJavaActionSet());

    TriggerDef[] trigs = selPlan.getTriggers();
    for (int i=0; i<trigs.length; i++) {
        writeTrigger(out, "Trig "+i, trigs[i]);
    }

    out.flush();

    DataItemRef[] dirz = selPlan.getDataItemRefs();
    int last = dirz.length;
    for (int i=0; i<last; i++)
    {
        DataItemRef dir = dirz[i];
    }

    Node[] allNodes = selPlan.getNodes();

    NodeComparator nc = new NodeComparator();
    Arrays.sort(allNodes, nc);

    last = allNodes.length;
    for (int i=0; i<last; i++)
    {
        out.flush();
        Node aNode = allNodes[i];
        String nodeVarName = "node"+aNode.getNodeId();

        out.write("\n    Node "+nodeVarName+" = ??create the node here\n");
        int nodeType = aNode.getType();
        String nodeTypeName = "Unknown";
        boolean formsOK = false;
        long nodeId = aNode.getNodeId();
        switch (nodeType)
        {
            case Node.TYPE_START:
                nodeTypeName = "Start Node";
                break;
            case Node.TYPE_EXIT:
                nodeTypeName = "Exit Node";
                break;
            case Node.TYPE_ACTIVITY:
                nodeTypeName = "Activity Node";
                formsOK = true;
                break;
            case Node.TYPE_AND:
                nodeTypeName = "And Node";
                break;
            case Node.TYPE_CONDITION:
                nodeTypeName = "Condition Node";
                break;
            case Node.TYPE_OR:
                nodeTypeName = "Or Node";
                break;
            case Node.TYPE_SUB_PROCESS:
                nodeTypeName = "Subprocess Node";
                break;
            case Node.TYPE_DELAY:
                nodeTypeName = "Time Delay Node";
                break;
            case Node.TYPE_CHAINED_PROCESS:
                nodeTypeName = "Chained Subprocess Node";
                break;
            case Node.TYPE_VOTING_ACTIVITY:
                nodeTypeName = "Voting Activity Node";
                formsOK = true;
                break;
            case Node.TYPE_REMOTE_SUB_PROCESS:
                nodeTypeName = "Remote Subprocess Node";
                break;
        }

        singleParamMethod(out, nodeVarName, "setName", aNode.getName());
        singleParamMethod(out, nodeVarName, "setDesc", aNode.getDesc());
        Point aPoint = aNode.getPosition();
        singleParamExp(out, nodeVarName, "setPosition", "new Point("+aPoint.x+ ", " + aPoint.y + ")");
        if (aNode.supportForm())
        {
            FormRef[] frs = aNode.getForms();
            int last2 = frs.length;
            for (int j=0; j<last2; j++)
            {
                FormRef fr = frs[j];
                singleParamMethod(out, nodeVarName, "?Form "+j+" Name:", fr.getName());
                singleParamMethod(out, nodeVarName, "?Form "+j+" Path:", fr.getPath());
            }
        }
        if (aNode.supportRole())
        {
            singleParamMethod(out, nodeVarName, "setRole", aNode.getRole());
        }
        if (aNode.supportRoleScript())
        {
            singleParamMethod(out, nodeVarName, "setRoleScript", aNode.getRoleScript());
        }
        if (aNode.supportRoleJavaActionSet())
        {
            writeAction1(out, nodeVarName, "setRoleJavaActionSet", aNode.getRoleJavaActionSet());
        }
        if (aNode.supportPrologueScript()) {
            singleParamMethod(out, nodeVarName, "setPrologueScript", aNode.getPrologueScript());
        }
        if (aNode.supportPrologueJavaActionSet())
        {
            writeAction1(out, nodeVarName, "setPrologueJavaActionSet", aNode.getPrologueJavaActionSet());
        }
        if (aNode.supportSubProcess())
        {
            singleParamExp(out, nodeVarName, "setSubPlanId", Long.toString(aNode.getSubPlanId()));
        }
        if (aNode.supportChainedProcess())
        {
            singleParamExp(out, nodeVarName, "setChainedPlanId", Long.toString(aNode.getChainedPlanId()));
        }
        if (aNode.supportRemoteSubProcess())
        {
            singleParamMethod(out, nodeVarName, "setSubPlanURI", aNode.getSubPlanURI());
        }
        if (aNode.supportEpilogueScript())
        {
            singleParamMethod(out, nodeVarName, "setEpilogueScript", aNode.getEpilogueScript());
        }
        if (aNode.supportEpilogueJavaActionSet())
        {
            writeAction1(out, nodeVarName, "setEpilogueJavaActionSet", aNode.getEpilogueJavaActionSet());
        }
        if (aNode.supportTimer())
        {
            TimerDef[] tz = aNode.getTimers();
            int last4 = tz.length;
            for (int j=0; j<last4; j++)
            {
                TimerDef aTimer = tz[j];
                TimerAction[] taz = aTimer.getTimerActions();
                writeAll(out, 1, "Timer "+j, aTimer.getId()+": "+aTimer.getName(), AS_HEADER, null);
                writeAll(out, 2, "Desc:", aTimer.getDescription(), AS_TEXT, null);
                writeAll(out, 2, "Type:", Integer.toString(aTimer.getType()), AS_TEXT, null);
                writeAll(out, 2, "Time:", aTimer.getTime(), AS_TEXT, null);
                int last5 = taz.length;
                for (int k=0; k<last5; k++)
                {
                    TimerAction aAction = taz[k];
                    writeAll(out, 2, Integer.toString(k)+" Name:", Integer.toString(aAction.getType()), AS_TEXT, null);
                    writeAll(out, 2, Integer.toString(k)+" Script:", aAction.getScriptAction(), AS_TEXT, null);
                    writeAll(out, 2, Integer.toString(k)+" Esc:",    aAction.getEscalateActionNameList(), AS_TEXT, null);
                    writeAll(out, 2, Integer.toString(k)+" Grp:", aAction.getEscalateActionGroupList(), AS_TEXT, null);
                    writeAll(out, 2, Integer.toString(k)+" Mail:", aAction.getSendMailActionFrom(), AS_TEXT, null);
                    writeAll(out, 2, Integer.toString(k)+" To:", aAction.getSendMailActionTo(), AS_TEXT, null);
                    writeAll(out, 2, Integer.toString(k)+" Sub:", aAction.getSendMailActionSubject(), AS_TEXT, null);
                    writeAll(out, 2, Integer.toString(k)+" CC:", aAction.getSendMailActionCc(), AS_TEXT, null);
                    writeAll(out, 2, Integer.toString(k)+" BCC:", aAction.getSendMailActionBcc(), AS_TEXT, null);
                    writeAll(out, 2, Integer.toString(k)+" JA:", aAction.getJavaActionSet(), AS_TEXT, null);
                }
            }
        }
        trigs=null;
        //trigs = aNode.getTriggers();
        if (trigs!=null) {
            for (int k=0; k<trigs.length; k++) {
                writeTrigger(out, "Trig "+k, trigs[k]);
            }
        }
    }
    for (int i=0; i<last; i++)
    {
        Node aNode = allNodes[i];
        ConditionSpec cs = null;
        if (aNode.supportConditionSpec())
        {
             cs = aNode.getConditionSpec();
        }
        Arrow[] az = aNode.getOutgoingArrows();
        int last2 = az.length;
        for (int j=0; j<last2; j++)
        {
            Arrow aArrow = az[j];
            long arrowId = aArrow.getArrowId();
            String arrowVarName = "arrow"+arrowId;

            Node target = aArrow.getTargetNode();
            Point startPoint = null;
            out.write("\n    Arrow "+arrowVarName+" = ??create new arrow here\n");
            singleParamMethod(out, arrowVarName, "setName", aArrow.getName());
            singleParamExp(out, arrowVarName, "setSourceNode", "node"+aArrow.getSourceNode().getNodeId());
            singleParamExp(out, arrowVarName, "setTargetNode", "node"+aArrow.getTargetNode().getNodeId());
            singleParamMethod(out, arrowVarName, "setDesc", aArrow.getDesc());

            writeAll(out, 2, "Points:", "cc", AS_TEXT, "points&arrow="+arrowId);
            if (cs != null)
            {
                BranchSpec bs = cs.getBranchSpec(aArrow.getName());
                String compOp = " ?? ";
                switch (bs.getComparisonOperator())
                {
                    case BranchSpec.EQUAL_OP:
                        compOp = " == ";
                        break;
                    case BranchSpec.NOT_EQUALS_OP:
                        compOp = " != ";
                        break;
                    case BranchSpec.LESS_THAN_OP:
                        compOp = " &lt; ";
                        break;
                    case BranchSpec.LESS_THAN_OR_EQUALS_OP:
                        compOp = " &lt;= ";
                        break;
                    case BranchSpec.GREATER_THAN_OP:
                        compOp = " &gt; ";
                        break;
                    case BranchSpec.GREATER_THAN_OR_EQUALS_OP:
                        compOp = " &gt;= ";
                        break;
                }
                if (bs.isDefault())
                {
                    singleParamExp(out, arrowVarName, "isDefault?", "true");
                }
                writeAll(out, 2, "Condition:", "d", AS_TEXT, null);
            }
        }
    } // FOR ENDS HERE
%>
    </pre>
    </td>
  </tr>
</table>


</BODY>
</HTML>

<%!

    boolean showEditButtons =false;
    String  selectedPlanID = null;

    final int AS_SCRIPT = 1;
    final int AS_TEXT = 2;
    final int AS_HEADER = 3;
    final int AS_HTML = 4;


    public
    void
    writeAll(Writer out, int level, String name, String value, int format, String loc)
         throws Exception
    {
        if (true) return;
    }

    public
    void
    writeAction1(Writer out, String obj, String method, JavaActionSet jas)
        throws Exception
    {
        if (jas == null) {
            return;
        }

        int count = jas.getActionCount();
        char specialChar = method.charAt(3);
        JavaAction[] jaa = jas.getJavaActions();

        out.write("    JavaActionSet "+obj+"ja = ??create Java ACtion Set\n");
        String jaArrayVarName = obj+"jb"+specialChar;
        out.write("    JavaAction[]  "+jaArrayVarName+" = new JavaAction["+count+"]\n");

        if (jaa == null) {
            out.write("    throw new Exception(&quot;This array of actions is null, not allowed!&quot;);\n");
            return;
        }
        for (int i=0; i<count; i++) {
            JavaAction ja = jaa[i];

            String jaVarName = jaArrayVarName+"["+i+"]";

            singleParamMethod(out, jaVarName, "setActionName", ja.getActionName());
            singleParamMethod(out, jaVarName, "setActionDescription", ja.getActionDescription());
            singleParamMethod(out, jaVarName, "setClassPath", ja.getClassPath());
            singleParamMethod(out, jaVarName, "setClassName", ja.getClassName());
            singleParamMethod(out, jaVarName, "setReturnValueUDAName", ja.getReturnValueUDAName());
            String params = ja.getArgumentsUDANames();
            if (params.indexOf("<E>")!=0) {
                singleParamMethod(out, jaVarName, "setArgumentsUDANames", params);
            }
            else {
                String parseable = "<g>"+params+"</g>";
                Element dom = DOMUtils.convertStringToDom(parseable);
                NodeList nl = dom.getChildNodes();
                int nllen = nl.getLength();
                out.write("    Document dom = new-empty-XML-document?;\n");

                for (int iii=0; iii<nllen; iii++) {
                    org.w3c.dom.Node nnParent = nl.item(iii);
                    String val = DOMUtils.textValueOf(nnParent, false);
                    out.write("    dom.addChild(");
                    QuickForm.writeHtml(out, JSConversions.quote4JS(val));
                    out.write(");\n");
                }
                out.write("    "+jaVarName+".setParams(dom);\n");
            }
            singleParamMethod(out, jaVarName, "setBeanName", ja.getBeanName());
            singleParamMethod(out, jaVarName, "setBeanMethod?", ja.getBeanName());
            singleParamMethod(out, jaVarName, "setBeanMethodArgumentsUDANames", ja.getBeanMethodArgumentsUDANames());
        }
        singleParamExp(out, obj+"ja", "setJavaActions", jaArrayVarName);
    }

    private
    void
    writeTrigger(Writer out, String label, TriggerDef trig)
        throws Exception
    {
        StringBuffer sit = new StringBuffer();
        String trigVarName = "trig"+trig.getId();
        out.write("    Trigger "+trigVarName+" = ???create new trigger\n");
        singleParamMethod(out, trigVarName, "setName", trig.getName());
        singleParamMethod(out, trigVarName, "setDescription", trig.getDescription());
        singleParamExp(out, trigVarName, "setType?", Long.toString(trig.getType()));
        singleParamExp(out, trigVarName, "setState?", Long.toString(trig.getState()));
        if (trig.isActive()) {
            singleParamExp(out, trigVarName, "setActive?", "true");
        }
        String[] conds = trig.getControlConditions();
        if (conds!=null && conds.length>0) {
            out.write("    String [] conds = new String["+conds.length+"];\n");
            for (int i=0; i<conds.length; i++) {
                out.write("    conds["+i+"] = ");
                QuickForm.writeHtml(out, JSConversions.quote4JS(conds[i]));
            }
            singleParamMethod(out, trigVarName, "getControlConditions", "conds");
        }
        if (true) return;

        int ac = trig.getActionCount();
        for (int actNo=0; actNo<ac; actNo++) {
            String[] param = trig.getActionParams(actNo);
            for (int i=0; i<param.length; i++) {
                writeAll(out, 2, "Params "+actNo+" "+i, param[i], AS_TEXT, null);
            }
            writeAll(out, 2, "Condition"+actNo, trig.getActionCondition(actNo), AS_TEXT, null);
        }

        Hashtable dMap = trig.getDataMap();
        Enumeration e1 = dMap.keys();
        while (e1.hasMoreElements()) {
            String key1 = (String) e1.nextElement();
            String value1 = (String) dMap.get(key1);
            writeAll(out, 2, "Data", key1 + " = " + value1, AS_TEXT, null);
        }
        Hashtable cMap = trig.getCorrelationMap();
        Enumeration e2 = cMap.keys();
        while (e2.hasMoreElements()) {
            String key2 = (String) e2.nextElement();
            String value2 = (String) dMap.get(key2);
            writeAll(out, 2, "Corr", key2 + " == " + value2, AS_TEXT, null);
        }
    }

    private
    String
    getSubtext(
        BPMSession bps,
        Plan selPlan)
        throws Exception
    {
        PlanVersionHistoryElement[] planHistory = bps.getPlanVersionHistory(selPlan.getName());

        long planId = -1;
        // Look for a published plan.
        for(int i=0; i< planHistory.length; i++) {
            if (planHistory[i].getState() == Plan.STATE_PUBLISHED) {
                planId = planHistory[i].getPlanId();
                break;
            }
        }

        if (planId != -1) {
            // There is a published plan
            if (planId == Long.parseLong(selectedPlanID)) {
                // Current plan is a published plan. So no subtext needed.
                return null;
            }
            else {
                // Subtext needed.
                return "(The published version of this process definition hides this process definition for ASAP interactions)";
            }
        }
        else {
            // There is no published plan. Check if there is any "Draft" plan for this user with a higher version number
            String requestUser = bps.getUserName();
            for(int i=0; i< planHistory.length; i++) {
                if (planHistory[i].getState() == Plan.STATE_DRAFT &&
                    requestUser.equals(planHistory[i].getOwner()))
                {
                    if (isHigherVersion(planHistory[i].getMajorVersion(), planHistory[i].getMinorVersion(), selPlan)) {
                        // Subtext needed
                        return "(The latest version of this process definition hides this process definition for ASAP interactions)";
                    }
                }
            }
            // No higher version found. No comment needed.
            return null;
        }
    }

    private
    boolean
    isHigherVersion(
        int majorVersion,
        int minorVersion,
        Plan selPlan)
        throws Exception
    {
        String selPlanVersion = selPlan.getVersion();
        int selPlanMajorVersion = Integer.parseInt(selPlanVersion.substring(0,selPlanVersion.indexOf(".")));
        int selPlanMinorVersion = Integer.parseInt(selPlanVersion.substring(selPlanVersion.indexOf(".")+1));

        if (majorVersion > selPlanMajorVersion) return true;
        if (majorVersion == selPlanMajorVersion) {
            if (minorVersion > selPlanMinorVersion)
            return true;
        }
        return false;
    }

    private
    void
    singleParamMethod(Writer out, String obj, String method, String param)
        throws Exception
    {
        if (param==null) {
            return;
        }
        if (param.length()==0) {
            return;
        }
        singleParamExp(out, obj, method, JSConversions.quote4JS(param));
    }
    private
    void
    singleParamExp(Writer out, String obj, String method, String param)
        throws Exception
    {
        if (param==null) {
            return;
        }

        out.write("    ");
        out.write(obj);
        out.write(".");
        out.write(method);
        out.write("(");
        QuickForm.writeHtml(out, param);
        out.write(");\n");
    }

    /**
    *   This comparator is used to sort the process definition list into ascending order
    *   relatively to their ID.
    */
    class PlanIDComparator implements java.util.Comparator
    {
        public int compare(Object obj1, Object obj2)
        {
            if ( obj1 == null || obj2 == null ||
                !(obj1 instanceof Plan) || !(obj2 instanceof Plan) )
                return 0;
            Plan plan1 = (Plan)obj1;
            Plan plan2 = (Plan)obj2;
            if ( plan1.getId() < plan2.getId() ) return -1;
            else return 1;
        }
    }


    // This comparitor is used to sort the activities into a reasonable
    // order.  It figures out how many hops the node is away from the
    // start node.  Then for all the nodes in the same number of
    // hops, it takes into account X & Y locations, closer to upper
    // left corner the earlier it will be in the list.

    class NodeComparator implements java.util.Comparator
    {
        NodeComparator() {}

        Hashtable jumpsFromStart = new Hashtable();

        public int compare(Object a, Object b) {
            Node nia = (Node) a;
            Node nib = (Node) b;
            Point pa = nia.getPosition();
            int vala = pa.x + 2*pa.y + 10000*findJumpsFromStart(nia);
            Point pb = nib.getPosition();
            int valb = pb.x + 2*pb.y + 10000*findJumpsFromStart(nib);
            if (vala < valb) {
                return -1;
            }
            if (vala == valb) {
                return 0;
            }
            return 1;
        }

        int findJumpsFromStart(Node ni) {
            // first check to see if we already knew the result
            Long id = new Long(ni.getNodeId());
            Integer storedVal = (Integer) jumpsFromStart.get(id);
            if (storedVal != null) {
                return storedVal.intValue();
            }

            // check to see if this is the start node
            int nodeType = ni.getType();
            if (nodeType == Node.TYPE_START) {
                jumpsFromStart.put(id, new Integer(0));
                return 0;
            }

            // prevent infinite loops
            jumpsFromStart.put(id, new Integer(-1));

            // now start search
            Arrow ai[] = ni.getIncomingArrows();
            int last = ai.length;
            for (int j=0; j<last; j++) {
                Arrow aij = ai[j];
                Node ni2 = aij.getSourceNode();
                int t = findJumpsFromStart(ni2);
                if (t >= 0) {
                    jumpsFromStart.put(id, new Integer(t+1));
                    return t+1;
                }
            }

            // if we get here, then a full depth search has not found
            // a start node, which means we are disconnected from
            // the start node, so return a high number
            jumpsFromStart.put(id, new Integer(100));
            return 100;
        }
    }


%>
