/*
   * This could be made a whole lot faster using a recursive query or some other techniques, but due to the caching and,
   * generally speaking, the relatively flat nature of the state machine this shouldn't be expensive.
   */
  public State[] getConcreteDescendentStates(int[] stateIds) throws ApplicationException {
    if (stateIds == null) {
      return null;
    }

    if (stateIds.length == 0) {
      return new State[0];
    }

    ArrayList results = new ArrayList();
    for (int i = 0; i < stateIds.length; i++) {
      ArrayList childrenOfState = (ArrayList) cache.get("descendents/" + stateIds[i]);
      if (childrenOfState == null) {
        childrenOfState = new ArrayList();
        State state = this.getStateById(stateIds[i]);
        if (!state.isAbstract()) {
          childrenOfState.add(state);
        }

        ArrayList children = StateManager.getStatesByParentId(state.getId());
        int[] childrenIds = new int[children.size()];
        for (int j = 0; j < children.size(); j++) {
          childrenIds[j] = ((State) children.get(j)).getId();
        }
        childrenOfState.addAll(Arrays.asList(getConcreteDescendentStates(childrenIds)));
        if (!childrenOfState.isEmpty()) {
          cache.put("descendents/" + stateIds[i], childrenOfState);
        }
      }

      results.addAll(childrenOfState);
    }

    return (State[]) ArrayUtils.toTypedArray(results, State.class);
  }
 public State getStateById(int id) throws ApplicationException {
   State state = (State) cache.get(id);
   if (state == null) {
     state = StateManager.getStateById(id);
     if (state != null) {
       cache.put(id, state);
       cache.put("<workflow>=" + state.getWorkflowId() + "/<name>=" + state.getName(), state);
     }
   }
   return state;
 }
 public State[] getStatesByWorkflowId(int worflowId) throws ApplicationException {
   ArrayList list = StateManager.getStatesByWorkflowId(worflowId);
   State[] result = new State[list.size()];
   for (int i = 0; i < list.size(); i++) {
     State current = (State) list.get(i);
     if (current != null) {
       cache.put(current.getId(), current);
     }
     result[i] = current;
   }
   return result;
 }
 public State getStateByNameAndWorkflowId(String name, int workflowId)
     throws ApplicationException {
   String key = "<workflow>=" + workflowId + "/<name>=" + name;
   State state = (State) cache.get(key);
   if (state == null) {
     state = StateManager.getStateByNameAndWorkflowId(name, workflowId);
     if (state != null) {
       cache.put(key, state);
       cache.put(state.getId(), state);
     }
   }
   return state;
 }
 public void transactionEnteringState(State stateVal, WorkflowTransactionPhase phase)
     throws WorkflowException {
   try {
     // flip the phase to active.
     phase.setStatus(ContractsUtils.getWorkflowStatusCommand().getActiveStatus().getId());
     ContractsUtils.getTransactionPhaseCommand().updateTransactionPhase(phase);
   } catch (ApplicationException ae) {
     LOG.log(Level.SEVERE, "An error occurred while updating phase " + phase.getId(), ae);
     throw new WorkflowException(
         "The transaction failed while entering state "
             + stateVal.getId()
             + ".  The root cause is: "
             + ae.getMessage());
   }
 }
  public AdDcCoopDetailBean[] getAdDcCoopDetailsByWeekAndDivision(
      Calendar adWeek, int regionMemberId) throws Exception {

    LOG.log(
        Level.FINE,
        "beginning of getAdDcCoopDetailsByWeekAndDivision() on the WAS side of NFCCore");

    ArrayList<AdDcCoopBean> coops =
        AdDcCoopManager.getDivisionCoopsByDateAndRegMbrId(adWeek, regionMemberId);

    LOG.log(Level.FINE, "coops_________________" + coops);

    AdDcCoopDetailBean[] results = new AdDcCoopDetailBean[coops.size()];

    LOG.log(Level.FINE, "results_________________" + results);

    LOG.log(
        Level.FINE, "inside of getAdDcCoopDetailsByWeekAndDivision() on the WAS side of NFCCore");
    Workflow coopWorkflow = ContractsUtils.getWorkflowCommand().getWorkflowByName(COOP_WORKFLOW);

    LOG.log(Level.FINE, "coopWorkflow_____________________________" + coopWorkflow);

    if (coopWorkflow == null) {
      LOG.log(Level.FINE, "coopWorkflow_____________________________is null");
      throw new ApplicationException("Unable to locate coop workflow configuration.");
    }

    LOG.log(Level.FINE, "before divisionStateGroup_____________________________");

    State divisionStateGroup =
        ContractsUtils.getStateCommand()
            .getStateByNameAndWorkflowId(DIVISION_STATE, coopWorkflow.getId());

    LOG.log(
        Level.FINE, "before divisionStateGroup_____________________________" + divisionStateGroup);

    State accountingStateGroup =
        ContractsUtils.getStateCommand()
            .getStateByNameAndWorkflowId(ACCOUNTING_STATE, coopWorkflow.getId());

    if (divisionStateGroup == null) {
      throw new ApplicationException("Unable to locate division state in workflow configuration.");
    }

    if (accountingStateGroup == null) {
      throw new ApplicationException(
          "Unable to locate accounting state in workflow configuration.");
    }

    for (int i = 0; i < coops.size(); i++) {
      AdDcCoopBean bean = coops.get(i);
      AdDcCoopDetailBean current = new AdDcCoopDetailBean(bean);
      AdCoopBean adCoop =
          ServiceLocator.getInstance()
              .getService(AdCoopCommand.class)
              .getAdCoopById(current.getCoopId());
      AdEntryBean adEntry =
          ServiceLocator.getInstance()
              .getService(AdEntryCommand.class)
              .getAdEntryByCoopId(current.getCoopId());
      current.setAdEntry(adEntry);
      current.setAdCoop(adCoop);

      current.setInDivisionPhase(
          ContractsUtils.getTransactionPhaseCommand()
              .isPhaseInState(bean.getWorkFlowPhaseId(), divisionStateGroup.getId()));

      current.setInAccountingPhase(
          ContractsUtils.getTransactionPhaseCommand()
              .isPhaseInState(bean.getWorkFlowPhaseId(), accountingStateGroup.getId()));

      results[i] = current;
    }

    LOG.log(Level.FINE, "end of getAdDcCoopDetailsByWeekAndDivision() on the WAS side of NFCCore");

    return results;
  }
  public ArrayList computeTransitions(State stateVal, String outcome) throws WorkflowException {
    if (LOG.isLoggable(Level.FINE)) {
      LOG.entering(State.class.getName(), "computeTransitions", outcome);
    }

    ArrayList results = new ArrayList();
    Transition[] transitions = null;

    try {
      transitions =
          ContractsUtils.getTransitionCommand().getTransitionsByFromStateId(stateVal.getId());

      for (int i = 0; i < transitions.length; i++) {
        Transition tran = transitions[i];
        if (tran.match(outcome)) {
          results.add(tran);
          break;
        }
      }
      // look for Workflow global transitions in the PROP_SET for the workflow
      Workflow wf = ContractsUtils.getWorkflowCommand().getWorkflowById(stateVal.getWorkflowId());
      GenericPropertySet gps = wf.getPropertySet();
      if (gps != null) {
        Iterator it = gps.keys();
        while (it.hasNext()) {
          String name = (String) it.next();
          if (name.startsWith("global.transition_")) {
            String tranName = gps.getProperty(name);
            if (tranName != null) {
              String tranOutcome = gps.getProperty("transition." + tranName + ".outcome");
              if ((tranOutcome == null && outcome == null) || tranOutcome.equals(outcome)) {
                Transition globalTran =
                    ContractsUtils.getTransitionCommand()
                        .getTransitionObjectByImplId(
                            new Integer(gps.getProperty("transition." + tranName + ".implId"))
                                .intValue());
                globalTran.setId(-1);
                globalTran.setFromStateId(stateVal.getId());
                String toState = gps.getProperty("transition." + tranName + ".toState");
                if (toState != null) {
                  if (toState.equals("_#fromState")) {
                    globalTran.setToStateId(stateVal.getId());
                  } else {
                    globalTran.setToStateId(
                        new Integer(
                                ServiceLocator.getInstance()
                                    .getLocal(StateCommandLocal.class)
                                    .getStateByNameAndWorkflowId(toState, wf.getId())
                                    .getId())
                            .intValue());
                  }
                  results.add(globalTran);
                } else {
                  LOG.log(
                      Level.SEVERE,
                      "Global transition " + tranName + " does not specify a toState");
                }
              }
            } else {
              LOG.log(
                  Level.SEVERE,
                  "Global transition key " + name + " does not specify a transition name");
            }
          }
        }
      }
      if (results.size() == 0) {
        Transition defTran =
            ContractsUtils.getTransitionCommand()
                .getTransitionById(stateVal.getDefaultTransitionId());
        if (defTran != null) results.add(defTran);
        else
          throw new WorkflowException(
              "No Transitions exist for this State ["
                  + stateVal.getId()
                  + "] for outcome: ["
                  + outcome
                  + "]!");
      }

    } catch (ApplicationException ae) {
      LOG.log(
          Level.SEVERE,
          "An error occurred while processing transitions from state " + stateVal.getId(),
          ae);
      throw new WorkflowException(
          "An unexpected error occurred while processing the workflow transition: "
              + ae.getMessage());
    } catch (Exception e) {
      LOG.log(
          Level.SEVERE,
          "An error occurred while processing transitions from state " + stateVal.getId(),
          e);
      throw new WorkflowException(
          "An unexpected error occurred while processing the workflow transition: "
              + e.getMessage());
    }

    if (LOG.isLoggable(Level.FINE)) {
      LOG.exiting(State.class.getName(), "computeTransitions", String.valueOf(results.size()));
    }
    return results;
  }