private void doControlTask() throws IOException, ClassNotFoundException {
    BlockingTaskSummaryResponseHandler handler = new BlockingTaskSummaryResponseHandler();
    client.getTasksAssignedAsPotentialOwner("control", "en-UK", handler);
    List<TaskSummary> sums = handler.getResults();
    assertNotNull(sums);
    assertEquals(1, sums.size());

    BlockingTaskOperationResponseHandler startTaskOperationHandler =
        new BlockingTaskOperationResponseHandler();
    client.start(sums.get(0).getId(), "control", startTaskOperationHandler);

    BlockingGetTaskResponseHandler getTaskHandler = new BlockingGetTaskResponseHandler();
    client.getTask(sums.get(0).getId(), getTaskHandler);
    Task controlTask = getTaskHandler.getTask();

    BlockingGetContentResponseHandler getContentHandler = new BlockingGetContentResponseHandler();
    client.getContent(controlTask.getTaskData().getDocumentContentId(), getContentHandler);
    Content content = getContentHandler.getContent();

    assertNotNull(content);

    ByteArrayInputStream bais = new ByteArrayInputStream(content.getContent());
    ObjectInputStream ois = new ObjectInputStream(bais);
    Map<String, Object> deserializedContent = (Map<String, Object>) ois.readObject();
    Emergency retrivedEmergency = (Emergency) deserializedContent.get("emergency");
    assertNotNull(retrivedEmergency);
    ActivePatients retrivedActivePatients =
        (ActivePatients) deserializedContent.get("activePatients");
    assertNotNull(retrivedActivePatients);
    assertEquals(1, retrivedActivePatients.size());
    SuggestedProcedures retrivedSuggestedProcedures =
        (SuggestedProcedures) deserializedContent.get("suggestedProcedures");
    assertNotNull(retrivedSuggestedProcedures);
    assertEquals(
        "[DefaultHeartAttackProcedure: ]",
        retrivedSuggestedProcedures.getSuggestedProceduresString());

    Map<String, Object> info = new HashMap<String, Object>();
    SelectedProcedures selectedProcedures = new SelectedProcedures(retrivedEmergency.getId());

    selectedProcedures.addSelectedProcedureName("DefaultHeartAttackProcedure");
    info.put("selectedProcedures", selectedProcedures);

    ContentData result = new ContentData();
    result.setAccessType(AccessType.Inline);
    result.setType("java.util.Map");
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ObjectOutputStream out = new ObjectOutputStream(bos);
    out.writeObject(info);
    out.close();
    result.setContent(bos.toByteArray());

    BlockingTaskOperationResponseHandler completeTaskOperationHandler =
        new BlockingTaskOperationResponseHandler();
    client.complete(sums.get(0).getId(), "control", result, completeTaskOperationHandler);
  }
  private void doOperatorTask() throws ClassNotFoundException, IOException {
    BlockingTaskSummaryResponseHandler handler = new BlockingTaskSummaryResponseHandler();
    client.getTasksAssignedAsPotentialOwner("operator", "en-UK", handler);
    List<TaskSummary> sums = handler.getResults();
    assertNotNull(sums);
    assertEquals(1, sums.size());

    BlockingTaskOperationResponseHandler startTaskOperationHandler =
        new BlockingTaskOperationResponseHandler();
    client.start(sums.get(0).getId(), "operator", startTaskOperationHandler);

    BlockingGetTaskResponseHandler getTaskHandler = new BlockingGetTaskResponseHandler();
    client.getTask(sums.get(0).getId(), getTaskHandler);
    Task operatorTask = getTaskHandler.getTask();

    BlockingGetContentResponseHandler getContentHandler = new BlockingGetContentResponseHandler();
    client.getContent(operatorTask.getTaskData().getDocumentContentId(), getContentHandler);
    Content content = getContentHandler.getContent();

    assertNotNull(content);

    ByteArrayInputStream bais = new ByteArrayInputStream(content.getContent());
    ObjectInputStream ois = new ObjectInputStream(bais);
    Map<String, Object> deserializedContent = (Map<String, Object>) ois.readObject();
    Call restoredCall = (Call) deserializedContent.get("call");
    persistenceService.storeCall(restoredCall);

    Emergency emergency = new Emergency();

    emergency.setCall(restoredCall);

    emergency.setLocation(new Location(1, 2));
    emergency.setType(Emergency.EmergencyType.HEART_ATTACK);
    emergency.setNroOfPeople(1);
    persistenceService.storeEmergency(emergency);

    trackingService.attachEmergency(restoredCall.getId(), emergency.getId());

    Map<String, Object> info = new HashMap<String, Object>();
    info.put("emergency", emergency);

    ContentData result = new ContentData();
    result.setAccessType(AccessType.Inline);
    result.setType("java.util.Map");
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ObjectOutputStream out = new ObjectOutputStream(bos);
    out.writeObject(info);
    out.close();
    result.setContent(bos.toByteArray());

    BlockingTaskOperationResponseHandler completeTaskOperationHandler =
        new BlockingTaskOperationResponseHandler();
    client.complete(sums.get(0).getId(), "operator", result, completeTaskOperationHandler);
  }
 public void handleCompletedTask(long taskId) {
   Task task = client.getTask(taskId);
   long workItemId = task.getTaskData().getWorkItemId();
   if (task.getTaskData().getStatus() == Status.Completed) {
     String userId = task.getTaskData().getActualOwner().getId();
     Map<String, Object> results = new HashMap<String, Object>();
     results.put("ActorId", userId);
     long contentId = task.getTaskData().getOutputContentId();
     if (contentId != -1) {
       Content content = client.getContent(contentId);
       ByteArrayInputStream bis = new ByteArrayInputStream(content.getContent());
       ObjectInputStream in;
       try {
         in = new ObjectInputStream(bis);
         Object result = in.readObject();
         in.close();
         results.put("Result", result);
         if (result instanceof Map) {
           Map<?, ?> map = (Map) result;
           for (Map.Entry<?, ?> entry : map.entrySet()) {
             if (entry.getKey() instanceof String) {
               results.put((String) entry.getKey(), entry.getValue());
             }
           }
         }
         if (session != null) {
           session
               .getWorkItemManager()
               .completeWorkItem(task.getTaskData().getWorkItemId(), results);
         } else {
           manager.completeWorkItem(task.getTaskData().getWorkItemId(), results);
         }
       } catch (IOException e) {
         e.printStackTrace();
       } catch (ClassNotFoundException e) {
         e.printStackTrace();
       }
     } else {
       if (session != null) {
         session.getWorkItemManager().completeWorkItem(workItemId, results);
       } else {
         manager.completeWorkItem(workItemId, results);
       }
     }
   } else {
     if (session != null) {
       session.getWorkItemManager().abortWorkItem(workItemId);
     } else {
       manager.abortWorkItem(workItemId);
     }
   }
 }
  public long addTask(Task task, ContentData contentData) {
    doCallbackOperationForPeopleAssignments(task.getPeopleAssignments());
    doCallbackOperationForTaskData(task.getTaskData());
    doCallbackOperationForTaskDeadlines(task.getDeadlines());
    em.persist(task);
    if (contentData != null) {
      Content content = new Content(contentData.getContent());
      em.persist(content);
      task.getTaskData().setDocument(content.getId(), contentData);
    }

    return task.getId();
  }
 public long addTask(Task task, Map<String, Object> params) {
   doCallbackOperationForPeopleAssignments(task.getPeopleAssignments());
   doCallbackOperationForTaskData(task.getTaskData());
   doCallbackOperationForTaskDeadlines(task.getDeadlines());
   if (params != null) {
     ContentData contentData = ContentMarshallerHelper.marshal(params, null);
     Content content = new Content(contentData.getContent());
     em.persist(content);
     task.getTaskData().setDocument(content.getId(), contentData);
   }
   em.persist(task);
   return task.getId();
 }
  public long newTask(String name, Map<String, Object> params) {
    TaskDef taskDef = taskDefService.getTaskDefById(name);

    Task task = TaskFactory.newTask(taskDef);
    em.persist(task);
    if (params != null) {
      ContentData contentData = ContentMarshallerHelper.marshal(params, null);
      Content content = new Content(contentData.getContent());
      em.persist(content);
      task.getTaskData().setDocument(content.getId(), contentData);
    }

    return task.getId();
  }
  public long newTask(TaskDef taskDef, Map<String, Object> params, boolean deploy) {
    // TODO: need to deal with the params for the content
    if (deploy) {
      taskDefService.deployTaskDef(taskDef);
    }
    Task task = TaskFactory.newTask(taskDef);
    em.persist(task);
    if (params != null) {
      ContentData contentData = ContentMarshallerHelper.marshal(params, null);
      Content content = new Content(contentData.getContent());
      em.persist(content);
      task.getTaskData().setDocument(content.getId(), contentData);
    }

    return task.getId();
  }
 public void execute(Content content) {
   Object result =
       ContentMarshallerHelper.unmarshall(
           content.getContent(), session.getEnvironment(), classLoader);
   results.put("Result", result);
   if (result instanceof Map) {
     @SuppressWarnings("rawtypes")
     Map<?, ?> map = (Map) result;
     for (Map.Entry<?, ?> entry : map.entrySet()) {
       if (entry.getKey() instanceof String) {
         results.put((String) entry.getKey(), entry.getValue());
       }
     }
   }
   session.getWorkItemManager().completeWorkItem(task.getTaskData().getWorkItemId(), results);
 }
  public void executeEmailNotification(
      EmailNotification notification, Task task, EntityManager em) {
    Map<String, EmailNotificationHeader> headers = notification.getEmailHeaders();

    // group users into languages
    Map<String, List<User>> users = new HashMap<String, List<User>>();
    for (OrganizationalEntity entity : notification.getBusinessAdministrators()) {
      if (entity instanceof Group) {
        buildMapByLanguage(users, (Group) entity);
      } else {
        buildMapByLanguage(users, (User) entity);
      }
    }

    for (OrganizationalEntity entity : notification.getRecipients()) {
      if (entity instanceof Group) {
        buildMapByLanguage(users, (Group) entity);
      } else {
        buildMapByLanguage(users, (User) entity);
      }
    }

    TaskData taskData = task.getTaskData();
    Map<String, Object> doc = null;
    if (taskData != null) {
      Content content = em.find(Content.class, taskData.getDocumentContentId());
      if (content != null) {
        ExpressionCompiler compiler = new ExpressionCompiler(new String(content.getContent()));
        doc = (Map<String, Object>) MVEL.executeExpression(compiler.compile());
      } else {
        doc = Collections.emptyMap();
      }
    }

    for (Iterator<Entry<String, List<User>>> it = users.entrySet().iterator(); it.hasNext(); ) {
      Entry<String, List<User>> entry = it.next();
      EmailNotificationHeader header = headers.get(entry.getKey());

      Map<String, Object> email = new HashMap<String, Object>();
      StringBuilder to = new StringBuilder();
      boolean first = true;
      for (User user : entry.getValue()) {
        if (!first) {
          to.append(';');
        }
        String emailAddress = userInfo.getEmailForEntity(user);
        to.append(emailAddress);
        first = false;
      }
      email.put("To", to.toString());

      if (header.getFrom() != null && header.getFrom().trim().length() > 0) {
        email.put("From", header.getFrom());
      } else {
        email.put("From", from);
      }

      if (header.getReplyTo() != null && header.getReplyTo().trim().length() > 0) {
        email.put("Reply-To", header.getReplyTo());
      } else {
        email.put("Reply-To", replyTo);
      }

      Map<String, Object> vars = new HashMap<String, Object>();
      vars.put("doc", doc);
      String subject = (String) TemplateRuntime.eval(header.getSubject(), vars);
      String body = (String) TemplateRuntime.eval(header.getBody(), vars);

      email.put("Subject", subject);
      email.put("Body", body);

      WorkItemImpl workItem = new WorkItemImpl();
      workItem.setParameters(email);

      handler.executeWorkItem(workItem, manager);
    }
  }
  @Override
  public Task convert(org.jbpm.task.query.TaskSummary source) {

    Task target = new Task();

    target.setDescription(source.getDescription());

    if (source.getActualOwner() != null) {
      target.setAssignee(source.getActualOwner().getId());
    }

    if (source.getCreatedOn() != null) {
      target.setCreateTime(convert(source.getCreatedOn(), XMLGregorianCalendar.class));
    }

    if (source.getExpirationTime() != null) {
      target.setDueDate(convert(source.getExpirationTime(), XMLGregorianCalendar.class));
    }
    target.setId(String.valueOf(source.getId()));

    if (source.getName() != null) {
      String[] parts = source.getName().split("/");
      target.setActivityName(parts[0]);
      target.setName(parts[1]);
    }

    target.setState(source.getStatus().name());

    target.setPriority(new Integer(source.getPriority()));
    target.setProcessInstanceId(
        source.getProcessId() + "." + Long.toString(source.getProcessInstanceId()));

    BlockingGetTaskResponseHandler getTaskResponseHandler = new BlockingGetTaskResponseHandler();
    taskClient.getTask(source.getId(), getTaskResponseHandler);
    org.jbpm.task.Task task = getTaskResponseHandler.getTask();

    BlockingGetContentResponseHandler getContentResponseHandler =
        new BlockingGetContentResponseHandler();
    taskClient.getContent(task.getTaskData().getDocumentContentId(), getContentResponseHandler);
    Content content = getContentResponseHandler.getContent();

    Map<String, Object> map =
        (Map<String, Object>) ContentMarshallerHelper.unmarshall(content.getContent(), null);

    for (String key : map.keySet()) {
      log.debug("Key: " + key);
    }

    // add task outcomes using the "Options" variable from the task
    String optionsString = (String) map.get("Options");
    if (optionsString != null) {
      String[] options = ((String) map.get("Options")).split(",");
      target.getOutcomes().addAll(Arrays.asList(options));
    }

    // get ad-hoc variables map

    Map<String, Object> contentMap =
        (Map<String, Object>) map.get(Bpmn20UserTaskNodeBuilder.TASK_INPUT_VARIABLES_NAME);
    if (contentMap != null) {
      for (Entry<String, Object> entry : contentMap.entrySet()) {
        log.debug(entry.getKey() + "=" + entry.getValue());
        addVariable(target, entry.getKey(), entry.getValue());
      }
    } else {
      log.debug("No Content found for task");
    }

    // add variables
    /*Set<String> names = taskService.getVariableNames(source.getId());
    Map<String, Object> variables = taskService.getVariables(source.getId(), names);
    // remove process name var
    variables.remove("_name");
    for (String key : variables.keySet()) {
        Variable var = new Variable();
        var.setName(key);
        // Support strings only.  Other types will cause ClassCastException
        try {
            var.setValue((String) variables.get(key));
        } catch (ClassCastException e) {
            var.setValue("Variable type " + variables.get(key).getClass().getName() + " is not supported");
        }
        addVariable(target, var);
    }

    // Do this only if the task is not an ad-hoc task (as indicated by null executionId)
    if (source.getExecutionId() != null) {

        // name is the 'form' attribute in JPDL
        // this is used in the COW schema to store the display name, as distinct from the system-generated name
        target.setName(source.getFormResourceName());

        // activityName is the 'name' from JPDL
        target.setActivityName(source.getActivityName());

        Execution ex = executionService.findExecutionById(source.getExecutionId());
        target.setProcessInstanceId(ex.getProcessInstance().getId());

        // outcomes
        Set<String> outcomes = taskService.getOutcomes(source.getId());
        for (String outcome : outcomes) {
            target.getOutcomes().add(outcome);
        }

        // Workaround to the fact that we cannot use autowiring here
        if (this.cowTaskService == null) {
            this.cowTaskService = (org.wiredwidgets.cow.server.service.TaskService) this.factory.getBean("taskService");
        }

        // add process level task varibles (
        String executionId = getTopLevelExecutionId(source.getExecutionId());
        org.wiredwidgets.cow.server.api.model.v2.Activity activity = cowTaskService.getWorkflowActivity(executionId, source.getActivityName());
        if (activity != null && activity instanceof org.wiredwidgets.cow.server.api.model.v2.Task) {
            org.wiredwidgets.cow.server.api.model.v2.Task cowTask = (org.wiredwidgets.cow.server.api.model.v2.Task) activity;
            if (cowTask.getVariables() != null) {
                for (org.wiredwidgets.cow.server.api.model.v2.Variable var : cowTask.getVariables().getVariables()) {
                    Variable newVar = new Variable();
                    newVar.setName(var.getName());
                    newVar.setValue(var.getValue());
                    addVariable(target, newVar);
                }
            }
        }
    } else {
        // for ad-hoc tasks
        target.setName(source.getName());
    }*/

    return target;
  }
  @Override
  public void completeTask(
      Long id, String assignee, String outcome, Map<String, Object> variables) {
    // should be handled upstream in controller
    assert (assignee != null);

    log.debug(assignee + " starting task with ID: " + id);

    BlockingGetTaskResponseHandler getTaskResponseHandler = new BlockingGetTaskResponseHandler();
    taskClient.getTask(id, getTaskResponseHandler);
    org.jbpm.task.Task task = getTaskResponseHandler.getTask();

    // convert to COW task so we can verify the decision
    Task cowTask = converter.convert(task, Task.class);

    if (cowTask.getOutcomes() != null && cowTask.getOutcomes().size() > 0) {
      // This is a decision task!
      if (outcome == null) {
        throw new RuntimeException("ERROR: no decision provided for a Decision task");
      }
      if (!cowTask.getOutcomes().contains(outcome)) {
        throw new RuntimeException("ERROR: decision value " + outcome + " is not a valid choice.");
      }
    }

    BlockingGetContentResponseHandler getContentResponseHandler =
        new BlockingGetContentResponseHandler();
    taskClient.getContent(task.getTaskData().getDocumentContentId(), getContentResponseHandler);
    Content inputContent = getContentResponseHandler.getContent();

    Map<String, Object> inputMap =
        (Map<String, Object>) ContentMarshallerHelper.unmarshall(inputContent.getContent(), null);

    for (Map.Entry<String, Object> entry : inputMap.entrySet()) {
      log.debug(entry.getKey() + " = " + entry.getValue());
    }

    Map<String, Object> outputMap = new HashMap<String, Object>();

    // put Outcome into the outputMap
    // The InputMap contains a variable that tells us what key to use
    if (inputMap.get(DECISION_VAR_NAME) != null) {
      log.debug("Decision outcome: " + outcome);
      outputMap.put((String) inputMap.get(DECISION_VAR_NAME), outcome);
    }

    Map<String, Object> outputVarsMap = new HashMap<String, Object>();

    // NOTE: obtaining the map from the Task results in a copy of the map as of the
    // time when the task became available.  It's possible that in the meantime (e.g. due to
    // a parallel task) the map has been altered.
    // Map<String, Object> inputVarsMap = (Map<String, Object>)
    // inputMap.get(TASK_INPUT_VARIABLES_NAME);

    // So, instead, we get the current values directly from the process instance, rather than the
    // values copied into the task

    Long processInstanceId = task.getTaskData().getProcessInstanceId();
    Map<String, Object> inputVarsMap = null;

    try {
      WorkflowProcessInstance pi =
          (WorkflowProcessInstance) kSession.getProcessInstance(processInstanceId);
      inputVarsMap = (Map<String, Object>) pi.getVariable(VARIABLES_PROPERTY);
    } catch (Exception e) {
      // not an active process?  look in the dB.
      log.error(e);
      List<VariableInstanceLog> vars =
          JPAProcessInstanceDbLog.findVariableInstances(processInstanceId, VARIABLES_PROPERTY);
      log.info("variable count: " + vars.size());
      if (vars.size() > 0) {
        // why more than one???
        inputVarsMap = (Map<String, Object>) vars.get(0);
      }
    }

    if (inputVarsMap != null) {
      // initialize the output map with the input values
      log.debug("Copying input map: " + inputVarsMap);
      outputVarsMap.putAll(inputVarsMap);
    }

    if (variables != null && variables.size() > 0) {
      log.debug("Adding variables: " + variables);
      // update with any new or modified values
      outputVarsMap.putAll(variables);
    }

    if (outputVarsMap.size() > 0) {
      log.debug("Adding map to output");
      outputMap.put(TASK_OUTPUT_VARIABLES_NAME, outputVarsMap);
    }

    // start the task
    if (task.getTaskData().getStatus().equals(org.jbpm.task.Status.Reserved)) {
      BlockingTaskOperationResponseHandler operationResponseHandler =
          new BlockingTaskOperationResponseHandler();
      // change status to InProgress
      taskClient.start(id, assignee, operationResponseHandler);
    }

    // kSession.getWorkItemManager().completeWorkItem(task.getTaskData().getWorkItemId(), new
    // HashMap<String,Object>());
    BlockingTaskOperationResponseHandler taskResponseHandler =
        new BlockingTaskOperationResponseHandler();
    // TODO: since we're passing the variables map further down, maybe we don't need to pass it
    // here?  Test this.
    ContentData contentData = ContentMarshallerHelper.marshal(outputMap, null);
    taskClient.complete(id, assignee, contentData, taskResponseHandler);
    taskResponseHandler.waitTillDone(1000);

    // note that we have to pass the variables again.
    kSession.getWorkItemManager().completeWorkItem(task.getTaskData().getWorkItemId(), outputMap);

    // update completed date
    // For some reason this does not get updated by default, and
    // there appears to be no JBPM API way to do this!
    org.jbpm.task.Task t = taskRepo.findOne(task.getId());
    t.getTaskData().setCompletedOn(new Date());
    // update the user
    t.getTaskData().setActualOwner(new User(assignee));

    // note that JPA handles updating of this object automatically

  }
  public void testAddRemoveAttachment() throws Exception {
    Map vars = new HashMap();
    vars.put("users", users);
    vars.put("groups", groups);
    vars.put("now", new Date());

    String str =
        "(with (new Task()) { priority = 55, taskData = (with( new TaskData()) { createdOn = now, activationTime = now}), ";
    str += "deadlines = new Deadlines(),";
    str += "delegation = new Delegation(),";
    str += "peopleAssignments = new PeopleAssignments(),";
    str += "names = [ new I18NText( 'en-UK', 'This is my task name')] })";

    BlockingAddTaskResponseHandler addTaskResponseHandler = new BlockingAddTaskResponseHandler();
    Task task = (Task) eval(new StringReader(str), vars);
    client.addTask(task, null, addTaskResponseHandler);

    long taskId = addTaskResponseHandler.getTaskId();

    Attachment attachment = new Attachment();
    Date attachedAt = new Date(System.currentTimeMillis());
    attachment.setAttachedAt(attachedAt);
    attachment.setAttachedBy(users.get("luke"));
    attachment.setName("file1.txt");
    attachment.setAccessType(AccessType.Inline);
    attachment.setContentType("txt");

    byte[] bytes = "Ths is my attachment text1".getBytes();
    Content content = new Content();
    content.setContent(bytes);

    BlockingAddAttachmentResponseHandler addAttachmentResponseHandler =
        new BlockingAddAttachmentResponseHandler();
    client.addAttachment(taskId, attachment, content, addAttachmentResponseHandler);
    assertTrue(addAttachmentResponseHandler.getAttachmentId() != attachment.getId());
    assertTrue(addAttachmentResponseHandler.getContentId() != attachment.getAttachmentContentId());

    BlockingGetTaskResponseHandler getTaskResponseHandler = new BlockingGetTaskResponseHandler();
    client.getTask(taskId, getTaskResponseHandler);
    Task task1 = getTaskResponseHandler.getTask();
    assertNotSame(task, task1);
    assertFalse(task.equals(task1));

    List<Attachment> attachments1 = task1.getTaskData().getAttachments();
    assertEquals(1, attachments1.size());
    Attachment returnedAttachment = attachments1.get(0);
    assertEquals(attachedAt, returnedAttachment.getAttachedAt());
    assertEquals(users.get("luke"), returnedAttachment.getAttachedBy());
    assertEquals(AccessType.Inline, returnedAttachment.getAccessType());
    assertEquals("txt", returnedAttachment.getContentType());
    assertEquals("file1.txt", returnedAttachment.getName());
    assertEquals(bytes.length, returnedAttachment.getSize());

    assertEquals(
        (long) addAttachmentResponseHandler.getAttachmentId(), (long) returnedAttachment.getId());
    assertEquals(
        (long) addAttachmentResponseHandler.getContentId(),
        (long) returnedAttachment.getAttachmentContentId());

    // Make the same as the returned tasks, so we can test equals
    task.getTaskData().setAttachments(attachments1);
    task.getTaskData().setStatus(Status.Created);
    assertEquals(task, task1);

    BlockingGetContentResponseHandler getResponseHandler = new BlockingGetContentResponseHandler();
    client.getContent(returnedAttachment.getAttachmentContentId(), getResponseHandler);
    content = getResponseHandler.getContent();
    assertEquals("Ths is my attachment text1", new String(content.getContent()));

    // test we can have multiple attachments

    attachment = new Attachment();
    attachedAt = new Date(System.currentTimeMillis());
    attachment.setAttachedAt(attachedAt);
    attachment.setAttachedBy(users.get("tony"));
    attachment.setName("file2.txt");
    attachment.setAccessType(AccessType.Inline);
    attachment.setContentType("txt");

    bytes = "Ths is my attachment text2".getBytes();
    content = new Content();
    content.setContent(bytes);

    addAttachmentResponseHandler = new BlockingAddAttachmentResponseHandler();
    client.addAttachment(taskId, attachment, content, addAttachmentResponseHandler);

    getTaskResponseHandler = new BlockingGetTaskResponseHandler();
    client.getTask(taskId, getTaskResponseHandler);
    task1 = getTaskResponseHandler.getTask();
    assertNotSame(task, task1);
    assertFalse(task.equals(task1));

    List<Attachment> attachments2 = task1.getTaskData().getAttachments();
    assertEquals(2, attachments2.size());

    getResponseHandler = new BlockingGetContentResponseHandler();
    client.getContent(addAttachmentResponseHandler.getContentId(), getResponseHandler);
    content = getResponseHandler.getContent();
    assertEquals("Ths is my attachment text2", new String(content.getContent()));

    // make two collections the same and compare
    attachment.setSize(26);
    attachment.setAttachmentContentId(addAttachmentResponseHandler.getContentId());
    attachments1.add(attachment);
    assertTrue(CollectionUtils.equals(attachments2, attachments1));

    BlockingDeleteAttachmentResponseHandler deleteCommentResponseHandler =
        new BlockingDeleteAttachmentResponseHandler();
    client.deleteAttachment(
        taskId,
        addAttachmentResponseHandler.getAttachmentId(),
        addAttachmentResponseHandler.getContentId(),
        deleteCommentResponseHandler);
    deleteCommentResponseHandler.waitTillDone(3000);

    Thread.sleep(3000);

    getTaskResponseHandler = new BlockingGetTaskResponseHandler();
    client.getTask(taskId, getTaskResponseHandler);
    task1 = getTaskResponseHandler.getTask();
    attachments2 = task1.getTaskData().getAttachments();
    assertEquals(1, attachments2.size());

    assertEquals("file1.txt", attachments2.get(0).getName());
  }
  public void testDelayedEmailNotificationOnDeadline() throws Exception {
    Map vars = new HashMap();
    vars.put("users", users);
    vars.put("groups", groups);
    vars.put("now", new Date());

    DefaultEscalatedDeadlineHandler notificationHandler =
        new DefaultEscalatedDeadlineHandler(getConf());
    WorkItemManager manager = new DefaultWorkItemManager(null);
    notificationHandler.setManager(manager);

    MockUserInfo userInfo = new MockUserInfo();
    userInfo.getEmails().put(users.get("tony"), emailAddressTony);
    userInfo.getEmails().put(users.get("darth"), emailAddressDarth);

    userInfo.getLanguages().put(users.get("tony"), "en-UK");
    userInfo.getLanguages().put(users.get("darth"), "en-UK");
    notificationHandler.setUserInfo(userInfo);

    taskService.setEscalatedDeadlineHandler(notificationHandler);

    Reader reader =
        new InputStreamReader(
            getClass().getResourceAsStream(MvelFilePath.DeadlineWithNotification));
    Task task = (Task) eval(reader, vars);

    BlockingAddTaskResponseHandler addTaskResponseHandler = new BlockingAddTaskResponseHandler();
    client.addTask(task, null, addTaskResponseHandler);
    long taskId = addTaskResponseHandler.getTaskId();

    Content content = new Content();
    content.setContent("['subject' : 'My Subject', 'body' : 'My Body']".getBytes());
    BlockingSetContentResponseHandler setContentResponseHandler =
        new BlockingSetContentResponseHandler();
    client.setDocumentContent(taskId, content, setContentResponseHandler);
    long contentId = setContentResponseHandler.getContentId();
    BlockingGetContentResponseHandler getResponseHandler = new BlockingGetContentResponseHandler();
    client.getContent(contentId, getResponseHandler);
    content = getResponseHandler.getContent();
    assertEquals(
        "['subject' : 'My Subject', 'body' : 'My Body']", new String(content.getContent()));

    // emails should not be set yet
    assertEquals(0, getWiser().getMessages().size());
    Thread.sleep(100);

    // nor yet
    assertEquals(0, getWiser().getMessages().size());

    long time = 0;
    while (getWiser().getMessages().size() != 2 && time < 15000) {
      Thread.sleep(500);
      time += 500;
    }

    // 1 email with two recipients should now exist
    assertEquals(2, getWiser().getMessages().size());

    List<String> list = new ArrayList<String>(2);
    list.add(getWiser().getMessages().get(0).getEnvelopeReceiver());
    list.add(getWiser().getMessages().get(1).getEnvelopeReceiver());

    assertTrue(list.contains(emailAddressTony));
    assertTrue(list.contains(emailAddressDarth));

    MimeMessage msg = ((WiserMessage) getWiser().getMessages().get(0)).getMimeMessage();
    assertEquals("My Body", msg.getContent());
    assertEquals("My Subject", msg.getSubject());
    assertEquals("*****@*****.**", ((InternetAddress) msg.getFrom()[0]).getAddress());
    assertEquals("*****@*****.**", ((InternetAddress) msg.getReplyTo()[0]).getAddress());
    boolean tonyMatched = false;
    boolean darthMatched = false;
    for (int i = 0; i < msg.getRecipients(RecipientType.TO).length; ++i) {
      String emailAddress = ((InternetAddress) msg.getRecipients(RecipientType.TO)[i]).getAddress();
      if ("*****@*****.**".equals(emailAddress)) {
        tonyMatched = true;
      } else if ("*****@*****.**".equals(emailAddress)) {
        darthMatched = true;
      }
    }
    assertTrue("Could not find tony in recipients list.", tonyMatched);
    assertTrue("Could not find darth in recipients list.", darthMatched);
  }