gt:       else if (scheduler.isInStandbyMode())
context: /*
   *
   *  **************************************************TAPESTRY SOLUTIONS PROPRIETARY VER 2.0
   *  *
   *  *  Copyright 2016 Tapestry Solutions, Inc.
   *  *  THIS PROGRAM IS PROPRIETARY TO TAPESTRY SOLUTIONS, INC.
   *  *  REPRODUCTION, DISCLOSURE, OR USE, IN WHOLE OR IN PART,
   *  *  UNDERTAKEN EXCEPT WITH PRIOR WRITTEN AUTHORIZATION OF
   *  *  TAPESTRY SOLUTIONS IS PROHIBITED.
   *  *
   *  **************************************************TAPESTRY SOLUTIONS PROPRIETARY VER 2.0
   *
   */
  
  package org.jaffa.modules.scheduler.services.quartz;
  
  import org.jaffa.modules.scheduler.services.*;
  import org.jaffa.modules.scheduler.services.configdomain.Task;
  import org.apache.log4j.Logger;
  import org.jaffa.components.voucher.IVoucherGenerator;
  import org.jaffa.components.voucher.VoucherGeneratorFactory;
  import org.jaffa.datatypes.DateTime;
  import org.jaffa.datatypes.exceptions.MandatoryFieldException;
  import org.jaffa.exceptions.ApplicationExceptions;
  import org.jaffa.exceptions.FrameworkException;
  import org.jaffa.modules.messaging.domain.BusinessEventLogMeta;
  import org.jaffa.security.SecurityManager;
  import org.jaffa.util.ExceptionHelper;
  import org.jaffa.util.JAXBHelper;
  import org.quartz.*;
  import org.quartz.Trigger.TriggerState;
  import org.quartz.impl.StdSchedulerFactory;
  import org.quartz.impl.matchers.GroupMatcher;
  
  import javax.xml.bind.JAXBException;
  import java.util.Collection;
  import java.util.Date;
  import java.util.LinkedList;
  import java.util.List;
  
  /**
   * A SchedulerHelper implementation based on the Quartz Scheduler.
   */
  public class QuartzSchedulerHelper implements SchedulerHelper {
  
    private static final Logger LOGGER = Logger
            .getLogger(QuartzSchedulerHelper.class);
  
    private static final String INITIALIZE_ERROR = "Failed to initialize the StdSchedulerFactory: ";
    private static final String SHUTDOWN_ERROR = "Failed to shutdown the StdSchedulerFactory: ";
  
    /**
     * The GroupName used when submitting Jobs to the Quartz service.
     */
    protected final static String JOB_GROUP = "JAFFA";
  
    /**
     * An enumeration of elements added to the JobDataMap of a Job.
     */
    protected enum JobData {
      SCHEDULED_TASK_OBJECT, SCHEDULED_TASK_OBJECT_CLASS_NAME, BUSINESS_OBJECT, BUSINESS_OBJECT_CLASS_NAME, RECURRENCE, RECURRENCE_CLASS_NAME
    }
  
    /**
     * The Quartz Scheduler.
     */
    private Scheduler scheduler;
  
    /**
     * Creates a new instance of QuartzSchedulerHelper. Locates the Quartz service
     * from JNDI.
     *
     * @throws FrameworkException    in case any internal error occurs.
     * @throws ApplicationExceptions Indicates application error(s).
     */
    public QuartzSchedulerHelper() throws FrameworkException,
            ApplicationExceptions {
    }
  
    /**
     * <p>
     * Initialize the <code>{@link org.quartz.SchedulerFactory}</code> with the
     * contents of the given <code>Properties</code> object.
     * </p>
     */
    public void instantiateSchedulerFactory() {
      final StdSchedulerFactory factory = new StdSchedulerFactory();
      try {
        scheduler = factory.getScheduler();
      } catch (SchedulerException e) {
        LOGGER.error(INITIALIZE_ERROR, e);
      }
    }
  
    /**
     * Starts the Scheduler.
     */
    public void startScheduler() {
      try {
        if (scheduler == null || scheduler.isShutdown()) {
          instantiateSchedulerFactory(); // This should create a scheduler, but won't always
  
          if (scheduler != null) {
            scheduler.startDelayed(600 /*seconds to delay the start = 10 min*/);
            LOGGER.info("GOLDesp Scheduler has been started.");
          }
          else {
            LOGGER.warn("No GOLDesp Scheduler to start");
          }
        } else if (scheduler.isInStandbyMode()) {
          scheduler.start();
          LOGGER.info("GOLDesp Scheduler has been started.");
        }
      } catch (SchedulerException e) {
        LOGGER.error("Error starting the scheduler", e);
      }
    }
  
    /**
     * Pauses the Scheduler.
     */
    public void pauseScheduler() {
      try {
        if (!scheduler.isShutdown()) {
          scheduler.standby();
          LOGGER.info("GOLDesp Scheduler has been paused.");
        }
      } catch (SchedulerException e) {
        LOGGER.error("Error calling pause for the scheduler", e);
      }
    }
  
    /**
     * Halts the <code>Scheduler</code>'s firing of <code>{@link Trigger}s</code>,
     * and cleans up all resources associated with the Scheduler. Equivalent to
     * <code>shutdown(false)</code>.
     */
    public void shutdownScheduler() {
      shutdownScheduler(false);
    }
  
    /**
     * Halts the <code>Scheduler</code>'s firing of <code>{@link Trigger}s</code>,
     * and cleans up all resources associated with the Scheduler. Equivalent to
     * <code>shutdown(false)</code>.
     *
     * @param waitForJobsToComplete if <code>true</code> the scheduler will not allow this method to
     *                              return until all currently executing jobs have completed.
     */
    public void shutdownScheduler(final boolean waitForJobsToComplete) {
      try {
        if (!scheduler.isShutdown()) {
          scheduler.shutdown(waitForJobsToComplete);
          LOGGER.info("GOLDesp Scheduler has been shutdown.");
        }
      } catch (SchedulerException e) {
        LOGGER.error(SHUTDOWN_ERROR, e);
      }
    }
  
    /**
     * Returns the list of Tasks from the Scheduler.
     *
     * @return the list of Tasks from the Scheduler.
     * @throws FrameworkException    in case any internal error occurs.
     * @throws ApplicationExceptions Indicates application error(s).
     */
    public ScheduledTask[] getAllTasks() throws FrameworkException,
            ApplicationExceptions {
      // Ensure that the Scheduler is available
      checkScheduler();
      List<ScheduledTask> taskList = getTaskList();
      return taskList != null && taskList.size() > 0 ? taskList
              .toArray(new ScheduledTask[taskList.size()]) : null;
    }
  
    /**
     * Returns the list of Tasks from the Scheduler created by a given user id with a given task type.
     *
     * @param userId   the identifier for a user.
     * @param taskType the type of tasks to be returned.
     * @return the list of Tasks from the Scheduler.
     * @throws FrameworkException    in case any internal error occurs.
     * @throws ApplicationExceptions Indicates application error(s).
     */
    public ScheduledTask[] getTasks(String userId, String taskType) throws FrameworkException, ApplicationExceptions {
      // Ensure that the Scheduler is available
      checkScheduler();
      List<ScheduledTask> returnTasks = null;
      List<ScheduledTask> taskList = getTaskList();
      if (taskList != null && taskList.size() > 0) {
        returnTasks = new LinkedList<ScheduledTask>();
        for (ScheduledTask scheduledTask : taskList) {
          if ((userId == null || scheduledTask.getRunAs().equals(userId)) && (taskType == null || scheduledTask.getTaskType().equals(taskType)))
            returnTasks.add(scheduledTask);
        }
      }
      return returnTasks != null && returnTasks.size() > 0 ? returnTasks.toArray(new ScheduledTask[returnTasks.size()]) : null;
    }
  
    /**
     * Returns the list of Tasks from the Scheduler for the given userId.
     *
     * @param userId the identifier for a user.
     * @return the list of Tasks from the Scheduler for the given userId.
     * @throws FrameworkException    in case any internal error occurs.
     * @throws ApplicationExceptions Indicates application error(s).
     */
    public ScheduledTask[] getUserTasks(String userId) throws FrameworkException,
            ApplicationExceptions {
      // Ensure that the Scheduler is available
      checkScheduler();
      List<ScheduledTask> userTasks = null;
      List<ScheduledTask> taskList = getTaskList();
      if (taskList != null && taskList.size() > 0) {
        userTasks = new LinkedList<ScheduledTask>();
        for (ScheduledTask scheduledTask : taskList) {
          if (scheduledTask.getRunAs().equals(userId))
            userTasks.add(scheduledTask);
        }
      }
      return userTasks != null && userTasks.size() > 0 ? userTasks
              .toArray(new ScheduledTask[userTasks.size()]) : null;
    }
  
    /**
     * Returns the Task from the Scheduler based on the given taskId.
     *
     * @param taskId the identifier for a Task.
     * @return the Task from the Scheduler based on the given taskId.
     * @throws FrameworkException    in case any internal error occurs.
     * @throws ApplicationExceptions Indicates application error(s).
     */
    public ScheduledTask getTask(final String taskId) throws FrameworkException,
            ApplicationExceptions {
      // Ensure that the Scheduler is available
      checkScheduler();
      try {
        final JobKey jobKey = getJobKey(taskId);
        final JobDetail jobDetail = scheduler.getJobDetail(jobKey);
        final List<? extends Trigger> triggers = scheduler
                .getTriggersOfJob(jobKey);
        return jobAndTriggerToTask(jobDetail, triggers);
      } catch (SchedulerException e) {
        LOGGER.error("Error getting task from scheduler " + taskId, e);
        throw new ApplicationExceptions(new JaffaSchedulerApplicationException(
                JaffaSchedulerApplicationException.TASK_NOT_FOUND,
                new Object[]{taskId}));
      }
    }
  
    public JobKey getJobKey(final String taskId) {
      JobKey jobKey = null;
      try {
        for (final JobKey key : scheduler.getJobKeys(GroupMatcher
                .jobGroupEquals(JOB_GROUP))) {
          if (key.getName().equalsIgnoreCase(taskId)) {
            jobKey = key;
            break;
          }
        }
      } catch (SchedulerException e) {
        LOGGER.error(e);
      }
      return jobKey;
    }
  
    /**
     * Updates the Task in the Scheduler.
     *
     * @param task the Task.
     * @throws FrameworkException    in case any internal error occurs.
     * @throws ApplicationExceptions Indicates application error(s).
     */
    public void updateTask(ScheduledTask task) throws FrameworkException,
            ApplicationExceptions {
      // Ensure that the Scheduler is available
      checkScheduler();
  
      // Perform as many validations as possible, before performing the delete
      // Most of the validations happen during Trigger creation.
      if (LOGGER.isDebugEnabled())
        LOGGER.debug("Validating " + task + " before updating it");
      prevalidate(task);
  
      // Stamp LastChangedBy and LastChangedOn
      if (SecurityManager.getPrincipal() != null)
        task.setLastChangedBy(SecurityManager.getPrincipal().getName());
      task.setLastChangedOn(new DateTime());
  
      TriggerHelper.taskToTrigger(task);
  
      // Get the existing Task, in case we need to revert after the delete
      if (LOGGER.isDebugEnabled())
        LOGGER.debug("Get existing values for " + task.getScheduledTaskId()
                + " before updating it");
      ScheduledTask existingTask = getTask(task.getScheduledTaskId());
  
      if (LOGGER.isDebugEnabled())
        LOGGER.debug("Updating " + task.getScheduledTaskId()
                + " by deleting and then adding it");
      deleteTask(task.getScheduledTaskId());
  
      try {
        addTask(task);
      } catch (Exception e) {
        // revert to original values
        if (LOGGER.isDebugEnabled())
          LOGGER.debug("Updating " + task.getScheduledTaskId()
                  + " has failed. Will now add the original values for the Task");
        addTask(existingTask);
        ExceptionHelper.throwAFR(e);
      }
    }
  
    /**
     * Adds the Task to the Scheduler.
     *
     * @param task the Task.
     * @throws FrameworkException    in case any internal error occurs.
     * @throws ApplicationExceptions Indicates application error(s).
     */
    public void addTask(ScheduledTask task) throws FrameworkException,
            ApplicationExceptions {
      // Ensure that the Scheduler is available
      checkScheduler();
  
      if (LOGGER.isDebugEnabled())
        LOGGER.debug("Adding " + task);
  
      // Validate the Task
      prevalidate(task);
  
      // Voucher the technical key
      if (task.getScheduledTaskId() == null
              || task.getScheduledTaskId().length() == 0) {
        IVoucherGenerator vg = VoucherGeneratorFactory.instance();
        vg.setDomainClassName(ScheduledTask.class.getName());
        vg.setFieldName(BusinessEventLogMeta.SCHEDULED_TASK_ID);
        vg.setLabelToken(BusinessEventLogMeta.META_SCHEDULED_TASK_ID
                .getLabelToken());
        task.setScheduledTaskId(vg.generate());
      }
  
      // Stamp CreatedBy and CreatedOn
      if (task.getCreatedBy() == null && SecurityManager.getPrincipal() != null)
        task.setCreatedBy(SecurityManager.getPrincipal().getName());
      if (task.getCreatedOn() == null)
        task.setCreatedOn(new DateTime());
  
      // Create the Job and Trigger
      final JobDetail job = taskToJob(task);
      final Trigger trigger = TriggerHelper.taskToTrigger(task);
  
      // Schedule the Task
      try {
        final Date ft = scheduler.scheduleJob(job, trigger);
        if (LOGGER.isInfoEnabled())
          LOGGER
                  .info(task.getScheduledTaskId()
                          + " has been scheduled to run at: "
                          + ft
                          + (trigger instanceof CronTrigger ? " and repeat based on expression: "
                          + ((CronTrigger) trigger).getCronExpression()
                          : ""));
      } catch (SchedulerException e) {
        LOGGER.error(
                "Error adding task in scheduler " + task.getScheduledTaskId(), e);
        // TODO: if (se.isClientError())
        // throw new ApplicationExceptions(new
        // JaffaSchedulerApplicationException(JaffaSchedulerApplicationException.CLIENT_ERROR,
        // new Object[] {se.getLocalizedMessage()}));
        // else
        throw new JaffaSchedulerFrameworkException(
                JaffaSchedulerFrameworkException.ADD_TASK_ERROR,
                new Object[]{task.getScheduledTaskId()}, e);
      }
    }
  
    /**
     * Deletes the Task from the Scheduler.
     *
     * @param taskId the identifier for a Task.
     * @throws FrameworkException    in case any internal error occurs.
     * @throws ApplicationExceptions Indicates application error(s).
     */
    public void deleteTask(final String taskId) throws FrameworkException,
            ApplicationExceptions {
      // Ensure that the Scheduler is available
      checkScheduler();
      try {
        if (LOGGER.isDebugEnabled())
          LOGGER.debug("Deleting " + taskId);
        scheduler.deleteJob(getJobKey(taskId));
      } catch (SchedulerException se) {
        LOGGER.error("Error deleting task from scheduler " + taskId, se);
        throw new JaffaSchedulerFrameworkException(
                JaffaSchedulerFrameworkException.DELETE_TASK_ERROR,
                new Object[]{taskId}, se);
      }
    }
  
    /**
     * Activates the Task in the Scheduler.
     *
     * @param taskId the identifier for a Task.
     * @throws FrameworkException    in case any internal error occurs.
     * @throws ApplicationExceptions Indicates application error(s).
     */
    public void activateTask(final String taskId) throws FrameworkException,
            ApplicationExceptions {
      // Ensure that the Scheduler is available
      checkScheduler();
      try {
        scheduler.resumeJob(getJobKey(taskId));
      } catch (SchedulerException se) {
        LOGGER.error("Error calling resume task in scheduler " + taskId, se);
        throw new JaffaSchedulerFrameworkException(
                JaffaSchedulerFrameworkException.ACTIVATE_TASK_ERROR,
                new Object[]{taskId}, se);
      }
    }
  
    /**
     * Inactivates the Task in the Scheduler.
     *
     * @param taskId the identifier for a Task.
     * @throws FrameworkException    in case any internal error occurs.
     * @throws ApplicationExceptions Indicates application error(s).
     */
    public void inactivateTask(final String taskId) throws FrameworkException,
            ApplicationExceptions {
      // Ensure that the Scheduler is available
      checkScheduler();
      try {
        scheduler.pauseJob(getJobKey(taskId));
      } catch (SchedulerException se) {
        LOGGER.error("Error calling pause task in scheduler " + taskId, se);
        throw new JaffaSchedulerFrameworkException(
                JaffaSchedulerFrameworkException.INACTIVATE_TASK_ERROR,
                new Object[]{taskId}, se);
      }
    }
  
    /**
     * Returns the status of the Scheduler.
     *
     * @return the status of the Scheduler.
     */
    public SchedulerStatusEnumeration getSchedulerStatus() {
      try {
        if (scheduler.isShutdown())
          return SchedulerStatusEnumeration.STOPPED;
  