public void addJob(AbstractExecutable executable) {
   try {
     executableDao.addJob(parse(executable));
     addJobOutput(executable);
   } catch (PersistentException e) {
     logger.error("fail to submit job:" + executable.getId(), e);
     throw new RuntimeException(e);
   }
 }
 private void addJobOutput(AbstractExecutable executable) throws PersistentException {
   ExecutableOutputPO executableOutputPO = new ExecutableOutputPO();
   executableOutputPO.setUuid(executable.getId());
   executableDao.addJobOutput(executableOutputPO);
   if (executable instanceof DefaultChainedExecutable) {
     for (AbstractExecutable subTask : ((DefaultChainedExecutable) executable).getTasks()) {
       addJobOutput(subTask);
     }
   }
 }
 public void discardJob(String jobId) {
   AbstractExecutable job = getJob(jobId);
   if (job instanceof DefaultChainedExecutable) {
     List<AbstractExecutable> tasks = ((DefaultChainedExecutable) job).getTasks();
     for (AbstractExecutable task : tasks) {
       if (!task.getStatus().isFinalState()) {
         updateJobOutput(task.getId(), ExecutableState.DISCARDED, null, null);
       }
     }
   }
   updateJobOutput(jobId, ExecutableState.DISCARDED, null, null);
 }
 private static ExecutablePO parse(AbstractExecutable executable) {
   ExecutablePO result = new ExecutablePO();
   result.setName(executable.getName());
   result.setUuid(executable.getId());
   result.setType(executable.getClass().getName());
   result.setParams(executable.getParams());
   if (executable instanceof DefaultChainedExecutable) {
     List<ExecutablePO> tasks = Lists.newArrayList();
     for (AbstractExecutable task : ((DefaultChainedExecutable) executable).getTasks()) {
       tasks.add(parse(task));
     }
     result.setTasks(tasks);
   }
   return result;
 }
 public void resumeJob(String jobId) {
   AbstractExecutable job = getJob(jobId);
   if (job == null) {
     return;
   }
   updateJobOutput(jobId, ExecutableState.READY, null, null);
   if (job instanceof DefaultChainedExecutable) {
     List<AbstractExecutable> tasks = ((DefaultChainedExecutable) job).getTasks();
     for (AbstractExecutable task : tasks) {
       if (task.getStatus() == ExecutableState.ERROR) {
         updateJobOutput(task.getId(), ExecutableState.READY, null, null);
         break;
       }
     }
   }
 }