private RouteNodeInstance determineStartNode(
     Collection<RouteNodeInstance> activeNodes, MovePoint movePoint)
     throws InvalidActionTakenException {
   RouteNodeInstance startNodeInstance = null;
   for (RouteNodeInstance nodeInstance : activeNodes) {
     if (nodeInstance.getName().equals(movePoint.getStartNodeName())) {
       if (startNodeInstance != null) {
         throw new InvalidActionTakenException(
             "More than one active node exists with the given name:  "
                 + movePoint.getStartNodeName());
       }
       startNodeInstance = nodeInstance;
     }
   }
   if (startNodeInstance == null) {
     throw new InvalidActionTakenException(
         "Could not locate an active node with the given name: " + movePoint.getStartNodeName());
   }
   return startNodeInstance;
 }
  public String getRouteLevelName() {
    // this is for backward compatibility of requests which have not been converted
    if (CompatUtils.isRouteLevelRequest(this)) {
      int routeLevelInt = getRouteLevel();
      if (routeLevelInt == KewApiConstants.EXCEPTION_ROUTE_LEVEL) {
        return "Exception";
      }

      List<RouteNode> routeLevelNodes =
          CompatUtils.getRouteLevelCompatibleNodeList(
              KEWServiceLocator.getRouteHeaderService()
                  .getRouteHeader(documentId)
                  .getDocumentType());
      if (!(routeLevelInt < routeLevelNodes.size())) {
        return "Not Found";
      }
      return ((RouteNode) routeLevelNodes.get(routeLevelInt)).getRouteNodeName();
    } else {
      return (nodeInstance == null ? "Exception" : nodeInstance.getName());
    }
  }
  @Test
  public void testParallelRoute() throws Exception {
    WorkflowDocument document =
        WorkflowDocumentFactory.createDocument(
            getPrincipalIdForName("ewestfal"), DOCUMENT_TYPE_NAME);
    document.saveDocumentData();
    assertTrue("Document should be initiated", document.isInitiated());
    assertEquals("Should be no action requests.", 0, document.getRootActionRequests().size());
    Collection<RouteNodeInstance> nodeInstances =
        KEWServiceLocator.getRouteNodeService().getActiveNodeInstances(document.getDocumentId());
    assertEquals("Wrong number of active nodes.", 1, nodeInstances.size());
    document.route("Routing for parallel");

    // should have generated a request to "bmcgough"
    document =
        WorkflowDocumentFactory.loadDocument(
            getPrincipalIdForName("bmcgough"), document.getDocumentId());
    assertTrue("Document should be enroute", document.isEnroute());
    List<ActionRequestValue> actionRequests =
        KEWServiceLocator.getActionRequestService().findPendingByDoc(document.getDocumentId());
    assertEquals("Incorrect pending action requests.", 1, actionRequests.size());
    ActionRequestValue bRequest = actionRequests.get(0);
    assertNotNull("Should have been routed through node instance.", bRequest.getNodeInstance());
    assertTrue(document.isApprovalRequested());

    document.approve("Approving test");

    // document should split at this point and generate an ack to temay and approves to rkirkend and
    // pmckown
    document =
        WorkflowDocumentFactory.loadDocument(
            getPrincipalIdForName("rkirkend"), document.getDocumentId());
    assertTrue("Document should be enroute", document.isEnroute());
    actionRequests =
        KEWServiceLocator.getActionRequestService().findPendingByDoc(document.getDocumentId());
    assertEquals("Incorrect pending action requests.", 3, actionRequests.size());
    boolean isToTemay = false;
    boolean isToPmckown = false;
    boolean isToRkirkend = false;
    for (Iterator iterator = actionRequests.iterator(); iterator.hasNext(); ) {
      ActionRequestValue actionRequest = (ActionRequestValue) iterator.next();
      if (actionRequest.getPrincipalId().equals(getPrincipalIdForName("temay"))) {
        isToTemay = true;
        assertEquals(
            "Request should be activated.",
            ActionRequestStatus.ACTIVATED.getCode(),
            actionRequest.getStatus());
        assertEquals(
            "Wrong action requested.",
            KewApiConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ,
            actionRequest.getActionRequested());
        assertNotNull(
            "Should have been routed through node instance.", actionRequest.getNodeInstance());
        assertEquals(
            "Invalid node.",
            ACKNOWLEDGE_1_NODE,
            actionRequest.getNodeInstance().getRouteNode().getRouteNodeName());
      }
      if (actionRequest.getPrincipalId().equals(getPrincipalIdForName("rkirkend"))) {
        isToRkirkend = true;
        assertEquals(
            "Request should be activated.",
            ActionRequestStatus.ACTIVATED.getCode(),
            actionRequest.getStatus());
        assertEquals(
            "Wrong action requested.",
            KewApiConstants.ACTION_REQUEST_APPROVE_REQ,
            actionRequest.getActionRequested());
        assertNotNull(
            "Should have been routed through node instance.", actionRequest.getNodeInstance());
        assertEquals(
            "Invalid node.",
            WORKFLOW_DOCUMENT_2_NODE,
            actionRequest.getNodeInstance().getRouteNode().getRouteNodeName());
      }
      if (actionRequest.getPrincipalId().equals(getPrincipalIdForName("pmckown"))) {
        isToPmckown = true;
        assertEquals(
            "Request should be activated.",
            ActionRequestStatus.ACTIVATED.getCode(),
            actionRequest.getStatus());
        assertEquals(
            "Wrong action requested.",
            KewApiConstants.ACTION_REQUEST_APPROVE_REQ,
            actionRequest.getActionRequested());
        assertNotNull(
            "Should have been routed through node instance.", actionRequest.getNodeInstance());
        assertEquals(
            "Invalid node.",
            WORKFLOW_DOCUMENT_3_NODE,
            actionRequest.getNodeInstance().getRouteNode().getRouteNodeName());
      }
    }
    assertTrue("No request to temay.", isToTemay);
    assertTrue("No request to pmckown.", isToPmckown);
    assertTrue("No request to rkirkend.", isToRkirkend);

    // check that we are at both nodes, one in each branch
    Set<String> nodeNames = document.getNodeNames();
    assertEquals("Wrong number of node names.", 2, nodeNames.size());
    boolean isNode2 = false;
    boolean isNode3 = false;
    for (String name : nodeNames) {
      if (name.equals(WORKFLOW_DOCUMENT_2_NODE)) {
        isNode2 = true;
      }
      if (name.equals(WORKFLOW_DOCUMENT_3_NODE)) {
        isNode3 = true;
      }
    }
    assertTrue("Not at node2.", isNode2);
    assertTrue("Not at node3.", isNode3);
    nodeInstances =
        KEWServiceLocator.getRouteNodeService().getActiveNodeInstances(document.getDocumentId());
    assertEquals("Wrong number of active nodes.", 2, nodeInstances.size());
    Iterator<RouteNodeInstance> iterator = nodeInstances.iterator();
    RouteNodeInstance instance1 = (RouteNodeInstance) iterator.next();
    RouteNodeInstance instance2 = (RouteNodeInstance) iterator.next();
    assertNotNull("Node should be in branch.", instance1.getBranch());
    assertNotNull("Node should be in branch.", instance2.getBranch());
    assertTrue(
        "Branches should be different.",
        !instance1.getBranch().getBranchId().equals(instance2.getBranch().getBranchId()));

    document =
        WorkflowDocumentFactory.loadDocument(
            getPrincipalIdForName("rkirkend"), document.getDocumentId());
    assertTrue("Should have request.", document.isApprovalRequested());
    document.approve("Git-r-dun");

    nodeInstances =
        KEWServiceLocator.getRouteNodeService().getActiveNodeInstances(document.getDocumentId());
    assertEquals("Wrong number of active nodes.", 2, nodeInstances.size());
    boolean isAtJoin = false;
    boolean isAtWD3 = false;
    for (RouteNodeInstance nodeInstance : nodeInstances) {
      if (nodeInstance.getRouteNode().getRouteNodeName().equals(JOIN_NODE)) {
        assertEquals(
            "Join branch should be split branch.",
            instance1.getBranch().getParentBranch().getBranchId(),
            nodeInstance.getBranch().getBranchId());
        isAtJoin = true;
      }
      if (nodeInstance.getRouteNode().getRouteNodeName().equals(WORKFLOW_DOCUMENT_3_NODE)) {
        isAtWD3 = true;
      }
    }
    assertTrue("Not at join", isAtJoin);
    assertTrue("Not at WD3", isAtWD3);

    document =
        WorkflowDocumentFactory.loadDocument(
            getPrincipalIdForName("pmckown"), document.getDocumentId());
    assertTrue("Should have request.", document.isApprovalRequested());
    document.approve("Do it.");

    nodeInstances =
        KEWServiceLocator.getRouteNodeService().getActiveNodeInstances(document.getDocumentId());
    assertEquals("Wrong number of active nodes.", 1, nodeInstances.size());
    boolean isAtWDF = false;
    for (RouteNodeInstance nodeInstance : nodeInstances) {
      if (nodeInstance.getRouteNode().getRouteNodeName().equals(WORKFLOW_DOCUMENT_FINAL_NODE)) {
        isAtWDF = true;
      }
    }
    assertTrue("Not at WDF", isAtWDF);

    document =
        WorkflowDocumentFactory.loadDocument(
            getPrincipalIdForName("xqi"), document.getDocumentId());
    assertTrue("Should still be enroute.", document.isEnroute());
    assertTrue("Should have request.", document.isApprovalRequested());
    document.approve("I'm the last approver");

    assertTrue("Document should be processed.", document.isProcessed());
    nodeInstances =
        KEWServiceLocator.getRouteNodeService().getActiveNodeInstances(document.getDocumentId());
    assertEquals(
        "The doc is processed so no node instances should be active", 0, nodeInstances.size());

    document =
        WorkflowDocumentFactory.loadDocument(
            getPrincipalIdForName("temay"), document.getDocumentId());
    assertTrue("Should have request.", document.isAcknowledgeRequested());
    document.acknowledge("");
    assertTrue(document.isFinal());
  }
  public ActionRequestValue deepCopy(Map<Object, Object> visited) {
    if (visited.containsKey(this)) {
      return (ActionRequestValue) visited.get(this);
    }
    ActionRequestValue copy = new ActionRequestValue();
    visited.put(this, copy);
    copy.actionRequestId = actionRequestId;
    copy.actionRequested = actionRequested;
    copy.documentId = documentId;
    copy.ruleBaseValuesId = ruleBaseValuesId;
    copy.status = status;
    copy.responsibilityId = responsibilityId;
    copy.groupId = groupId;
    copy.roleName = roleName;
    copy.qualifiedRoleName = qualifiedRoleName;
    copy.qualifiedRoleNameLabel = qualifiedRoleNameLabel;
    copy.recipientTypeCd = recipientTypeCd;
    copy.priority = priority;
    copy.routeLevel = routeLevel;
    copy.docVersion = docVersion;
    if (createDate != null) {
      copy.createDate = new Timestamp(createDate.getTime());
    }
    copy.responsibilityDesc = responsibilityDesc;
    copy.annotation = annotation;
    copy.jrfVerNbr = jrfVerNbr;
    copy.principalId = principalId;
    copy.forceAction = forceAction;
    copy.currentIndicator = currentIndicator;
    copy.approvePolicy = approvePolicy;
    copy.delegationTypeCode = delegationTypeCode;
    copy.requestLabel = requestLabel;
    if (parentActionRequest != null) {
      copy.parentActionRequest = parentActionRequest.deepCopy(visited);
    }
    if (actionTaken != null) {
      copy.actionTaken = actionTaken.deepCopy(visited);
    }
    if (nodeInstance != null) {
      copy.nodeInstance = nodeInstance.deepCopy(visited);
    }
    if (childrenRequests != null) {
      List<ActionRequestValue> copies = new ArrayList<ActionRequestValue>();
      for (ActionRequestValue childRequest : childrenRequests) {
        copies.add(childRequest.deepCopy(visited));
      }
      copy.childrenRequests = copies;
    }

    copy.createDateString = createDateString;
    copy.displayStatus = displayStatus;
    copy.resolveResponsibility = resolveResponsibility;
    if (routeHeader != null) {
      copy.routeHeader = routeHeader.deepCopy(visited);
    }
    if (simulatedActionItems != null) {
      List<ActionItem> copies = new ArrayList<ActionItem>();
      for (ActionItem simulatedActionItem : simulatedActionItems) {
        copies.add(simulatedActionItem.deepCopy(visited));
      }
      copy.simulatedActionItems = copies;
    }
    return copy;
  }
 private String determineReturnNodeName(RouteNodeInstance startNodeInstance, MovePoint movePoint)
     throws InvalidActionTakenException {
   return determineReturnNodeName(startNodeInstance.getRouteNode(), movePoint, 0);
 }