/**
   * Executes an import by getting the parameters from the notification.
   *
   * @param notification the notification
   * @return the status of the import
   */
  protected ImportJobStatus executeImport(final ImportNotification notification) {
    ImportJob importJob = notification.getImportJob();

    // update the CSV file path with the local file path
    notification.setImportSource(getRemoteCsvFileName(notification.getImportSource()));

    // Validate again
    final ImportDataType importDataType =
        importService.findImportDataType(importJob.getImportDataTypeName());
    if (importDataType == null) {
      throw new EpSystemException(
          "ImportJob specifies unknown importDataType " + importJob.getImportDataTypeName());
    }

    ImportJobRunner importJobRunner =
        getImportJobRunner(importDataType.getImportJobRunnerBeanName());
    importJobRunner.init(notification, notification.getProcessId());

    updateTotalRowsNumber(importJobRunner.getTotalRows(), notification.getProcessId());

    importJobStatusHandler.reportImportJobState(
        notification.getProcessId(), ImportJobState.RUNNING);
    // Start the runner.
    LOG.info("Launch import job runner: " + importJobRunner);
    importJobRunner.run();

    return importJobStatusHandler.getImportJobStatus(notification.getProcessId());
  }
 /**
  * Verifies whether the import job process was cancelled and if yes reports it to the status.
  *
  * @param importJobProcessId the process ID
  * @return true if cancelled
  */
 protected boolean isCancelled(final String importJobProcessId) {
   if (importJobStatusHandler.isImportJobCancelled(importJobProcessId)) {
     importJobStatusHandler.reportImportJobState(importJobProcessId, ImportJobState.CANCELLED);
     return true;
   }
   return false;
 }
  private boolean validateImportJob(final ImportNotification notification) {
    importJobStatusHandler.reportImportJobState(
        notification.getProcessId(), ImportJobState.VALIDATING);

    List<ImportBadRow> importBadRows = Collections.emptyList();
    try {
      importBadRows = processValidation(notification);
    } catch (Exception exc) {
      LOG.error("Validation failed.", exc);
      importJobStatusHandler.reportImportJobState(
          notification.getProcessId(), ImportJobState.VALIDATION_FAILED);
      return false;
    }

    if (CollectionUtils.isNotEmpty(importBadRows)) {
      importJobStatusHandler.reportBadRows(
          notification.getProcessId(),
          importBadRows.toArray(new ImportBadRow[importBadRows.size()]));
      importJobStatusHandler.reportImportJobState(
          notification.getProcessId(), ImportJobState.VALIDATION_FAILED);
      return false;
    }

    importJobStatusHandler.reportImportJobState(
        notification.getProcessId(), ImportJobState.QUEUED_FOR_IMPORT);
    return true;
  }
  /**
   * Validates one import job in case there is a notification for that.
   *
   * <p>Note: Only one job at a time will be processed. It is not clear what the consequences will
   * be in a clustered environment running different import jobs. All submitted import jobs are
   * executed in sequence ordered by the date of submission.
   */
  public void launchImportJob() {
    final long startTime = System.currentTimeMillis();
    LOG.info("Start import job quartz job at: " + new Date(startTime));

    if (hasRunningImportJob()) {
      LOG.info("Import Job. Another processor is running at the moment. Quiting operation.");
      return;
    }
    List<ImportNotification> notifications =
        importNotificationDao.findByActionAndState(
            ImportAction.LAUNCH_IMPORT, ImportNotificationState.NEW, 1);

    if (CollectionUtils.isEmpty(notifications)) {
      LOG.info("Import Job. No notifications found. Quiting operation.");
      return;
    }

    // grab the first notification. there should be only one.
    ImportNotification notification = notifications.iterator().next();

    if (!lock(notification)) {
      LOG.info(
          "Import Job. Could not lock notification. Likely locked by another processor. "
              + notification);
      return;
    }

    try {
      if (isCancelled(notification.getProcessId())) {
        LOG.info("Import Job cancelled. Process ID: " + notification.getProcessId());
        return;
      }

      if (validateImportJob(notification)) {
        if (isCancelled(notification.getProcessId())) {
          LOG.info("Import Job cancelled. Process ID: " + notification.getProcessId());
          return;
        }
        ImportJobStatus importStatus = null;
        try {
          importStatus = executeImport(notification);
        } catch (Exception exc) {
          LOG.error("Import job failure.", exc);
          importJobStatusHandler.reportImportJobState(
              notification.getProcessId(), ImportJobState.FAILED);
          return;
        }
        sendEmail(importStatus, notification.getInitiator(), notification.getReportingLocale());
        LOG.info(
            "Import job quartz job completed in (ms): " + (System.currentTimeMillis() - startTime));
      }
    } finally {
      unlock(notification);
    }
  }
 /**
  * @param totalRows the total number of rows
  * @param processId the process ID
  */
 protected void updateTotalRowsNumber(final int totalRows, final String processId) {
   importJobStatusHandler.reportTotalRows(processId, totalRows);
 }