/**
   * Creates a new {@link TaskParentInterfaceImpl} object.</b> It initializes the {@link
   * IDataAccessProvider}</b> Moreover all timers are reactivated (e.g. suspend until timer,
   * expiration timer). See {@link TaskInstanceTimers} for more information.
   */
  public TaskParentInterfaceImpl() {
    // this.dataAccessProvider = IDataAccessProvider.Factory.newInstance();
    this.evenHandler = EventHandler.newInstance();

    /*
     * Reactivate all task instance timers (e.g. suspend until timer,
     * expiration timer) i.e. schedule the execution of certain actions
     * until their timer has expired.
     */
    TaskInstanceTimers.reactivateTimers();
  }
  /*
   * (non-Javadoc)
   *
   * @see com.htm.TaskParentInterface#createTaskInstance(java.lang.String,
   * java.lang.String, java.lang.Object, java.util.Set, java.lang.String,
   * java.sql.Timestamp)
   */
  public String createTaskInstance(
      String taskParentId,
      Set<ICorrelationProperty> correlationProperties,
      String taskModelName,
      String taskInstanceName,
      Object inputData,
      Set<IAttachment> attachments,
      Timestamp expirationTime)
      throws HumanTaskManagerException {

    try {

      // TODO contextId
      String initiatorUserId = getCurrentUser();

      if (StringUtils.isEmpty(initiatorUserId)) {
        String errorMsg = "The username of the task initiator could not be determined.";
        log.error(errorMsg);
        throw new HumanTaskManagerException(errorMsg);
      }

      /* Start transaction for creating a task instance */
      dataAccessProvider.beginTx();
      this.authorizationManager.authorizeTaskParentAction(
          initiatorUserId, null, EActions.CREATE_TASK_INSTANCE);

      /* Create the task instance model */
      TaskInstanceFactory taskFac = this.taskInstanceFactory;
      ITaskInstance taskInstance =
          taskFac.createTaskInstance(
              taskModelName,
              taskInstanceName,
              inputData,
              taskParentId,
              correlationProperties,
              expirationTime);

      /* Store the task instance instance */
      dataAccessProvider.persistHumanTaskInstance(taskInstance);

      // Audit
      // if (Configuration.isLoggingEnabled()) {
      // IAuditLogger auditLogger = AuditFactory.newInstance();
      // TaskInstanceView taskInstanceView = new
      // TaskInstanceView(taskInstance);
      // AuditAction action = new
      // AuditAction(EActions.CREATE_TASK_INSTANCE.toString(),
      // taskInstanceView, taskInstanceView.getStatus(), null,
      // initiatorUserId);
      // auditLogger.logAction(action);
      // }

      /* Activate the task instance expiration timer. */
      TaskInstanceTimers.activateExpirationTimer(taskInstance);

      /*
       * Create Work Items and add attachments
       */
      List<IWorkItem> workItems = new ArrayList<IWorkItem>();

      WorkItemFactory workItemFac = this.workItemFactory;
      /*
       * A single work item for the task initiator has to be created
       * because she is not defined in the task model by a people query.
       * This should be done before the other work items are created since
       * the people queries in the task model could refer on the task
       * initiator.
       */
      workItems.add(
          workItemFac.createNewWorkItem(initiatorUserId, EHumanRoles.TASK_INITIATOR, taskInstance));
      /*
       * The attachments should also be added before the other work items
       * are created then the people queries can refer on the attachments.
       */
      taskInstance.setAttachments(
          this.taskInstanceFactory.createAssignedUser(initiatorUserId), attachments);

      /*
       * Create work items for roles that are defined via people queries
       * within the task model i.e. for roles business administrators,
       * task stakeholder, potential owners
       */
      workItems.addAll(workItemFac.createWorkItemsForTaskInstance(taskInstance));

      // TODO: evaluate QueryProperties
      taskFac.evaluateQueryProperties(taskInstance.getId(), taskModelName);

      /*
       * If the task instance has one or more potential owners it
       * transitions to ready state i.e. it is activated
       */
      boolean hasPotentialOwner = taskInstance.hasPotentialOwners();

      log.debug("Create task instance - Task instance has potential owners : " + hasPotentialOwner);
      /*
       * The task instance can only set to the READY state if it has
       * potential owners and if the task instance is not already expired.
       */
      String oldState = taskInstance.getStatus().toString();
      if (taskInstance.hasPotentialOwners() && !taskInstance.isExpired()) {
        taskInstance.setStatus(ETaskInstanceState.READY);
        taskInstance.setActivationTime(new Timestamp(Calendar.getInstance().getTimeInMillis()));
        // TODO only one potential owner -> immediately go to reserved
        // state
      }

      if (!hasPotentialOwner) {
        log.info(
            "Create task instance - "
                + "Can't transition to '"
                + ETaskInstanceState.READY
                + "' state because no potential owner(s) were found.");
      }
      if (taskInstance.isExpired()) {
        log.info(
            "Create task instance - "
                + "The task instance is "
                + ETaskInstanceState.OBSOLETE
                + " created because it has already expired at '"
                + Utilities.formatTimestamp(expirationTime)
                + "'.");
      }

      dataAccessProvider.persistWorkItems(workItems);
      /* Inform event subscriber about the new work items */
      publishNewWorkItemEvent(workItems);

      // Audit
      if (Configuration.isLoggingEnabled()) {
        IAuditLogger auditLogger = AuditFactory.newInstance();
        TaskInstanceView taskInstanceView = new TaskInstanceView(taskInstance);
        AuditAction action =
            new AuditAction(
                EActions.CREATE_TASK_INSTANCE.toString(),
                taskInstanceView,
                taskInstanceView.getStatus(),
                oldState,
                initiatorUserId);
        auditLogger.logAction(action);
      }

      dataAccessProvider.commitTx();
      return taskInstance.getId();
    } catch (HumanTaskManagerException e) {
      dataAccessProvider.rollbackTx();
      throw e;
    } finally {
      dataAccessProvider.close();
    }
  }