@Override
  protected void processRequest() throws Exception {
    FormProcessor fp = new FormProcessor(request);
    TriggerService triggerService = new TriggerService();
    String action = fp.getString("action");
    String triggerName = fp.getString("tname");
    scheduler = getScheduler();
    System.out.println("found trigger name " + triggerName);
    Trigger trigger = scheduler.getTrigger(triggerName.trim(), TRIGGER_IMPORT_GROUP);
    System.out.println("found trigger from the other side " + trigger.getFullName());
    if (StringUtil.isBlank(action)) {
      setUpServlet(trigger);
      forwardPage(Page.UPDATE_JOB_IMPORT);
    } else if ("confirmall".equalsIgnoreCase(action)) {
      HashMap errors =
          triggerService.validateImportJobForm(
              fp, request, scheduler.getTriggerNames("DEFAULT"), trigger.getName());
      if (!errors.isEmpty()) {
        // send back
        addPageMessage(
            "Your modifications caused an error, please see the messages for more information.");
        setUpServlet(trigger);
        forwardPage(Page.UPDATE_JOB_IMPORT);
      } else {
        StudyDAO studyDAO = new StudyDAO(sm.getDataSource());
        int studyId = fp.getInt(CreateJobImportServlet.STUDY_ID);
        StudyBean study = (StudyBean) studyDAO.findByPK(studyId);
        // in the place of a users' current study, tbh
        Date startDate = trigger.getStartTime();
        trigger =
            triggerService.generateImportTrigger(
                fp, sm.getUserBean(), study, startDate, request.getLocale().getLanguage());
        // scheduler = getScheduler();
        JobDetailBean jobDetailBean = new JobDetailBean();
        jobDetailBean.setGroup(TRIGGER_IMPORT_GROUP);
        jobDetailBean.setName(trigger.getName());
        jobDetailBean.setJobClass(org.akaza.openclinica.web.job.ImportStatefulJob.class);
        jobDetailBean.setJobDataMap(trigger.getJobDataMap());
        jobDetailBean.setDurability(true); // need durability?
        jobDetailBean.setVolatility(false);

        try {
          scheduler.deleteJob(triggerName, TRIGGER_IMPORT_GROUP);
          Date dateStart = scheduler.scheduleJob(jobDetailBean, trigger);

          addPageMessage("Your job has been successfully modified.");
          forwardPage(Page.VIEW_IMPORT_JOB_SERVLET);
        } catch (SchedulerException se) {
          se.printStackTrace();
          // set a message here with the exception message
          setUpServlet(trigger);
          addPageMessage(
              "There was an unspecified error with your creation, please contact an administrator.");
          forwardPage(Page.UPDATE_JOB_IMPORT);
        }
      }
    }
  }
  protected SchedulerResponse getScheduledJob(Scheduler scheduler, JobKey jobKey) throws Exception {

    JobDetail jobDetail = scheduler.getJobDetail(jobKey);

    if (jobDetail == null) {
      return null;
    }

    SchedulerResponse schedulerResponse = new SchedulerResponse();

    JobDataMap jobDataMap = jobDetail.getJobDataMap();

    String description = jobDataMap.getString(SchedulerEngine.DESCRIPTION);

    schedulerResponse.setDescription(description);

    String destinationName = jobDataMap.getString(SchedulerEngine.DESTINATION_NAME);

    schedulerResponse.setDestinationName(destinationName);

    Message message = getMessage(jobDataMap);

    JobState jobState = getJobState(jobDataMap);

    message.put(SchedulerEngine.JOB_STATE, jobState);

    schedulerResponse.setMessage(message);

    StorageType storageType =
        StorageType.valueOf(jobDataMap.getString(SchedulerEngine.STORAGE_TYPE));

    schedulerResponse.setStorageType(storageType);

    String jobName = jobKey.getName();
    String groupName = jobKey.getGroup();

    TriggerKey triggerKey = new TriggerKey(jobName, groupName);

    Trigger trigger = scheduler.getTrigger(triggerKey);

    if (trigger == null) {
      schedulerResponse.setGroupName(groupName);
      schedulerResponse.setJobName(jobName);

      return schedulerResponse;
    }

    message.put(SchedulerEngine.END_TIME, trigger.getEndTime());
    message.put(SchedulerEngine.FINAL_FIRE_TIME, trigger.getFinalFireTime());
    message.put(SchedulerEngine.NEXT_FIRE_TIME, trigger.getNextFireTime());
    message.put(SchedulerEngine.PREVIOUS_FIRE_TIME, trigger.getPreviousFireTime());
    message.put(SchedulerEngine.START_TIME, trigger.getStartTime());

    schedulerResponse.setTrigger(new QuartzTrigger(trigger));

    return schedulerResponse;
  }
  public static Trigger convertTriggerFromNativeObject(org.quartz.Trigger quartzTrigger) {
    Trigger spagobiTrigger;

    spagobiTrigger = new Trigger();
    spagobiTrigger.setName(quartzTrigger.getName());
    spagobiTrigger.setGroupName(quartzTrigger.getGroup());
    spagobiTrigger.setDescription(quartzTrigger.getDescription());

    // spagobiTrigger.setCalendarName( quartzTrigger.getCalendarName() );
    Assert.assertTrue(
        quartzTrigger.getCalendarName() == null,
        "quartz trigger calendar name is not null: " + quartzTrigger.getCalendarName());

    spagobiTrigger.setStartTime(quartzTrigger.getStartTime());
    spagobiTrigger.setEndTime(quartzTrigger.getEndTime());

    // triggers that run immediately have a generated name that starts with schedule_uuid_ (see
    // TriggerXMLDeserializer)
    // It would be better anyway to relay on a specific property to recognize if a trigger is
    // thinked to run immediately
    spagobiTrigger.setRunImmediately(spagobiTrigger.getName().startsWith("schedule_uuid_"));

    if (quartzTrigger instanceof org.quartz.CronTrigger) {
      org.quartz.CronTrigger quartzCronTrigger = (org.quartz.CronTrigger) quartzTrigger;
      // dirty trick
      String expression = (String) quartzCronTrigger.getJobDataMap().get(SPAGOBI_CRON_EXPRESSION);
      if (expression != null) {
        quartzCronTrigger.getJobDataMap().remove(SPAGOBI_CRON_EXPRESSION);
      } else {
        // for back compatibility
        expression =
            (String) quartzCronTrigger.getJobDataMap().get(SPAGOBI_CRON_EXPRESSION_DEPRECATED);
        quartzCronTrigger.getJobDataMap().remove(SPAGOBI_CRON_EXPRESSION_DEPRECATED);
      }
      spagobiTrigger.setCronExpression(new CronExpression(expression));
    }

    Job job = new Job();
    job.setName(quartzTrigger.getJobName());
    job.setGroupName(quartzTrigger.getJobGroup());
    job.setVolatile(quartzTrigger.isVolatile());
    Map<String, String> parameters =
        convertParametersFromNativeObject(quartzTrigger.getJobDataMap());
    job.addParameters(parameters);

    spagobiTrigger.setJob(job);

    return spagobiTrigger;
  }
  protected void unschedule(Scheduler scheduler, JobKey jobKey) throws Exception {

    JobDetail jobDetail = scheduler.getJobDetail(jobKey);

    TriggerKey triggerKey = new TriggerKey(jobKey.getName(), jobKey.getGroup());

    if (jobDetail == null) {
      return;
    }

    unregisterMessageListener(scheduler, jobKey);

    JobDataMap jobDataMap = jobDetail.getJobDataMap();

    JobState jobState = getJobState(jobDataMap);

    Trigger trigger = scheduler.getTrigger(triggerKey);

    if (trigger == null) {
      return;
    }

    jobState.setTriggerDate(SchedulerEngine.END_TIME, new Date());
    jobState.setTriggerDate(SchedulerEngine.FINAL_FIRE_TIME, trigger.getPreviousFireTime());
    jobState.setTriggerDate(SchedulerEngine.NEXT_FIRE_TIME, null);
    jobState.setTriggerDate(SchedulerEngine.PREVIOUS_FIRE_TIME, trigger.getPreviousFireTime());
    jobState.setTriggerDate(SchedulerEngine.START_TIME, trigger.getStartTime());

    jobState.setTriggerState(TriggerState.UNSCHEDULED);

    jobState.clearExceptions();

    jobDataMap.put(SchedulerEngine.JOB_STATE, JobStateSerializeUtil.serialize(jobState));

    scheduler.unscheduleJob(triggerKey);

    scheduler.addJob(jobDetail, true);
  }
  /**
   * Schedules a given job and trigger (both wrapped by a <code>JobSchedulingBundle</code>).
   *
   * @param job job wrapper.
   * @param sched job scheduler.
   * @param localOverWriteExistingJobs locally overwrite existing jobs.
   * @exception SchedulerException if the Job or Trigger cannot be added to the Scheduler, or there
   *     is an internal Scheduler error.
   */
  public void scheduleJob(
      JobSchedulingBundle job, Scheduler sched, boolean localOverWriteExistingJobs)
      throws SchedulerException {
    if ((job != null) && job.isValid()) {
      JobDetail detail = job.getJobDetail();

      JobDetail dupeJ = sched.getJobDetail(detail.getName(), detail.getGroup());

      if ((dupeJ != null) && !localOverWriteExistingJobs) {
        getLog().info("Not overwriting existing job: " + dupeJ.getFullName());
        return;
      }

      if (dupeJ != null) {
        getLog().info("Replacing job: " + detail.getFullName());
      } else {
        getLog().info("Adding job: " + detail.getFullName());
      }

      if (job.getTriggers().size() == 0 && !job.getJobDetail().isDurable()) {
        if (dupeJ == null) {
          throw new SchedulerException(
              "A new job defined without any triggers must be durable: " + detail.getFullName());
        }

        if ((dupeJ.isDurable()
            && (sched.getTriggersOfJob(detail.getName(), detail.getGroup()).length == 0))) {
          throw new SchedulerException(
              "Can't make a durable job without triggers non-durable: " + detail.getFullName());
        }
      }

      sched.addJob(detail, true);

      for (Iterator iter = job.getTriggers().iterator(); iter.hasNext(); ) {
        Trigger trigger = (Trigger) iter.next();

        trigger.setJobName(detail.getName());
        trigger.setJobGroup(detail.getGroup());

        if (trigger.getStartTime() == null) {
          trigger.setStartTime(new Date());
        }

        boolean addedTrigger = false;
        while (addedTrigger == false) {
          Trigger dupeT = sched.getTrigger(trigger.getName(), trigger.getGroup());
          if (dupeT != null) {
            if (getLog().isDebugEnabled()) {
              getLog()
                  .debug(
                      "Rescheduling job: "
                          + detail.getFullName()
                          + " with updated trigger: "
                          + trigger.getFullName());
            }
            if (!dupeT.getJobGroup().equals(trigger.getJobGroup())
                || !dupeT.getJobName().equals(trigger.getJobName())) {
              getLog().warn("Possibly duplicately named triggers in jobs xml file!");
            }
            sched.rescheduleJob(trigger.getName(), trigger.getGroup(), trigger);
          } else {
            if (getLog().isDebugEnabled()) {
              getLog()
                  .debug(
                      "Scheduling job: "
                          + detail.getFullName()
                          + " with trigger: "
                          + trigger.getFullName());
            }

            try {
              sched.scheduleJob(trigger);
            } catch (ObjectAlreadyExistsException e) {
              if (getLog().isDebugEnabled()) {
                getLog()
                    .debug(
                        "Adding trigger: "
                            + trigger.getFullName()
                            + " for job: "
                            + detail.getFullName()
                            + " failed because the trigger already existed.  "
                            + "This is likely due to a race condition between multiple instances "
                            + "in the cluster.  Will try to reschedule instead.");
              }
              continue;
            }
          }
          addedTrigger = true;
        }
      }

      addScheduledJob(job);
    }
  }
  protected SchedulerResponse getScheduledJob(Scheduler scheduler, JobKey jobKey) throws Exception {

    JobDetail jobDetail = scheduler.getJobDetail(jobKey);

    if (jobDetail == null) {
      return null;
    }

    SchedulerResponse schedulerResponse = new SchedulerResponse();

    JobDataMap jobDataMap = jobDetail.getJobDataMap();

    String description = jobDataMap.getString(SchedulerEngine.DESCRIPTION);

    schedulerResponse.setDescription(description);

    String destinationName = jobDataMap.getString(SchedulerEngine.DESTINATION_NAME);

    schedulerResponse.setDestinationName(destinationName);

    Message message = getMessage(jobDataMap);

    JobState jobState = getJobState(jobDataMap);

    message.put(SchedulerEngine.JOB_STATE, jobState);

    schedulerResponse.setMessage(message);

    StorageType storageType =
        StorageType.valueOf(jobDataMap.getString(SchedulerEngine.STORAGE_TYPE));

    schedulerResponse.setStorageType(storageType);

    String jobName = jobKey.getName();
    String groupName = jobKey.getGroup();

    TriggerKey triggerKey = new TriggerKey(jobName, groupName);

    Trigger trigger = scheduler.getTrigger(triggerKey);

    if (trigger == null) {
      schedulerResponse.setGroupName(groupName);
      schedulerResponse.setJobName(jobName);

      return schedulerResponse;
    }

    message.put(SchedulerEngine.END_TIME, trigger.getEndTime());
    message.put(SchedulerEngine.FINAL_FIRE_TIME, trigger.getFinalFireTime());
    message.put(SchedulerEngine.NEXT_FIRE_TIME, trigger.getNextFireTime());
    message.put(SchedulerEngine.PREVIOUS_FIRE_TIME, trigger.getPreviousFireTime());
    message.put(SchedulerEngine.START_TIME, trigger.getStartTime());

    if (trigger instanceof CalendarIntervalTrigger) {
      CalendarIntervalTrigger calendarIntervalTrigger = CalendarIntervalTrigger.class.cast(trigger);

      IntervalUnit intervalUnit = calendarIntervalTrigger.getRepeatIntervalUnit();

      schedulerResponse.setTrigger(
          new IntervalTrigger(
              jobName,
              groupName,
              calendarIntervalTrigger.getStartTime(),
              calendarIntervalTrigger.getEndTime(),
              calendarIntervalTrigger.getRepeatInterval(),
              TimeUnit.valueOf(intervalUnit.name())));
    } else if (trigger instanceof CronTrigger) {
      CronTrigger cronTrigger = CronTrigger.class.cast(trigger);

      schedulerResponse.setTrigger(
          new com.liferay.portal.kernel.scheduler.CronTrigger(
              jobName,
              groupName,
              cronTrigger.getStartTime(),
              cronTrigger.getEndTime(),
              cronTrigger.getCronExpression()));
    } else if (trigger instanceof SimpleTrigger) {
      SimpleTrigger simpleTrigger = SimpleTrigger.class.cast(trigger);

      schedulerResponse.setTrigger(
          new IntervalTrigger(
              jobName,
              groupName,
              simpleTrigger.getStartTime(),
              simpleTrigger.getEndTime(),
              (int) simpleTrigger.getRepeatInterval(),
              TimeUnit.MILLISECOND));
    }

    return schedulerResponse;
  }