/**
   * Returns the workflow property set for a particular user and workflow
   *
   * @return the workflow property set for the workflow with workflowId and the user represented by
   *     userPrincipal
   */
  public PropertySet getPropertySet(
      InfoGluePrincipal userPrincipal, long workflowId, Session session) {
    PropertySet propertySet = null;

    try {
      WorkflowFacade wf =
          new WorkflowFacade(userPrincipal, workflowId, hibernateSessionFactory, session);
      propertySet = wf.getPropertySet();
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
    }

    return propertySet;
    // return new WorkflowFacade(userPrincipal, workflowId, false).getPropertySet();
  }
  /**
   * Returns a list of all available workflows, i.e., workflows defined in workflows.xml
   *
   * @param userPrincipal a user principal
   * @return a list WorkflowVOs representing available workflows
   */
  public List<WorkflowVO> getAvailableWorkflowVOList(InfoGluePrincipal userPrincipal)
      throws SystemException {
    final List<WorkflowVO> accessibleWorkflows = new ArrayList<WorkflowVO>();

    Session session = null;
    net.sf.hibernate.Transaction tx = null;

    try {
      session = hibernateSessionFactory.openSession();

      tx = session.beginTransaction();

      WorkflowFacade wf = new WorkflowFacade(userPrincipal, hibernateSessionFactory, session);
      final List<WorkflowVO> allWorkflows = wf.getDeclaredWorkflows();

      for (final Iterator<WorkflowVO> i = allWorkflows.iterator(); i.hasNext(); ) {
        final WorkflowVO workflowVO = i.next();
        if (getIsAccessApproved(workflowVO.getName(), userPrincipal)) {
          accessibleWorkflows.add(workflowVO);
        }
      }

      session.flush();

      tx.commit();
    } catch (Exception e) {
      logger.error(
          "An error occurred when we tries to execute getAvailableWorkflowVOList():"
              + e.getMessage(),
          e);
      try {
        tx.rollback();
      } catch (HibernateException he) {
        logger.error(
            "An error occurred when we tries to rollback transaction():" + he.getMessage(), he);
      }
      restoreSessionFactory(e);
    } finally {
      try {
        session.close();
      } catch (HibernateException e) {
        logger.error("An error occurred when we tries to close session:" + e.getMessage(), e);
      }
    }

    return accessibleWorkflows;
  }
  /**
   * @param principal the user principal representing the desired user
   * @param name the name of the workflow to create.
   * @param actionId the ID of the initial action
   * @param inputs the inputs to the workflow
   * @return a WorkflowVO representing the newly created workflow instance
   * @throws SystemException if an error occurs while initiaizing the workflow
   */
  public WorkflowVO initializeWorkflow(
      InfoGluePrincipal principal, String name, int actionId, Map inputs) throws SystemException {
    WorkflowVO workflowVO = null;

    try {
      Session session = null;
      net.sf.hibernate.Transaction tx = null;

      try {
        session = hibernateSessionFactory.openSession();
        tx = session.beginTransaction();

        if (getIsAccessApproved(name, principal)) {
          WorkflowFacade wf =
              new WorkflowFacade(
                  principal, name, actionId, inputs, hibernateSessionFactory, session);
          workflowVO = wf.createWorkflowVO();

          session.flush();

          tx.commit();
        } else {
          throw new Bug("You are not allowed to create " + name + " workflows.");
        }
      } catch (Exception e) {
        logger.error(
            "An error occurred when we tries to run initializeWorkflow():" + e.getMessage(), e);
        try {
          tx.rollback();
        } catch (HibernateException he) {
          logger.error(
              "An error occurred when we tries to rollback transaction:" + he.getMessage(), he);
        }
        restoreSessionFactory(e);
      } finally {
        try {
          session.close();
        } catch (HibernateException e) {
          logger.error("An error occurred when we tries to close:" + e.getMessage(), e);
        }
      }
    } catch (Exception e) {
      throw new SystemException(e);
    }

    return workflowVO;
  }
  /**
   * Returns the workflows owned by the specified principal.
   *
   * @param userPrincipal a user principal.
   * @return a list of WorkflowVOs owned by the principal.
   * @throws SystemException if an error occurs while finding the workflows
   */
  public List getMyCurrentWorkflowVOList(InfoGluePrincipal userPrincipal) throws SystemException {
    List list = new ArrayList();

    Session session = null;
    net.sf.hibernate.Transaction tx = null;

    try {
      session = hibernateSessionFactory.openSession();

      tx = session.beginTransaction();

      WorkflowFacade wf = new WorkflowFacade(userPrincipal, hibernateSessionFactory, session);
      list = wf.getMyActiveWorkflows(userPrincipal);

      session.flush();

      tx.commit();
    } catch (Exception e) {
      logger.error(
          "An error occurred when we tries to execute getMyCurrentWorkflowVOList():"
              + e.getMessage(),
          e);
      try {
        tx.rollback();
      } catch (HibernateException he) {
        logger.error(
            "An error occurred when we tries to rollback transaction:" + he.getMessage(), he);
      }
      restoreSessionFactory(e);
    } finally {
      try {
        session.close();
      } catch (HibernateException e) {
        logger.error("An error occurred when we tries to close session:" + e.getMessage(), e);
      }
    }

    return list;

    // return new WorkflowFacade(userPrincipal, true).getMyActiveWorkflows(userPrincipal);
  }
  /**
   * Returns all current steps for a workflow, i.e., steps that could be performed in the workflow's
   * current state
   *
   * @param userPrincipal a user principal
   * @param workflowId the Id of the desired workflow
   * @return a list of WorkflowStepVOs representing the current steps of the workflow with
   *     workflowId
   */
  public List getCurrentSteps(InfoGluePrincipal userPrincipal, long workflowId) {
    List currentSteps = new ArrayList();

    Session session = null;
    net.sf.hibernate.Transaction tx = null;

    try {
      session = hibernateSessionFactory.openSession();
      tx = session.beginTransaction();

      WorkflowFacade wf =
          new WorkflowFacade(userPrincipal, workflowId, hibernateSessionFactory, session);
      currentSteps = wf.getCurrentSteps();

      session.flush();

      tx.commit();
    } catch (Exception e) {
      logger.error("An error occurred when we tries to run getCurrentSteps():" + e.getMessage(), e);
      try {
        tx.rollback();
      } catch (HibernateException he) {
        logger.error(
            "An error occurred when we tries to rollback transaction:" + he.getMessage(), he);
      }
      restoreSessionFactory(e);
    } finally {
      try {
        session.close();
      } catch (HibernateException e) {
        logger.error("An error occurred when we tries to close session:" + e.getMessage(), e);
      }
    }

    // WorkflowFacade wf = new WorkflowFacade(userPrincipal, workflowId, true);
    // List currentSteps = wf.getCurrentSteps();

    return currentSteps;
  }
  /**
   * Returns true if the workflow has terminated; false otherwise.
   *
   * @param workflowVO the workflow.
   * @return true if the workflow has terminated; false otherwise.
   */
  public boolean hasTerminated(InfoGluePrincipal userPrincipal, long workflowId)
      throws WorkflowException {
    boolean isFinished = false;

    Session session = null;
    net.sf.hibernate.Transaction tx = null;

    try {
      session = hibernateSessionFactory.openSession();
      tx = session.beginTransaction();

      WorkflowFacade wf =
          new WorkflowFacade(userPrincipal, workflowId, hibernateSessionFactory, session);
      isFinished = wf.isFinished();

      session.flush();

      tx.commit();
    } catch (Exception e) {
      logger.error("An error occurred when we tries to run hasTerminated:" + e.getMessage(), e);
      try {
        tx.rollback();
      } catch (HibernateException he) {
        logger.error(
            "An error occurred when we tries to rollback transaction:" + he.getMessage(), he);
      }
      restoreSessionFactory(e);
    } finally {
      try {
        session.close();
      } catch (HibernateException e) {
        logger.error("An error occurred when we tries to close session:" + e.getMessage(), e);
      }
    }

    return isFinished;
    // return new WorkflowFacade(userPrincipal, workflowId, true).isFinished();
  }
  public PropertySet getPropertySet(InfoGluePrincipal userPrincipal, long workflowId) {
    PropertySet propertySet = null;

    Session session = null;
    net.sf.hibernate.Transaction tx = null;

    try {
      session = hibernateSessionFactory.openSession();
      tx = session.beginTransaction();

      WorkflowFacade wf =
          new WorkflowFacade(userPrincipal, workflowId, hibernateSessionFactory, session);
      propertySet = wf.getPropertySet();

      session.flush();

      tx.commit();
    } catch (Exception e) {
      logger.error("An error occurred when we tries to run getHistorySteps():" + e.getMessage(), e);
      try {
        tx.rollback();
      } catch (HibernateException he) {
        logger.error(
            "An error occurred when we tries to rollback transaction:" + he.getMessage(), he);
      }
      restoreSessionFactory(e);
    } finally {
      try {
        session.close();
      } catch (HibernateException e) {
        logger.error("An error occurred when we tries to close session:" + e.getMessage(), e);
      }
    }

    return propertySet;
    // return new WorkflowFacade(userPrincipal, workflowId, false).getPropertySet();
  }
  /**
   * Invokes an action on a workflow for a given user and request
   *
   * @param principal the user principal
   * @param workflowId the ID of the desired workflow
   * @param actionId the ID of the desired action
   * @param inputs the inputs to the workflow
   * @return a WorkflowVO representing the current state of the workflow identified by workflowId
   * @throws WorkflowException if a workflow error occurs
   */
  public WorkflowVO invokeAction(
      InfoGluePrincipal principal, long workflowId, int actionId, Map inputs)
      throws WorkflowException {
    WorkflowVO workflowVO = null;

    Session session = null;
    net.sf.hibernate.Transaction tx = null;

    try {
      session = hibernateSessionFactory.openSession();

      tx = session.beginTransaction();

      WorkflowFacade wf =
          new WorkflowFacade(principal, workflowId, hibernateSessionFactory, session);
      wf.doAction(actionId, inputs);

      session.flush();

      tx.commit();
    } catch (Exception e) {
      logger.error(
          "An error occurred when we tries to execute invokeAction():" + e.getMessage(), e);
      try {
        tx.rollback();
      } catch (HibernateException he) {
        logger.error(
            "An error occurred when we tries to rollback transaction:" + he.getMessage(), he);
      }
      restoreSessionFactory(e);
    } finally {
      try {
        session.close();
      } catch (HibernateException e) {
        logger.error("An error occurred when we tries to close session:" + e.getMessage(), e);
      }
    }

    try {
      session = hibernateSessionFactory.openSession();

      tx = session.beginTransaction();

      WorkflowFacade wf =
          new WorkflowFacade(principal, workflowId, hibernateSessionFactory, session);

      workflowVO = wf.createWorkflowVO();

      session.flush();

      tx.commit();
    } catch (Exception e) {
      logger.error(
          "An error occurred when we tries to execute invokeAction():" + e.getMessage(), e);
      try {
        tx.rollback();
      } catch (HibernateException he) {
        logger.error(
            "An error occurred when we tries to rollback transaction:" + he.getMessage(), he);
      }
      restoreSessionFactory(e);
    } finally {
      try {
        session.close();
      } catch (HibernateException e) {
        logger.error("An error occurred when we tries to close session:" + e.getMessage(), e);
      }
    }

    return workflowVO;
  }