//Name 	 Check multiple signoff
//Description 	Checks to see whether all the people who need to sign off the task have done so
//Type 	Trigger / Add Message / BEFORE Trigger

//Workflow has states:

//Pending
//In progress
//Awaiting approval
//Signed off

//Message that moves task from "In progress" to "Awaiting approval" assigns Submitter as handler.
//Message type "Acceptance" leaves task in state "Awaiting approval"
//Message type "Final acceptance" moves task from "Awaiting approval" to "Signed off"
//Message type "Failed acceptance" moves task back to state "Pending"

//Script prevents task from being moved to state "Signed off" unless Acceptance messages have been
//created by Submitter and all Additional approvers.

//Also if last person from whom acceptance is required submits and Acceptance that "Acceptance" message
//is changed to be a "Final acceptance" message


StringBuffer buf= new StringBuffer();
TreeSet requiredApprovers= new TreeSet();
TreeSet approvedBy= new TreeSet();

//Get the users in the "Additional approvers" field
if (message.getTask().getUDFValues().get(CSVImport.findUDFIdByName("Additional approvers"))!=null){
    requiredApprovers = message.getTask().getUDFValues().get(CSVImport.findUDFIdByName("Additional approvers")).getValue(message.getTask());
}

//Get the Task's submitter
    requiredApprovers.add(message.getTask().getSubmitterId());


//Add the ID of the Submitter of this Message
approvedBy.add(message.getSubmitterId());

//Iterate through the list of messages to get IDs of previous submitters of Accepted messages
Object m = message.getTask().getMessages();
Collections.reverse(m);
if (m!=null){
    for (int j=m.size(); j>0; j--){
        if (m.get(j-1).getMstatus().getName().equals("Failed acceptance")){
             break;
        }
        if (m.get(j-1).getMstatus().getName().equals("Acceptance")){
            approvedBy.add(m.get(j-1).getSubmitterId());
        }
    }
}

TreeSet approvalsRqd = new TreeSet(requiredApprovers);
approvalsRqd.removeAll(approvedBy);

//List all still needed to approve
for (Iterator i2 = ((TreeSet)approvalsRqd).iterator(); i2.hasNext();){
    String login = new SecuredUserBean(i2.next().toString(), sc).getLogin();
    if (buf.indexOf("; "+login)<0){
        buf.append("; ");
        buf.append(login);
    }
}

//Display appropriate messages or automatically change message type and handler
//comment out/uncomment as desired
if (message.getMstatus().getName().equals("Final acceptance")&&approvalsRqd.size()!=0){
    //throw new UserMessageException("Approval is still required from "+buf.substring(2)+". Please therefore generate an Acceptance message and assign the task to one of the users from whom acceptance is required");
message.setMstatus("Acceptance");
message.setHandlerUserId(approvalsRqd.first());
} else if (message.getMstatus().getName().equals("Acceptance") && approvalsRqd.size()==0) {
    //throw new UserMessageException("No further approvals are required. Please therefore generate a Final acceptance message.");
message.setMstatus("Final acceptance");

}

return message;