<%@page contentType="text/html;charset=UTF-8" pageEncoding="ISO-8859-1" session="true"
%><%@page errorPage="Exception.jsp"
%><%@page import="com.fujitsu.iflow.model.bpm.BPMSession"
%><%@page import="com.fujitsu.iflow.model.bpm.BPMAdmin"
%><%@page import="com.fujitsu.iflow.model.bpmcore.BPMSessionImpl"
%><%@page import="com.fujitsu.iflow.model.util.ComplexConditionHelper"
%><%@page import="com.fujitsu.iflow.model.util.IflowEnumeration"
%><%@page import="com.fujitsu.iflow.model.util.QuickForm"
%><%@page import="com.fujitsu.iflow.model.util.URLEncoder"
%><%@page import="com.fujitsu.iflow.model.wfcore.ListSpec"
%><%@page import="com.fujitsu.iflow.model.workflow.Arrow"
%><%@page import="com.fujitsu.iflow.model.workflow.ArrowInstance"
%><%@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.NodeInstance"
%><%@page import="com.fujitsu.iflow.model.workflow.Plan"
%><%@page import="com.fujitsu.iflow.model.workflow.ProcessInstance"
%><%@page import="com.fujitsu.iflow.model.workflow.TimerAction"
%><%@page import="com.fujitsu.iflow.model.workflow.TimerDef"
%><%@page import="com.fujitsu.iflow.model.workflow.TimerStatus"
%><%@page import="com.fujitsu.iflow.model.workflow.WFObjectFactory"
%><%@page import="com.fujitsu.iflow.model.workflow.WFObjectList"
%><%@page import="com.fujitsu.iflow.model.workflow.WorkItem"
%><%@page import="com.fujitsu.iflow.server.dataobjects.ProcessInstanceStatesEnum"
%><%@page import="com.fujitsu.iflow.server.dataobjects.WorkItemStatesEnum"
%><%@page import="java.awt.Point"
%><%@page import="java.io.Writer"
%><%@page import="java.text.SimpleDateFormat"
%><%@page import="java.util.Arrays"
%><%@page import="java.util.Collections"
%><%@page import="java.util.Comparator"
%><%@page import="java.util.Date"
%><%@page import="java.util.Hashtable"
%><%@page import="java.util.Vector"
%><%
    String isArchived = request.getParameter("isArchived");

    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;
    }

    String piId = (String)request.getParameter("piId");
    if (piId == null) {
        throw new Exception("ProcessInstance.jsp requires the process instance id to be specified in a 'piId' parameter.  No such parameter was found on this invocation.");
    }

    long piIdLong;
    try {
         piIdLong = Long.parseLong(piId);
    }
    catch (Exception e4) {
        throw new Exception("The piID variable had a problem being parsed as a long value: "+e4.toString());
    }

    ProcessInstance pi = null;

    if (isArchived != null && isArchived.equals("true")) {
        BPMAdmin bpas = bps.getAdmin();
        pi = bpas.getArchivedProcess(piIdLong);
    }
    else {
        pi = bps.getProcessInstance(piIdLong);
    }

    Plan plan = pi.getPlan();

    StringBuffer reqURL = request.getRequestURL();
    reqURL.append("?");
    if (request.getQueryString() != null) {
        reqURL.append(request.getQueryString());
    }

    String[] stateNames = new String[20];
    stateNames[0] = "Unstarted";
    stateNames[1] = "Ready";
    stateNames[2] = "Disabled";
    stateNames[3] = "Assigned";
    stateNames[4] = "Waiting on Subprocess";
    stateNames[5] = "Closed";
    stateNames[6] = "Aborted";
    stateNames[7] = "Completed";
    stateNames[8] = "Last Work Item Completed";
    stateNames[9] = "Last Work Item Aborted";
    stateNames[10] = "Error";
    stateNames[11] = "Suspended";
    stateNames[12] = "Unknown";
    stateNames[13] = "Unknown";

    String[] stateColors = new String[20];
    String[] processStateColors = new String[20];
    for (int i=0; i<20; i++) {
        stateColors[i] = "orange";  //default
        processStateColors[i] = "orange";  //default
    }
    stateColors[NodeInstance.STATE_INITIAL] = "white";
    stateColors[NodeInstance.STATE_RUNNING] = "mediumspringgreen";
    stateColors[NodeInstance.STATE_WAITING_ON_SUB_PROCESS] = "yellow";
    stateColors[NodeInstance.STATE_COMPLETED] = "lightskyblue";
    stateColors[NodeInstance.STATE_ERROR] = "crimson";

    processStateColors[ProcessInstance.STATE_RUNNING] = "mediumspringgreen";
    processStateColors[ProcessInstance.STATE_ERROR] = "crimson";
    processStateColors[ProcessInstance.STATE_CLOSED] = "lightskyblue";

    String textState = ProcessInstanceStatesEnum.from_int(pi.getState()).toString();

    myOut = out;

    // bring in this processes workitems, if any.
    WFObjectList wfol = WFObjectFactory.getWFObjectList(((BPMSessionImpl)bps)._wfs);
    String transportType = (String) session.getAttribute("TransportType");
    if(transportType == null || !transportType.equalsIgnoreCase("LE")) {
        wfol.addFilter(WFObjectList.LISTFIELD_PROCESSINSTANCE_ID , "=", "'"+ pi.getId() +"'");
    }
    wfol.openBatchedList(Filter.AllWorkItems);
    Object[] workItemList = wfol.getNextBatch(0, 99);

    // goofy habit of API returning null instead of an empty array.
    if (workItemList == null) {
        workItemList = new Object[0];
    }
    SimpleDateFormat sdf = new SimpleDateFormat("MM-dd-yy  hh:mm z");


%>
<HTML>
<HEAD>
<title>Interstage Business Process Manager | Process Instance</TITLE>
<jsp:include page="StyleSheet.jsp" flush="true"/>
<script language="javascript" src="styles/clockscripts.js"></script>
</HEAD>
<body class="bodyClass">
<!--jsp:include page="ProcessHeader.jsp" flush="true"/-->
<jsp:include page="ProcessHeader.jsp" flush="true"/>
<br/>
  <% // Edit Buttons %>
  <table cellpadding=2 cellspacing=1 class="tableclass" align="center" width="90%">
    <tr>
      <td align="left">
        <jsp:include page="ProcessMenu.jsp">
        <jsp:param name="piId" value="<%=String.valueOf(piId) %>" />
        <jsp:param name="referralURL" value="<%=reqURL.toString() %>" />
     </jsp:include>
      </td>
    </tr>
  </table>

<br><TABLE cellpadding=2 cellspacing=1 class="tableClass" width="600" align="center" bgcolor="#CCCCCC">

<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>Process Instance <%= piId %></b></font></td></tr>

<tr><td class="oddrow" width="50">Name:</td>
    <td class="TxtField" width="490">
        <%QuickForm.writeHtml(out,pi.getName());%>
    </td>
    <td class="oddrow" width="50">State:</td>
    <td width="100" bgcolor="<%=processStateColors[pi.getState()]%>">
        <%=textState%>
    </td>
</tr>
<tr><td class="oddrow" width="50">Initiator:</td>
    <td class="TxtField" width="400">
        <%QuickForm.writeHtml(out,pi.getInitiator());%>
    </td>
    <td class="oddrow" width="50">Priority:</td>
    <td class="TxtField" width="100">
        <%=pi.getPriority()%>
    </td>
</tr>
<tr><td class="oddrow" width="50">Created:</td>
    <td class="TxtField" width="400">
        <%=printDate(pi.getCreationTime())%>
    </td>
    <td class="oddrow" width="50">Sequence:</td>
    <td class="TxtField" width="100">
        <%=pi.getSequenceId()%>
    </td>
</tr>
<%
    writeLevel1(out, "Description:", pi.getDescription());
    writeLevel1(out, "Title:", pi.getTitle());
%>
<tr><td class="oddrow" width="150">Process Definition:</td>
    <td class="TxtField" colspan="3" width="740"><%=plan.getId()%>&nbsp; &nbsp;
        <a href="ProcessDefinition.jsp?planId=<%=plan.getId()%>"><%QuickForm.writeHtml(out,plan.getName());%></a>
    </td>
</tr>
</table><br/>

<table border="0" cellpadding="2" cellspacing=1 class="tableClass"
       bgcolor="#CCCCCC" align="center" width="90%">
<tr class="headrow"><td colspan="5"><font class="arialfonts" color="#FFFFFF">
    <b>Process Instance Status</b></font></td></tr>
<%

    NodeInstance[] nis = pi.getMemberNodeInstances();
    Vector v = new Vector();
    // I cant believe there is no built in operation to copy an array into a vector!
    int last = nis.length;
    for (int i=0; i<last; i++) {
        v.addElement(nis[i]);
    }
    NodeComparator nc = new NodeComparator();
    Collections.sort(v, nc);
    for (int i=0; i<last; i++) {
        NodeInstance ni = (NodeInstance) v.elementAt(i);
        int state = ni.getState();
        long nodeId = ni.getNodeInstanceId();
        String stateName = stateNames[state];
        String stateColor = stateColors[state];
        String completedDate = "";
        if (state == NodeInstance.STATE_COMPLETED) {
            completedDate = "unknown";
        }
        if (state != 3) {
            long compDate = -1;
            Hashtable historyInfoTable = getActivityHistoryInfo(pi,ni.getNodeInstanceId());
            Long completionDateLong = (Long) historyInfoTable.get("CompletionDate");
            if(completionDateLong!=null){
                compDate = completionDateLong.longValue();
            }
            String responsibleStr = (String) historyInfoTable.get("Responsible");
            if(responsibleStr==null) {
                responsibleStr = "";
            }

        %><tr><td class="evenrow" width="80"><%=ni.getNodeInstanceId()%></td>
              <td class="oddrow"><%QuickForm.writeHtml(out, ni.getName());%></td>
              <td bgcolor="<%=stateColor%>"><%QuickForm.writeHtml(out, stateName);%></td>
              <td class="oddrow"><%writeDateLong(out, compDate);%></td>
              <td class="oddrow"><%=responsibleStr %></td></tr><%
        }
        else {
        %><tr><td class="evenrow" width="80"><%=ni.getNodeInstanceId()%></td>
              <td class="oddrow"><b><%QuickForm.writeHtml(out, ni.getName());%></b></td>
              <td bgcolor="<%=stateColor%>"><%QuickForm.writeHtml(out, stateName);%></td>
              <td class="oddrow"></td>
              <td class="oddrow"></td></tr>
          <tr><td></td><td colspan=4 class="evenrow">

      <table width="100%" class="tableClass">
        <tr class="headrow" bgcolor="#CCCCCC">
                     <td>WorkItem</td>
                     <td>Assignee</td>
                     <td>Created</td>
                     <td>Status</td>
                 </tr>
          <%
            for (int j=0; j<workItemList.length; j++) {
                WorkItem wi = (WorkItem) workItemList[j];
                long wNodeId = wi.getNodeInstanceId();
                if (nodeId != wNodeId) {
                    continue;
                }
                long wid = wi.getId();
                long cTime = wi.getCreationTime();
                String wiState = "Completed";
                if (wi.getState() != -1) {
                    wiState = WorkItemStatesEnum.from_int(wi.getState()).toString();
                }

                 %>
                 <tr>
                     <td class="evenrow"><a href="WorkItem.jsp?taskId=<%=wid%>"><%=wid%></a></td>
                     <td class="evenrow"><%QuickForm.writeHtml(out, wi.getAssignee());%></td>
                     <td class="evenrow"><%writeDateLong(out, cTime);%></td>
                     <td class="evenrow"><%=wiState%></td>
                 </tr><%
             }
            TimerStatus[] nts = ni.getStatusOfTimers();
            if (nts.length>0) {
                 %><tr class="headrow" bgcolor="#CCCCCC">
                     <td width="100">Timer</td>
                     <td width="200">Name</td>
                     <td width="300">Expires</td>
                     <td width="150"></td>
                 </tr> <%
            }
            for (int j=0; j<nts.length; j++) {
                TimerStatus ntsi = nts[j];
                long timerId = ntsi.getTimerInstanceID();
                String timerName = ntsi.getTimerName();
                long timedExp = ntsi.getTimerExpirationTime();
                boolean isExpired = (System.currentTimeMillis() > timedExp);
                String timerColor = stateColors[NodeInstance.STATE_RUNNING];
                if (isExpired) {
                    timerColor = stateColors[NodeInstance.STATE_COMPLETED];
                }
                %>
                 <tr>
                     <td class="evenrow" width="100"><%=timerId%></td>
                     <td class="evenrow" width="200"><%QuickForm.writeHtml(out, timerName);%></td>
                     <td width="300" bgcolor="<%=timerColor%>"><%writeDateLong(out, timedExp);%></td>
                     <td class="evenrow" width="150"></td>
                 </tr><%
            }
          %>  </table>


               </td></tr><%
        }
    }
%>
</table><br/>
<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>Process Instance Variables: User Defined Attributes</b></font></td></tr>
<%
    DataItemRef[] direfs = pi.getDataItems();
    last = direfs.length;
    for (int i=0; i<last; i++) {
        String UDAName = direfs[i].getName();
        String UDAType = direfs[i].getType();
        String value = direfs[i].getValue();
        %><tr class="oddrow">
          <td class="TxtField" width="50"><%QuickForm.writeHtml(out,UDAType);%></td>
          <td width="150"><%QuickForm.writeHtmlWithNBSPs(out,UDAName);%></td>
          <td width="570"><%
          if(UDAType != null && UDAType.equals(DataItemRef.TYPE_DATE)){
              writeDate(out, value);
          }
          else {
              QuickForm.writeHtmlWithLineBreaks(out,value);
          }%></td>
          </tr>
        <%
        out.flush();
    }


%>
</table><br/>
<table border="0" cellpadding="2" cellspacing=1 class="tableClass"
       bgcolor="#CCCCCC" align="center" width="90%"><tr class="headrow"><td colspan="5"><font class="arialfonts" color="#FFFFFF">
    <b>Timer Status</b></font></td></tr>
<%
    TimerStatus[] ts = pi.getStatusOfTimers();
    last = ts.length;
    for (int i=0; i<last; i++) {
        TimerStatus tstat = ts[i];
        long timerId = tstat.getTimerInstanceID();
        String timerName = tstat.getTimerName();
        long timedExp = tstat.getTimerExpirationTime();
        %><tr>
          <td width="30" align="right"><%=timerId%>.</td>
          <td width="150"><%QuickForm.writeHtml(out,timerName);%></td>
          <td width="150"><%writeDateLong(out, timedExp);%></td>
          </tr><%
    }
%>
</table>

<br>
<table cellpadding=2 cellspacing=1 class="tableclass" align="center" width="90%">
  <tr>
    <td align="left">
      <jsp:include page="ProcessMenu.jsp">
      <jsp:param name="piId" value="<%=String.valueOf(piId) %>" />
      <jsp:param name="referralURL" value="<%=reqURL.toString() %>" />
      </jsp:include>
    </td>
  </tr>
</table>
<p>&nbsp;</p>
</TABLE>
</BODY>
</HTML>

<%!
    boolean showEditButtons = false;
    final int AS_SCRIPT = 1;
    final int AS_TEXT = 2;
    final int AS_HEADER = 3;
    final int AS_HTML = 4;
    Writer myOut;



    public
    void
    writeAll(Writer out, int level, String name, String value, int format, String loc)
         throws Exception
    {
        //suppress null values when not editing
        if (!showEditButtons) {
            if (value==null) {
                return;
            }
            if (value.length()==0) {
                return;
            }
        }
        out.write("<tr>");
        int leftOver = 740;
        if (showEditButtons) {
            leftOver -= 10;
        }
        if (level > 1) {
            out.write("<td class=\"evenrow\" width=\"50\"></td>");
            leftOver -= 50;
            if (level > 2) {
                out.write("<td class=\"evenrow\" width=\"50\"></td>");
                leftOver -= 50;
            }
        }
        out.write("<td class=\"oddrow\" width=\"50\">");
        out.write(name);
        out.write("</td>\n    <td  class=\"TxtField\" colspan=\"");
        out.write(Integer.toString(4-level));
        out.write("\" width=\"");
        out.write(Integer.toString(leftOver));
        out.write("\">");
        if (value == null)
        {
            out.write("<i>null</i>");
        }
        else if (format == AS_SCRIPT)
        {
            writeScript(out, value);
         }
        else if (format == AS_TEXT)
        {
            QuickForm.writeHtmlWithLineBreaks(out, value);
        }
        else if (format == AS_HEADER)
        {
            out.write("<b>");
            QuickForm.writeHtmlWithLineBreaks(out, value);
            out.write("</b>");
        }
        else if (format == AS_HTML)
        {
            out.write(value);
        }
        else
        {
            QuickForm.writeHtmlWithLineBreaks(out, "unknown format");
        }
        if (showEditButtons)
        {
            out.write("</td><td width=\"10\" bgcolor=\"#FFFFFF\">");
            if (loc!=null) {
                out.write("<a href=\"EditPD.jsp?pdId=");
                out.write("888");
                out.write("&mode=");
                out.write(loc);
                out.write("\"><img border=\"0\" src=\"images/edit_sm.gif\"></a>");
            }
        }
        out.write("</td></tr>\n");
        out.flush();
    }

    // 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) {
            NodeInstance nia = (NodeInstance) a;
            NodeInstance nib = (NodeInstance) 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(NodeInstance ni) {
            // first check to see if we already knew the result
            Long id = new Long(ni.getNodeInstanceId());
            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, fir
            ArrowInstance ai[] = ni.getIncomingArrowInstances();
            int last = ai.length;
            for (int j=0; j<last; j++) {
                ArrowInstance aij = ai[j];
                NodeInstance ni2 = aij.getSourceNodeInstance();
                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;
        }
    }
    public
     void
     writeHtmlLevel(Writer out, String name, String value)
         throws Exception
    {
        writeAll(out, 1, name, value, AS_HTML, null);
    }


     public
     void
     writeLevel1(Writer out, String name, String value)
         throws Exception
    {
        writeAll(out, 1, name, value, AS_TEXT, null);
    }

    /***************8
     * the only issue with printing scripts is that if you use the (pre) tag, and
     * if the script is very very long, it warps the whole table.  So this continues
     * to use the (pre) tag, but arbitrarily truncates the scripts if the line gets
     * longer than 80 characters.
     */
    public
    void
    writeScript(Writer out, String script)
        throws Exception
    {
        out.write("<tt>");
        int last = script.length();
        int start = 0;
        boolean beginningOfLine = true;
        for (int pos=0; pos < last; pos++) {
            char c = script.charAt(pos);

            // handle the indent spaces
            if (beginningOfLine) {
                if (c == ' ' || c=='\t') {
                    out.write("&nbsp;");
                    continue;
                }
                beginningOfLine = false;
            }

            // look for and handle end of line
            if (c == '\n') {
                String line = script.substring(start, pos);
                QuickForm.writeHtml(out, line);
                out.write("<br>\n");
                start = pos+1;
                beginningOfLine = true;
                continue;
            }

            // handle case where line is too long
            if (pos - start > 80) {
                String line = script.substring(start, pos);
                QuickForm.writeHtml(out, line);
                out.write("<br>\n");
                start = pos;
                continue;
            }
        }

        //remainder of script
        String line = script.substring(start, last);
        QuickForm.writeHtml(out, line);
        out.write("</tt>");
    }




    /**
    *   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;
        }
    }

    public
    void
    writeDate(Writer out, String dateStr)
        throws Exception
    {
        writeDateLong(out,Long.parseLong(dateStr));
    }

    public
    void
    writeDateLong(Writer out, long dateLong)
        throws Exception
    {
        if (dateLong==-1) {
            return;
        }
        out.write("<script> showDate('");
        out.write(Long.toString(dateLong));
        out.write("'); </script>");
    }

    public
    String
    printDate(long dateLong)
    {
        if(dateLong==-1) return "";
        return  "<script> showDate('"+dateLong+"'); </script>";
    }


    public
    Hashtable
    getActivityHistoryInfo(ProcessInstance pi,long acticityId)
    {
        Hashtable historyInfo = new Hashtable();

        Integer timeStampKey = new Integer(ListSpec.PROCESSHISTORY_TIMESTAMP);
    Integer consumerIdKey = new Integer(ListSpec.PROCESSHISTORY_CONSUMERID);
        Integer producerTypeKey = new Integer(ProcessInstance.HISTORY_PRODUCER_TYPE);
        Integer responisbleKey = new Integer(ListSpec.PROCESSHISTORY_RESPONSIBLE);

             int _processHistoryFields[] = {
            ProcessInstance.HISTORY_ID,
            ProcessInstance.HISTORY_TIME_STAMP,
            ProcessInstance.HISTORY_CONSUMER_ID,
            ProcessInstance.HISTORY_RESPONSIBLE,
            ProcessInstance.HISTORY_PROCESSINSTANCE_ID,
            ProcessInstance.HISTORY_PRODUCER_TYPE,

            };

       try{
        IflowEnumeration sElements = pi.getHistory(_processHistoryFields);

        while(sElements.hasMoreElements()) {
            Hashtable historyData = (Hashtable) sElements.nextElement();
            long consumerId = ((Long) historyData.get(consumerIdKey)).longValue();
        long producerType = ((Long) historyData.get(producerTypeKey)).longValue();


            if(consumerId==acticityId && producerType == 7){
                  historyInfo.put("CompletionDate",historyData.get(timeStampKey));
                  historyInfo.put("Responsible",historyData.get(responisbleKey));
            }

     }
    }catch(Exception ex){
        ex.printStackTrace();
    }
    return historyInfo;
    }



%>
