<%@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.workflow.WFObjectFactory"
%><%@page import="com.fujitsu.iflow.model.util.Log"
%><%@page import="com.fujitsu.iflow.common.UdaNameSanitizer"
%><%@page import="com.fujitsu.iflow.model.workflow.DataItemRef"
%><%@page import="com.fujitsu.iflow.model.workflow.WorkItem"
%><%@page import="com.fujitsu.iflow.model.workflow.ProcessInstance"
%><%@page import="java.util.*"
%><%@page import="java.text.SimpleDateFormat"
%><%@page import="java.math.BigDecimal"
%><%@page import="java.util.Date"
%><%@page import="java.text.DateFormat"
%><%@page import="java.util.Locale"
%><%@page import="java.text.ParseException"
%><%@page import="com.fujitsu.iflow.model.util.URLEncoder"
%><% 
    request.setCharacterEncoding("UTF-8");request.getParameterNames(); //Need dummy call for WL9.1
    BPMSession bps = (BPMSession) session.getAttribute("BPMSession");
    if (bps == null) 
    {
        throw new Exception("You are not logged in, or your log-in session has expired.  Go back to the previous page, refresh the page, and log in before tyring this function again.");
    }

    String taskIdStr = request.getParameter("taskId");
    if (taskIdStr == null) 
    {
        throw new Exception("WorkItemAction.jsp needs a parameter called 'taskId' that specifies the integer task id.");
    }
    long taskId;
    try 
    {
        taskId = Long.parseLong(taskIdStr);
    }
    catch (Exception e) 
    {
        throw new Exception("Problem with 'taskId': "+e.toString());
    }
    String formName = request.getParameter("Forms");

    String choice = request.getParameter("choice");
    if (choice == null)
    {
        choice = "";
    }
    String cmdValue = request.getParameter("cmd");
    if (cmdValue == null)
    {
        cmdValue = "";
    }
    String isCompletedWI = request.getParameter("isCompleted");
    WorkItem task = null;
    try 
    {
        if (isCompletedWI != null)
        {
            int completeWiIndex;
            try 
            {
                completeWiIndex = Integer.parseInt(isCompletedWI);
            }
            catch (NumberFormatException nfe)
            {
                completeWiIndex = -1;
            }

            if (completeWiIndex >= 0) 
            {
                WorkItem[] tasks = (WorkItem[])session.getAttribute("completedTasks");
                if (tasks == null || tasks.length <= 0) 
                {
                    throw new Exception("Missing workitem information for task #" + taskId);
                }
                task = tasks[completeWiIndex];
            }
        }
        else 
        {
            task = bps.getWorkItem(taskId);
        }
        if (task == null) 
        {
            throw new Exception("Perhaps that task is no longer available.");
        }
    }
    catch (Exception e) 
    {
        throw new Exception("Unable to find the work item with id '" + taskId + "', because: "+e.toString());
    }

    ProcessInstance pi = task.getProcessInstance();
    int actual_piSeqId = pi.getSequenceId();
    int form_piSeqId=-1;
    if(request.getParameter("procSeq") != null)
    {
        form_piSeqId = Integer.parseInt(request.getParameter("procSeq"));
    }
    else
    {
        form_piSeqId = actual_piSeqId;
    }
    Vector attributeList = new Vector();
    String formsUrlParam = "";
    if (formName == null) 
    {
        formName = "";
    }
    else 
    {
        formsUrlParam = "&Forms="+URLEncoder.encode(formName, "UTF-8");
    }
    String workItemUrl = "WorkItem.jsp?taskId=" + taskId + formsUrlParam;
    if (isCompletedWI != null) 
    {
        workItemUrl = workItemUrl + "&isCompleted="+isCompletedWI;
    }

    Properties properties = new Properties();
    boolean ok = true;
    Enumeration paramNames = (Enumeration)request.getParameterNames();
    while(paramNames.hasMoreElements())
    {
        String pName = (String)paramNames.nextElement();
        if (pName.toLowerCase().indexOf("attachment:") > -1) 
        {
            cmdValue = pName;
        }
        else if (pName.startsWith("uda_")) 
        {
            attributeList.addElement(pName.substring(4));
        }
    }

    String workTime = request.getParameter("workTime");
    long ms = 0;
    if (workTime != null && !workTime.trim().equals("00:00:00"))
    {
        try 
        {
            ms = parseTimeString(workTime);
        }
        catch (Exception e) 
        {
            throw new Exception("Unable to set the work duration value of '"+workTime+"' because: "+e.toString());
        }
    }
    //if refresh then don't do anything else
    if (cmdValue.equalsIgnoreCase("refresh")) 
    {
        response.sendRedirect(response.encodeRedirectURL(workItemUrl));
        return;
    }

    if (actual_piSeqId != form_piSeqId)
    {
        request.setAttribute("message", "The process instance has been changed since your last access, refetch the WorkItem");
        request.setAttribute("nextPage", workItemUrl);
        request.setAttribute("nextLink", "Refresh WorkItem");
        %>
            <jsp:forward page="Error.jsp" />
        <%
    }

    if (attributeList != null && attributeList.size() > 0)
    {
        DataItemRef[] udaData = pi.getDataItems();
        int ulen = udaData.length;
        String uNames[] = new String[ulen];
        for (int i=0; i<ulen; i++)
        {
            uNames[i] = udaData[i].getName();
        }
        Hashtable udaLookup = UdaNameSanitizer.getReverseLookup(uNames);
        Properties udas = new Properties();
        boolean bDataChanged = false;

        //StringBuffer debugMsg = new StringBuffer();
        for ( int i = 0; i < attributeList.size(); i ++ )
        {
            String attributeIdentifier = (String)attributeList.elementAt(i);
            String attributeName = (String)udaLookup.get(attributeIdentifier);
            //debugMsg.append("\n-> ");
            //debugMsg.append(attributeIdentifier);

            if (attributeName == null)
            {
                continue;  //ignore this variable that does not exist in process
            }
            String[] attributeVal = request.getParameterValues("uda_" + attributeIdentifier);
            String attributeValue = request.getParameter("uda_" + attributeIdentifier);
            String[] displAttributeVal = request.getParameterValues("displ_uda_" + attributeIdentifier);
            try 
            {
                if(attributeVal.length ==1)
                {
                    if (!typeMatches(attributeName, attributeValue, udaData) ) 
                    {
                        throw new Exception("Unable to store value into UDA variable '" + attributeName+ "'");                       
                    }
                    attributeValue = getRightValue(attributeName, attributeValue, udaData);
                    udas.put(attributeName, attributeValue);
                }
                else if(attributeVal.length>1)
                {  
                    attributeValue ="";
                    for(int index =0;index<attributeVal.length;index++)
                    {
                        attributeValue += attributeVal[index];
                        if(index<attributeVal.length-1)
                        {
                            attributeValue +="&sep;";
                        }
                    }
                    udas.put(attributeName, attributeValue);
                }
                if (!bDataChanged && !valueMatches(attributeName, attributeValue, udaData)) 
                {
                    bDataChanged = true;
                }
            }
            catch (Exception e) 
            {
                throw new Exception("Unable to store value into UDA variable '" + attributeName
                        + "' because: " + e.toString());
            }
            //debugMsg.append(" success");
        }
        try
        {
            if (bDataChanged) 
            {
                pi.startEdit();
                pi.setDataItemValues(udas);
                pi.commitEdit();
            }
        }
        catch (Exception e) 
        {
            throw new Exception ("Unable to edit and update the values on the process instance, because: " + e.toString());
        }
        //throw new Exception(debugMsg.toString());
    }

    //if save then we are done at this point
    if (cmdValue.equalsIgnoreCase("save")) 
    {

        if (choice.length() <= 0) 
        {
            task.recordWorkTime(ms);
        }
        response.sendRedirect(response.encodeRedirectURL(workItemUrl));
        return;
    }


    if (choice.length() > 0) 
    {
        task.makeChoice(choice, ms);
        %>
                <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
                    <html>
                        <head>
                            <title>Interstage Business Process Manager | Work Item Start</title>
                            <jsp:include page="StyleSheet.jsp" flush="true"/>
                            <meta http-equiv=refresh content="2; url=WorkList.jsp">
                            <script language="javascript" src="styles/clockscripts.js"></script>
                        </head>
                        <body class="bodyClass" onLoad="goforit();">
                            <jsp:include page="WorkItemHeader.jsp" flush="true"/>
                            <br/>
                            <center><font class="arialfonts">Work Item <%=taskId%> is completed.  (state = <%= task.getState() %>)<br>
                                    <a href="WorkList.jsp">Click here to return to Worklist or please wait till the page gets reloaded.</a></font>
                            </center>
        <%
        return;
    }

       String docUrlBase = "../servlet/DocumentAction?taskId="+taskId+"&documentName=";
       if (cmdValue != null) 
       {
        if (cmdValue.equalsIgnoreCase("accept"))
        {
            task.accept();
            session.setAttribute("accepted", "yes");
            session.removeAttribute("declined");
            session.removeAttribute("attributeNames");
        }
        else if (cmdValue.equalsIgnoreCase("decline")) 
        {
            task.decline();
            session.setAttribute("declined", "yes");
            session.removeAttribute("accepted");
            session.removeAttribute("attributeNames");
            workItemUrl = "WorkList.jsp";
        }
        else if (cmdValue.equalsIgnoreCase("reassign")) 
        {
            if (formName == null)
            {
                workItemUrl = "Reassign.jsp?taskId="+taskId;
            }
            else
            {
                workItemUrl = "Reassign.jsp?taskId="+taskId +"&Forms="+formName;
            }
        }
        else if (cmdValue.equalsIgnoreCase("add")) 
        {
            workItemUrl = "AddAttachment.jsp?Forms=" + formName + "&taskId="+taskId;
        }
        else if (cmdValue.equalsIgnoreCase("delete selected")) 
        {
            String[] delAttach = request.getParameterValues("attachCheck");
            if (delAttach != null && delAttach.length > 0) 
            {
                ProcessInstance procInstance = task.getProcessInstance();
                procInstance.startEdit();
                for(int i=0; i<delAttach.length; i++)
                {
                    procInstance.removeAttachment(delAttach[i]);
                    out.write("<h1>");
                    out.write(delAttach[i]);
                    out.write("</h1>");
                }
                procInstance.commitEdit();
            }
        }
        else if (cmdValue.toLowerCase().indexOf("view attachment") > -1) 
        {
            String chkAttach = cmdValue.substring(cmdValue.indexOf(":")+1, cmdValue.lastIndexOf("."));
            if (chkAttach != null && chkAttach.length() > 0) 
            {
                workItemUrl = docUrlBase + URLEncoder.encode(chkAttach,"UTF-8") + "&AttachOption=ReadOnly"+formsUrlParam;
            }
        }
        else if (cmdValue.toLowerCase().indexOf("edit attachment") > -1) 
        {
            String chkAttach = cmdValue.substring(cmdValue.indexOf(":")+1, cmdValue.lastIndexOf("."));
            if (chkAttach != null && chkAttach.length() > 0) 
            {
                workItemUrl = docUrlBase + URLEncoder.encode(chkAttach,"UTF-8") + "&AttachOption=Edit" + formsUrlParam;
            }
        }
        else if (cmdValue.toLowerCase().indexOf("save attachment") > -1) 
        {
            String chkAttach = cmdValue.substring(cmdValue.indexOf(":")+1, cmdValue.lastIndexOf("."));
            if (chkAttach != null && chkAttach.length() > 0) 
            {
                workItemUrl = docUrlBase + URLEncoder.encode(chkAttach,"UTF-8") + "&AttachOption=CheckIn" + formsUrlParam;
            }
        }
        else 
        {
            throw new Exception("workItemAction.jsp does not understand the command: "+cmdValue);
        }
       }

       response.sendRedirect(response.encodeRedirectURL(workItemUrl));

%>
<%!
public boolean isBoolean(String text)
{
    boolean isMatch = false;
    if (text != null && text.trim().length()>0)
    {
        if (text.trim().equalsIgnoreCase("true") ||
                text.trim().equalsIgnoreCase("false"))
        {
            isMatch = true;
        }
    }
    return isMatch;
}

public boolean isInteger(String text)
{
    boolean isMatch = false;
    if (text != null && text.trim().length()>0)
    {
        try
        {
            Integer i = Integer.valueOf(text);
            isMatch = true;
        }
        catch(NumberFormatException e)
        {
            isMatch = false; //unnecessary
        }
    }
    return isMatch;
}

public boolean isFloat(String text)
{
    boolean isMatch = false;
    if (text != null && text.trim().length()>0)
    {
        try
        {
            Float f = Float.valueOf(text);
            isMatch = true;
        }
        catch(NumberFormatException e)
        {
            isMatch = false; //unnecessary
        }
    }
    return isMatch;
}

public boolean isLong(String text)
{
    boolean isMatch = false;
    if (text != null && text.trim().length()>0)
    {
        try
        {
            Long l = Long.valueOf(text);
            isMatch = true;
        }
        catch(NumberFormatException e)
        {
            isMatch = false; //unnecessary
        }
    }
    return isMatch;
}

public boolean isDate(String text)
{
    boolean isMatch = false;
    if (text != null && text.trim().length()>0)
    {
        try
        {
            DateFormat df = DateFormat.getDateTimeInstance(
                    DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.getDefault());
            df.parse(text);
            isMatch = true;
        }
        catch (ParseException e)
        {
            try 
            {
                long l = Long.parseLong(text);
                new Date(l);
                isMatch=true;
            }
            catch (NumberFormatException e1)
            {
                isMatch = false; //unnecessary
            }
        }
    }
    return isMatch;
}

public boolean isBigDecimal(String text)
{
    boolean isMatch = false;
    if (text != null && text.trim().length()>0)
    {
        try
        {
            BigDecimal l = new BigDecimal(text);
            isMatch = true;
        }
        catch(NumberFormatException e)
        {
            isMatch = false; //unnecessary
        }
    }
    return isMatch;
}

/**
 *   Utility method to check whether a given attribute value matches the
 *   tye type of of the attribute name. This method is mainly used in validating
 *   a form when a user modifies the values of the user defined attributes of
 *   a process.
 */

public boolean typeMatches(String attributeName,String attributeValue,DataItemRef[] items) 
    throws Exception
{
    if (attributeName == null ||
            attributeValue == null ||
            items == null)
    {
        throw new Exception("Improper parameters sent to 'typeMatches' routine.");
    }
    
    int last = items.length;
    for (int i = 0; i < last; i++)
    {
        if (items[i].getName().equals(attributeName))
        {
            DataItemRef item = items[i];
            if (item.getType().equals(DataItemRef.TYPE_STRING)) 
            {
                return true;
            }
            if (item.getType().equals(DataItemRef.TYPE_INTEGER)) 
            {
                if (!isInteger(attributeValue))
                {
                    throw new Exception("Value is not an Integer: "+attributeValue);
                }
                return true;
            }
            if (item.getType().equals(DataItemRef.TYPE_BOOLEAN)) 
            {
                if (!isBoolean(attributeValue))
                {
                    throw new Exception("Value is not a Boolean: "+attributeValue);
                }
                return true;
            }
            if (item.getType().equals(DataItemRef.TYPE_FLOAT)) 
            {
                if (!isFloat(attributeValue))
                {
                    throw new Exception("Value is not a Float: "+attributeValue);
                }
                return true;
            }
            if (item.getType().equals(DataItemRef.TYPE_LONG)) 
            {
                if (!isLong(attributeValue))
                {
                    throw new Exception("Value is not a Long: "+attributeValue);
                }
                return true;
            }
            if (item.getType().equals(DataItemRef.TYPE_DATE)) 
            {
                if (!isDate(attributeValue))
                {
                    throw new Exception("Value is not a Date: "+attributeValue);
                }
                return true;
            }
            if (item.getType().equals(DataItemRef.TYPE_BIGDECIMAL)) 
            {
                if (!isBigDecimal(attributeValue))
                {
                    throw new Exception("Value is not a Big Decimal: "+attributeValue);
                }
                return true;
            }
            throw new Exception("Data type of attribute is not understood by WorkItemAction.jsp");
        }
    }
    throw new Exception("Data type of attribute was not found in the set of data item references.");
}

public boolean valueMatches(String attributeName,String attributeValue,DataItemRef[] items)
    throws Exception
{
    boolean bMatch = false;
    if (attributeName == null ||
            attributeValue == null ||
            items == null)
    {
        return false;
    }
    
    for (int i = 0; i < items.length; i++)
    {
        if (items[i].getName().equals(attributeName))
        {
            DataItemRef item = items[i];
            if (attributeValue.equals(item.getValue()))
            {
                bMatch = true;
                break;
            }
        }
    }
    return bMatch;
}


/**
 *   A utility method that is used only in JSP by a form when trying to
 *   modifies the values of UDA of a process. Some fields inside the form
 *   may be empty (the user did not enter a value for them for example),
 *   and this method simply chooses a default value for such cases.
 */

public String getRightValue(String name,String value,DataItemRef[] items)
{
    String retValue = value;
    
    if (name == null || name.trim().equals(""))
    {
        return null;
    }
    if (value == null || value.trim().equals(""))
    {
        for (int i = 0; i < items.length; i++)
        {
            if (items[i].getName().equals(name))
            {
                DataItemRef item = items[i];
                if (item.getType().equals(DataItemRef.TYPE_STRING)) 
                {
                    retValue = "";
                }
                else if ((item.getType().equals(DataItemRef.TYPE_INTEGER))  ||
                        (item.getType().equals(DataItemRef.TYPE_LONG)))
                {
                    retValue = "0";
                }
                else if (item.getType().equals(DataItemRef.TYPE_BOOLEAN)) 
                {
                    retValue = "false";
                }
                else if (item.getType().equals(DataItemRef.TYPE_FLOAT)) 
                {
                    retValue = ".0.";
                }
                else if (item.getType().equals(DataItemRef.TYPE_DATE))
                {
                    Date d = new Date();
                    DateFormat df = DateFormat.getDateTimeInstance(
                            DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.getDefault());
                    retValue = df.format(d);
                }
                else if (item.getType().equals(DataItemRef.TYPE_BIGDECIMAL)) 
                {
                    retValue = "0.00";
                }
                break;
            }
        }
    }
    return retValue;
}

public long parseTimeString(String workTime)
{
    int idx = workTime.indexOf(":");
    int hrs = 0;
    int min = 0;
    int sec = 0;
    if (idx == -1) 
    {
        hrs = Integer.parseInt(workTime)*60*60*1000;
    }
    else 
    {
        hrs = Integer.parseInt(workTime.substring(0,idx))*60*60*1000;
        workTime = workTime.substring(idx+1);
        idx = workTime.indexOf(":");
        if (idx == -1) 
        {
            min = Integer.parseInt(workTime)*60*1000;
        }
        else 
        {
            min = Integer.parseInt(workTime.substring(0,idx))*60*1000;
            sec = Integer.parseInt(workTime.substring(idx+1))*1000;
        }
    }
    return sec+min+hrs;
}


%>
