/**
   * Removes a new process instance
   *
   * @param instanceId instance id
   */
  public void removeProcessInstance(String instanceId) throws WorkflowException {
    SilverTrace.info(
        "worflowEngine",
        "ProcessInstanceManagerImpl.removeProcessInstance()",
        "root.MSG_GEN_ENTER_METHOD",
        "InstanceId=" + instanceId);
    ProcessInstanceImpl instance;
    Database db = null;
    try {
      // Delete forms data associated with this instance
      removeProcessInstanceData(instanceId);

      // Constructs the query
      db = WorkflowJDOManager.getDatabase();
      db.begin();
      instance = (ProcessInstanceImpl) db.load(ProcessInstanceImpl.class, instanceId);
      db.remove(instance);
      db.commit();
    } catch (PersistenceException pe) {
      throw new WorkflowException(
          "ProcessInstanceManagerImpl.removeProcessInstance", "EX_ERR_CASTOR_REMOVE_INSTANCE", pe);
    } finally {
      WorkflowJDOManager.closeDatabase(db);
    }

    WorkflowHub.getErrorManager().removeErrorsOfInstance(instanceId);
    SilverTrace.info(
        "worflowEngine",
        "ProcessInstanceManagerImpl.removeProcessInstance()",
        "root.MSG_GEN_EXIT_METHOD");
  }
  /**
   * unlocks this instance for the given instance and state
   *
   * @param state state that have to be locked
   * @param user the locking user
   */
  public void unlock(ProcessInstance instance, State state, User user) throws WorkflowException {
    Database db = null;

    try {
      // Get database connection
      db = WorkflowJDOManager.getDatabase();

      // begin transaction
      db.begin();

      // Re-load process instance
      UpdatableProcessInstance copyInstance =
          (UpdatableProcessInstance) db.load(ProcessInstanceImpl.class, instance.getInstanceId());

      // Do workflow stuff
      try {
        // unlock instance for user
        copyInstance.unLock(state, user);
      } catch (WorkflowException we) {
        db.rollback();
        throw new WorkflowException(
            "ProcessInstanceManagerImpl.unlock", "workflowEngine.EX_ERR_UNLOCK", we);
      }

      // commit
      db.commit();
    } catch (PersistenceException pe) {
      throw new WorkflowException(
          "ProcessInstanceManagerImpl.unlock", "workflowEngine.EX_ERR_CASTOR_UNLOCK", pe);
    } finally {
      WorkflowJDOManager.closeDatabase(db);
    }
  }
  /**
   * Get the process instances for a given instance id
   *
   * @param instanceId id of searched instance
   * @return the searched process instance
   */
  public ProcessInstance getProcessInstance(String instanceId) throws WorkflowException {
    ProcessInstanceImpl instance;

    Database db = null;
    try {
      // Constructs the query
      db = WorkflowJDOManager.getDatabase();
      db.begin();
      instance = (ProcessInstanceImpl) db.load(ProcessInstanceImpl.class, instanceId);
      db.commit();

      return instance;
    } catch (PersistenceException pe) {
      throw new WorkflowException(
          "ProcessInstanceManagerImpl.getProcessInstance", "EX_ERR_CASTOR_GET_INSTANCE", pe);
    } finally {
      WorkflowJDOManager.closeDatabase(db);
    }
  }
  /**
   * Get the list of process instances for which timeout date is over
   *
   * @return an array of ProcessInstance objects
   * @throws WorkflowException
   */
  public ProcessInstance[] getTimeOutProcessInstances() throws WorkflowException {
    Database db = null;
    Connection con = null;
    PreparedStatement prepStmt = null;
    ResultSet rs = null;
    String selectQuery = "";
    OQLQuery query = null;
    QueryResults results;
    List<ProcessInstance> instances = new ArrayList<ProcessInstance>();

    try {
      // Constructs the query
      db = WorkflowJDOManager.getDatabase(false);
      db.begin();

      // Need first to make a SQL query to find all concerned instances ids
      con = this.getConnection();

      selectQuery = "SELECT DISTINCT activeState.instanceId ";
      selectQuery += "FROM SB_Workflow_ActiveState activeState ";
      selectQuery += "WHERE activeState.timeoutDate < ? ";

      prepStmt = con.prepareStatement(selectQuery);
      prepStmt.setTimestamp(1, new Timestamp((new Date()).getTime()));
      rs = prepStmt.executeQuery();

      StringBuffer queryBuf = new StringBuffer();
      queryBuf.append(
          "SELECT distinct instance FROM com.silverpeas.workflow.engine.instance.ProcessInstanceImpl instance");
      queryBuf.append(" WHERE instanceId IN LIST(");

      while (rs.next()) {
        String instanceId = rs.getString(1);
        queryBuf.append("\"");
        queryBuf.append(instanceId);
        queryBuf.append("\"");
        queryBuf.append(" ,");
      }
      queryBuf.append(" \"-1\")");

      query = db.getOQLQuery(queryBuf.toString());

      // Execute the query
      try {
        results = query.execute(org.exolab.castor.jdo.Database.ReadOnly);

        // get the instance if any
        while (results.hasMore()) {
          ProcessInstance instance = (ProcessInstance) results.next();
          instances.add(instance);
        }
      } catch (Exception ex) {
        SilverTrace.warn(
            "workflowEngine",
            "ProcessInstanceManagerImpl.getTimeOutProcessInstances",
            "workflowEngine.EX_PROBLEM_GETTING_INSTANCES",
            ex);
      }

      db.commit();

      return (ProcessInstance[]) instances.toArray(new ProcessInstance[0]);
    } catch (SQLException se) {
      throw new WorkflowException(
          "ProcessInstanceManagerImpl.getTimeOutProcessInstances",
          "EX_ERR_CASTOR_GET_TIMEOUT_INSTANCES",
          "sql query : " + selectQuery,
          se);
    } catch (PersistenceException pe) {
      throw new WorkflowException(
          "ProcessInstanceManagerImpl.getTimeOutProcessInstances",
          "EX_ERR_CASTOR_GET_TIMEOUT_INSTANCES",
          pe);
    } finally {
      WorkflowJDOManager.closeDatabase(db);

      try {
        DBUtil.close(rs, prepStmt);
        if (con != null) con.close();
      } catch (SQLException se) {
        SilverTrace.error(
            "workflowEngine",
            "ProcessInstanceManagerImpl.getTimeOutProcessInstances",
            "root.EX_RESOURCE_CLOSE_FAILED",
            se);
      }
    }
  }