· 4 years ago · Apr 19, 2021, 08:22 AM
1package eu.nites.bcc.core.asm.core;
2
3import cz.atria.common.db.util.QueryRepository;
4import cz.atria.common.db.util.SQLRuntimeException;
5import cz.atria.common.db.util.handlers.ListHandler;
6import cz.atria.common.db.util.id.GenIdObject;
7import cz.atria.common.db.util.repositories.PackageRepository;
8import cz.atria.common.lang.Util;
9import eu.nites.bcc.core.asm.core.XMLRequest.*;
10import eu.nites.bcc.core.asm.core.actionlauncher.ASMActionJob;
11import eu.nites.bcc.core.asm.core.actionlauncher.ASMExecutionHelper;
12import eu.nites.bcc.core.asm.core.actionlauncher.ASMJobListener;
13import eu.nites.bcc.core.asm.core.actionlauncher.ASMTriggerListener;
14import eu.nites.bcc.core.core.core.AppMessageSource;
15import eu.nites.bcc.core.core.core.SpringBaseDAO;
16import eu.nites.bcc.core.core.core.SpringSecurityDAO;
17import eu.nites.bcc.core.core.core.User;
18import eu.nites.bcc.core.core.core.sort.OrderInfo;
19import eu.nites.bcc.core.core.core.sort.OrderInfoComparator;
20import eu.nites.bcc.core.core.core.treestructure.TSObjectVersionStateEnum;
21import org.apache.commons.logging.Log;
22import org.apache.commons.logging.LogFactory;
23import org.quartz.*;
24import org.quartz.impl.matchers.GroupMatcher;
25import org.quartz.impl.triggers.CronTriggerImpl;
26import org.springframework.beans.factory.annotation.Autowired;
27import org.springframework.beans.factory.annotation.Qualifier;
28import org.springframework.scheduling.quartz.SchedulerFactoryBean;
29import org.springframework.stereotype.Repository;
30import org.springframework.transaction.annotation.Transactional;
31
32import javax.annotation.PostConstruct;
33import java.sql.SQLException;
34import java.text.ParseException;
35import java.util.*;
36
37/**
38 * @author Damir Yunusov
39 * @since 19.10.2009
40 */
41@Repository
42@Transactional
43public class SpringASMExecutionsDAO extends SpringBaseDAO
44{
45 public static final String BEAN_NAME = "springASMExecutionsDAO";
46 private final static String SQL_PATH = "eu.nites.bcc.core.asm.core.sql.actionlauncher";
47
48 private final static String CREATE_ACTION_EXECUTION_SQL = "CreateActionExecution";
49 private final static String UPDATE_ACTION_EXECUTION_SQL = "UpdateActionExecution";
50 private final static String CREATE_EXECUTION_PARAMETER_SQL = "CreateExecutionParameter";
51 private final static String CREATE_LARGE_EXECUTION_PARAMETER_SQL = "CreateLargeExecutionParameter";
52 private final static String UPDATE_EXECUTION_PARAMETER_SQL = "UpdateExecutionParameter";
53
54 private static final String UPDATE_EXECUTION_IS_CHAINING_QUEUED = "UpdateExecutionIsChainingQueued";
55
56 private static final String SCHEDULE_SEQ_NAME = "ASM_SCHEDULES_SEQ";
57 private static final String EXECUTION_SEQ_NAME = "ASM_ACTION_EXECUTIONS_SEQ";
58 private static final String EXECUTION_CHAIN_SEQ_NAME = "ASM_CHAIN_EXECUTION_SEQ";
59 private final static String CREATE_DATA_PROC_REQUEST = "CreateDPRequest";
60 private final static String UPDATE_DATA_PROC_REQUEST_STATE = "UpdateDPRequestState";
61 private final static String CREATE_DPR_TARGET_ID = "CreateDPRTargetId";
62 private final static String GET_DATA_PROC_REQUESTS = "GetDataProcRequests";
63 private final static String CREATE_DPR_STATE_CHANGE = "CreateDPRStateChange";
64 private static final String UPDATE_EXECUTION_DURATION = "UpdateExecutionDuration";
65 private static final String UPDATE_EXECUTION_RESULT_CODE = "UpdateExecutionResultCode";
66 private static final String CREATE_CHAIN_EXECUTION_PARAMETER = "CreateChainExecutionParameter";
67 private static final String UPDATE_CHAIN_EXEC_PARAM_TO_NOT_ACTIVE = "UpdateChainExecutionParameterToNotActive";
68 private static final String UPDATE_OUTPUT_EXECUTION_PARAMETERS = "UpdateOutputExecutionParameters";
69 private static final String UPDATE_CHAIN_EXECUTION_STATUS = "UpdateChainExecutionStatus";
70 private static final String GET_ASM_CHAIN_EXECUTION = "GetASMChainExecution";
71 private static final String TRIGGER_GROUP = "TestGroup";
72
73 private static final String GET_PROCESSING_PARAMETERS_SET = "GetProcessingParametersSet";
74 private static final String GET_PROCESSING_PARAMETERS_SET_WITH_BATCH_UID = "GetProcessingParametersSetWithBatchUid";
75 private static final String GET_PROCESSING_PARAMETERS_SET_NO_BATCH_UID = "GetProcessingParametersSetNoBatchUid";
76 private static final String GET_ONE_PROCESSING_PARAMETERS_SET = "GetOneProcessingParametersSet";
77
78 private Log log = LogFactory.getLog(SpringASMExecutionsDAO.class);
79
80 @SuppressWarnings ("SpringJavaAutowiringInspection")
81 @Autowired
82 @Qualifier ("asmScheduler")
83 private SchedulerFactoryBean asmScheduler;
84
85// @SuppressWarnings ("SpringJavaAutowiringInspection")
86// @Autowired
87// @Qualifier ("asmOneShotScheduler")
88// private SchedulerFactoryBean asmOneShotScheduler;
89
90 @Autowired
91 protected SpringASMDAO asmDao;
92 @SuppressWarnings ("SpringJavaAutowiringInspection")
93 @Autowired
94 protected SpringSecurityDAO springSecurityDAO;
95
96 private QueryRepository getQueryRepository()
97 {
98 return PackageRepository.getInstance(SQL_PATH);
99 }
100
101
102 // @PostConstruct
103 @SuppressWarnings ("UnusedDeclaration")
104 private void init()
105 {
106 log.warn("Entering SpringASMExecutionsDAO#init() method...");
107 try
108 {
109 initASMSchedulers();
110 // processChainingOnDeploy();
111 }
112 catch (Exception e)
113 {
114 log.error(e);
115 }
116 log.warn("Exiting SpringASMExecutionsDAO#init() method...");
117 }
118
119 private void initASMSchedulers() throws SchedulerException
120 {
121 getCronScheduler().getListenerManager().addJobListener(new ASMJobListener());
122 getCronScheduler().getListenerManager().addTriggerListener(new ASMTriggerListener());
123 getCronScheduler().start();
124 log.warn("ASM Cron scheduler started...");
125
126 getOneShotScheduler().getListenerManager().addJobListener(new ASMJobListener());
127 getOneShotScheduler().getListenerManager().addTriggerListener(new ASMTriggerListener());
128 getOneShotScheduler().start();
129 log.warn("ASM One Shot (RAM) scheduler started...");
130 }
131
132 public void deleteAllTriggers()
133 {
134 try
135 {
136 getScheduler(true).clear();
137
138 }
139 catch (SchedulerException e)
140 {
141 log.error(e);
142 }
143 }
144
145 /* we use 2 queries in order to optimize the search */
146 public List<String> getValidationConfigSet(Long batchUid) throws SQLException
147 {
148 String query = batchUid == null ? GET_PROCESSING_PARAMETERS_SET_NO_BATCH_UID : GET_PROCESSING_PARAMETERS_SET_WITH_BATCH_UID;
149 String sql = getQueryRepository().getQuery(query);
150 return batchUid == null ? getDefaultQueryRunner().query(sql, ListHandler.STRING_HANDLER) : getDefaultQueryRunner().query(sql, ListHandler.STRING_HANDLER, batchUid);
151 }
152
153 public List<String> getOneValidationConfigSet(Long dcSpec) throws SQLException {
154 String sql = getQueryRepository().getQuery(GET_ONE_PROCESSING_PARAMETERS_SET);
155 return getDefaultQueryRunner().query(sql, ListHandler.STRING_HANDLER, dcSpec);
156 }
157
158
159
160 /* To be refactored urgently! */
161
162 @AppMessageSource (ASMMessageIds.SCHEDULE_CHAIN)
163 public ASMSchedule scheduleChain(Integer actionId, Date scheduleDate,
164 Map<Integer, List<ASMExecutionParameter>> parameters, Integer chainId,
165 Long chainExecutionId, Integer userId, Integer chainItemId, boolean isScheduled)
166 {
167 return scheduleChain(actionId, scheduleDate, parameters, chainId, null, chainExecutionId, userId, chainItemId, isScheduled, null);
168 }
169
170 @AppMessageSource (ASMMessageIds.SCHEDULE_CHAIN)
171 public ASMSchedule scheduleChain(Integer actionId, Date scheduleDate,
172 Map<Integer, List<ASMExecutionParameter>> parameters, Integer chainId, List<ASMchainParameterXML> chainExecTimeParams,
173 Long chainExecutionId, Integer userId, Integer chainItemId, boolean isScheduled, Integer chainScheduleId)
174 {
175 ASMSchedule schedule = scheduleChainHelper(actionId, scheduleDate, chainId);
176 schedule.setChainExecutionId(chainExecutionId);
177 schedule.setChainScheduleId(chainScheduleId);
178 schedule.setUserId(userId);
179 schedule.setChainItemId(chainItemId);
180 schedule.setChainExecTimeParams(chainExecTimeParams);
181 return innerScheduleChain(schedule, parameters, isScheduled);
182 }
183
184 private ASMSchedule scheduleChainHelper(Integer actionId, Date scheduleDate, Integer chainId)
185 {
186 if (scheduleDate == null)
187 {
188 scheduleDate = new Date();
189 }
190 ASMSchedule schedule = new ASMSchedule();
191 schedule.setActionId(actionId);
192 schedule.setStartDate(scheduleDate);
193 schedule.setChainId(chainId);
194 return schedule;
195 }
196
197 @AppMessageSource (ASMMessageIds.SCHEDULE_ACTION)
198 public ASMSchedule scheduleAction(Integer actionId,Integer userId, Date scheduleDate, List<ASMExecutionParameter> parameters,
199 Integer chainId, Long executionId)
200 {
201 ASMSchedule schedule = scheduleChainHelper(actionId, scheduleDate, chainId);
202 schedule.setUserId(userId);
203 schedule.setExecutionId(executionId);
204 return innerScheduleChain(schedule, parameters);
205 }
206
207 @AppMessageSource (ASMMessageIds.SCHEDULE_ACTION)
208 public ASMSchedule scheduleAction(Integer actionId, Date scheduleDate, List<ASMExecutionParameter> parameters,
209 Long executionId)
210 {
211 return scheduleAction(actionId, null, scheduleDate, parameters, null, executionId);
212 }
213
214 public ASMSchedule innerScheduleChain(ASMSchedule schedule, List<ASMExecutionParameter> overrideParams)
215 {
216 innerScheduleChainHelper(schedule);
217 createSchedule(schedule, overrideParams);
218 return schedule;
219 }
220
221 public ASMSchedule innerScheduleChain(ASMSchedule schedule,
222 Map<Integer, List<ASMExecutionParameter>> overrideParams, boolean isScheduled)
223 {
224 innerScheduleChainHelper(schedule);
225 createSchedule(schedule, overrideParams, isScheduled);
226 return schedule;
227 }
228
229 private void innerScheduleChainHelper(ASMSchedule schedule)
230 {
231 if (schedule.isScheduled())
232 {
233 checkSchedule(schedule, null);
234 }
235
236 schedule.setId(getScheduleId());
237
238 if (schedule.getUserId() == null)
239 schedule.setUserId(10001); // todo: if userId not set, assign system user - configure it in CFG
240
241 schedule.setCreateDate(new Date());
242 schedule.setChangeDate(schedule.getCreateDate());
243 }
244
245 // todo - refactor to use already defined methods
246 public List<ASMSchedule> getSchedulesByChainId(Integer chainId)
247 {
248 List<ASMSchedule> list = new ArrayList<ASMSchedule>();
249 try
250 {
251 Set<TriggerKey> groupKeys = getScheduler(true).getTriggerKeys(GroupMatcher.triggerGroupEquals(TRIGGER_GROUP));
252
253 Trigger.TriggerState triggerState;
254
255 for (TriggerKey key : groupKeys)
256 {
257 triggerState = getScheduler(true).getTriggerState(key);
258 if (triggerState == Trigger.TriggerState.NORMAL || triggerState == Trigger.TriggerState.PAUSED )
259 {
260 Trigger trigger = getScheduler(true).getTrigger(key);
261 ASMSchedule schedule = null;
262 if (trigger != null)
263 schedule = (ASMSchedule)trigger.getJobDataMap().get(ASMExecutionConstants.SCHEDULE);
264 if (schedule != null && chainId.equals(schedule.getChainId()))
265 list.add(schedule);
266 }
267 }
268 }
269 catch (SchedulerException e)
270 {
271 log.error("Error while getting chain schedule: ", e);
272 throw new RuntimeException(e);
273 }
274
275 return list;
276 }
277
278 /**
279 * to be called once on deploy
280 */
281 @Deprecated
282 private void processChainingOnDeploy()
283 {
284 // todo: check if sorting needed - extend executions tbl with changeDate column
285 List<ASMExecution> executionsList = asmDao
286 .getChainingQueuedExecutions(); // get executions with is_chaining_queued = 1
287
288 if (executionsList.size() > 0)
289 {
290 log.info("Number of Action Executions to be processed for chaining on deploy : " + executionsList.size());
291 }
292 else
293 {
294 log.info("No Action Executions detected to be processed for chaining on deploy!");
295 return;
296 }
297
298 for (ASMExecution execution : executionsList)
299 {
300 log.debug("Long job completed: " + execution);
301 longJobWasExecuted(execution, true);
302 }
303 }
304
305 /**
306 * add flag to denote whether status changed internally or externally
307 */
308 public void longJobWasExecuted(ASMExecution execution, boolean onDeploy)
309 {
310 try
311 {
312 log.info(String.format(
313 "Status of ASM execution: (Execution ID, Action Name, Chain ID) = (%s, %s, %s) changed.",
314 execution.getId(), execution.getActionName(),
315 execution.getChainId()));
316
317 ASMExecutionHelper.logExecutionEnd(execution, null );
318
319 if (execution.getChainId() == null)
320 {
321 log.info(String.format("Execution:(ID, Action Name) = (%s, %s) is not processed within a chain.",
322 execution.getId(), execution.getActionName()));
323 ASMAction action = execution.getAction();
324
325 // 2. Notification for single action execution where action service is marked as LONG process
326 if (action != null)
327 {
328 /* Notify */
329 ASMExecutionHelper.notifyExecutionStatus(execution, action, false);
330 }
331 }
332 else
333 {
334 log.info("Check for chained actions...");
335
336 List<ASMChainItem> chainedActions = asmDao.getASMChainItemChildren(execution.getChainItemId());
337 ASMChainExecutionStatusEnum chainExecutionStatus = getASMChainExecution(execution.getChainExecutionId())
338 .getExecutionStatusEnum();
339
340 if (chainedActions.size() == 0 && chainExecutionStatus != ASMChainExecutionStatusEnum.CANCELLED)
341 {
342 log.debug(String.format(
343 "No chained actions for ASM Action:(ID,Name)=(%s,%s) within chain:(ID, Name)=(%s,%s)",
344 execution.getActionId(), execution.getActionName(), execution.getChainId(),
345 execution.getChainName()));
346
347 //Since this is leaf of chain - get all siblings and check their status
348 List<ASMExecution> leafExecutions = getASMDao().getChainSubExecutionsByChainItemId(execution.getChainExecutionId(),
349 getASMDao().getASMChainItem(execution.getChainItemId()).getParentItemId());
350
351 //If status of any of them is Started - chain status should stay Started too
352 Boolean anyStartedStatus = ASMExecutionHelper.isThereAnyStartedStatus(leafExecutions);
353
354 //Otherwise update chain status
355 ASMChain chain = asmDao.getASMChain(execution.getChainId());
356 if (chain != null && !anyStartedStatus && getASMChainExecution(execution.getChainExecutionId()).getExecutionStatusEnum() != ASMChainExecutionStatusEnum.FAILED)
357 {
358 updateChainExecutionStatus(execution.getChainExecutionId(), execution.getExecutionStatusEnum() == ASMActionExecutionStatusEnum.COMPLETED ?
359 ASMChainExecutionStatusEnum.COMPLETED.getId() : ASMChainExecutionStatusEnum.FAILED.getId(), execution.getMessageId());
360
361 // 4. Notification for end of chain execution when last action service is defined as LONG process
362 ASMExecutionHelper.notifyExecutionStatus(execution, chain, false);
363 }
364 }
365 else if (chainExecutionStatus != ASMChainExecutionStatusEnum.PAUSED && chainExecutionStatus != ASMChainExecutionStatusEnum.CANCELLED)
366 {
367 // get schedule id of the chain
368 Integer chainScheduleId = execution.getChainScheduleId();
369
370 for (ASMChainItem item : chainedActions)
371 {
372 if (item.getDependencyTypeEnum() == execution.getExecutionStatusEnum())
373 {
374 Integer delay = item.getDelay() != null ? item.getDelay() : 0;
375 Integer itemId = item.getId();
376 Date start = new Date();
377 if (delay > 0)
378 start = ASMExecutionHelper.incrementDate(start, delay);
379
380 log.debug(String.format(
381 "Chained action{ID=%s} found within chain{ID=%s}. Creating one-time execution schedule...",
382 item.getActionId(), execution.getChainId()));
383
384 /** todo: differ -on-demand- and -scheduled- chain executions
385 * pick up param values from db *
386 * */
387 Map<Integer, List<ASMExecutionParameter>> parametersFromDB = new HashMap<Integer, List<ASMExecutionParameter>>();
388 List<ASMChainExecutionItemParameter> values = asmDao.getChainExecutionsParamValues(execution.getChainExecutionId(), itemId);
389 parametersFromDB.put(itemId, convertChainParametersToSimple(values));
390
391 scheduleChain(item.getActionId(), start, parametersFromDB, execution.getChainId(), null,
392 execution.getChainExecutionId(), execution.getUserId(), item.getId(),
393 execution.isScheduled(), chainScheduleId);
394 }
395 else
396 {
397 updateChainExecutionStatus(execution.getChainExecutionId(), execution.getExecutionStatusEnum().getId(), execution.getMessageId());
398 }
399 }
400 }
401 }
402 }
403 catch (Exception e)
404 {
405 log.error(e.getMessage(), e);
406 throw new RuntimeException(e);
407 }
408 finally
409 {
410 if (onDeploy)
411 {
412 markExecutionProcessedOnDeploy(execution);
413 }
414 }
415 }
416
417 public void markExecutionProcessedOnDeploy(ASMExecution execution)
418 {
419 String updateExecChangeSQL = getQueryRepository().getQuery(UPDATE_EXECUTION_IS_CHAINING_QUEUED);
420 getDefaultQueryRunner().update(updateExecChangeSQL, execution.getId());
421 log.debug(String.format("Action Execution with ID:%s marked as processed for chaining on deploy.",
422 execution.getId()));
423 }
424
425 public void updateResultCode(Long executionId, Integer exitCode)
426 {
427 String sqlUpdateResultCode = getQueryRepository().getQuery(UPDATE_EXECUTION_RESULT_CODE);
428 getDefaultQueryRunner().update(sqlUpdateResultCode, exitCode, executionId);
429 }
430
431 public void createASMExecutionLog(Long executionId, Integer logLevel, Integer messageId, String messageParams,
432 String message, String callStack)
433 {
434 String trimmedCallStack = callStack != null && callStack.length() > 2000 ? callStack.substring(0, 2000) : callStack;
435
436 //language=Oracle
437 String sql = "insert into tbl$asm_execution_logs(id, execution_id, log_level_id, message_id, message_params, message_str, call_stack) " +
438 "values (asm_execution_logs_seq.nextval, ?, ?, ?, ?, ?, ?)";
439 getDefaultQueryRunner().update(sql, executionId, logLevel, messageId, messageParams, message, trimmedCallStack);
440 }
441
442 public List<ASMExecutionParameter> getASMExecutionParameters(Integer actionVersionId)
443 {
444 ASMActionVersion actionVersion = getASMDao().getActionVersion(actionVersionId);
445
446 List<ASMServiceParameterValue> list = actionVersion.getParameterValues();
447
448 List<ASMExecutionParameter> params = new ArrayList<ASMExecutionParameter>();
449
450 for (ASMServiceParameterValue value : list)
451 {
452 ASMExecutionParameter param = new ASMExecutionParameter();
453 param.setName(value.getParameter().getName());
454 param.setParameterId(value.getParameterId());
455
456 if (value.getParameter().getTypeId().equals(ASMServiceParameterTypeEnum.IN) || value.getParameter()
457 .getTypeId().equals(ASMServiceParameterTypeEnum.INOUT))
458 {
459 param.setOldValue(value.getValue());
460 }
461 params.add(param);
462 }
463
464 return params;
465 }
466
467 public void ASMDPRConsumerMethod()
468 {
469 List<ASMDataProcRequest> dprs = getDataProcRequests();
470 if (!dprs.isEmpty())
471 {
472 for (ASMDataProcRequest dpr : dprs)
473 {
474 Integer serviceId = getServiceIdByProductionActionId(dpr.getActionId());
475
476 if (serviceId != null)
477 {
478 List<ASMExecutionParameter> params = getExecutionParameters(serviceId, dpr.getActionId());
479
480 if (!params.isEmpty())
481 {
482 /** dpr id is only used for dpr,
483 * used currently in mdm, and telecom projects
484 * assumption is made that in this case only one parameter will be used (dataProcessingRequest)
485 * */
486
487 log.debug("Setting value of DPR = " + dpr.getId());
488 params.get(0).setOldValue(dpr.getId());
489
490 scheduleDPRequest(dpr.getActionId(), null, params);
491 updateDataProcState(dpr, ASMDataProcRequestStateEnum.IN_PROGRESS);
492 }
493 }
494// else log.warn("DPRequest schedule stopped for action with ID: " + dpr.getActionId() + " because no production version exists!");
495 }
496 }
497 }
498
499 private ASMSchedule scheduleDPRequest(Integer actionId, Date scheduleDate, List<ASMExecutionParameter> parameters)
500 {
501 if (scheduleDate == null)
502 {
503 scheduleDate = new Date();
504 }
505
506 ASMSchedule schedule = new ASMSchedule();
507 schedule.setActionId(actionId);
508 schedule.setStartDate(scheduleDate);
509 checkSchedule(schedule, null);
510 schedule.setId(getScheduleId());
511 /** TODO: use sys user id from configuration */
512 schedule.setId(getScheduleId());
513 schedule.setUserId(10001);
514 schedule.setCreateDate(new Date());
515 schedule.setChangeDate(schedule.getCreateDate());
516 createSchedule(schedule, parameters);
517 return schedule;
518 }
519
520 public void checkSchedule(ASMSchedule schedule, Integer id)
521 {
522 int actionId;
523 if (schedule.getActionId() != null)
524 actionId = schedule.getActionId();
525 else
526 actionId = schedule.getActionVersion().getActionId();
527 List<ASMSchedule> list = getSchedules(actionId, null);
528 for (ASMSchedule sched : list)
529 if (!sched.getId().equals(id) &&
530 sched.getName() != null && schedule.getName() != null &&
531 sched.getName().trim().equals(schedule.getName().trim()))
532 throw createAppMessageException(ASMMessageIds.SUCH_SCHEDULE_NAME_EXISTS);
533 }
534
535 private List<ASMDataProcRequest> getDataProcRequests()
536 {
537 return getDefaultQueryRunner().query(
538 getQueryRepository().getQuery(GET_DATA_PROC_REQUESTS, "byStateId"),
539 ASMDataProcRequestProcessor.getListHandler(), 1); /**sent to processing only - changed for Bijeljina, so Open Only*/
540 }
541
542 private List<ASMExecutionParameter> getExecutionParameters(int serviceId, int actionId)
543 {
544 List<ASMServiceParameter> serviceParams = asmDao.getServiceParameters(serviceId, null);
545 ASMServiceParameterValue value;
546 List<ASMExecutionParameter> params = new ArrayList<ASMExecutionParameter>();
547 for (ASMServiceParameter p : serviceParams)
548 {
549 /** should be only one version with production state*/
550 value = asmDao.getParameterValue(
551 asmDao.getActionVersionsByStateEnum(actionId,
552 TSObjectVersionStateEnum.PRODUCTION, null).get(0).getId(), p.getId());
553 if (value != null)
554 {
555 ASMExecutionParameter param = new ASMExecutionParameter();
556 param.setParameterId(value.getParameterId());
557 if (value.getParameter().getTypeId().equals(ASMServiceParameterTypeEnum.IN)
558 || value.getParameter().getTypeId().equals(ASMServiceParameterTypeEnum.INOUT))
559 param.setOldValue(value.getValue());
560 params.add(param);
561 }
562 }
563 return params;
564 }
565
566 @AppMessageSource (ASMMessageIds.GET_SERVICE_ID)
567 public Integer getServiceIdByProductionActionId(Integer actionId)
568 {
569 ASMService service = asmDao.getServiceByProductionActionId(actionId);
570 if (service != null) return service.getId();
571
572// log.warn("No production version exists for action with ID: " + actionId);
573 return null;
574 }
575
576 @AppMessageSource (ASMMessageIds.GET_SCHEDULE_ID)
577 public int getScheduleId()
578 {
579 return getDefaultQueryRunner().getSequenceNextValue(SCHEDULE_SEQ_NAME);
580 }
581
582 @AppMessageSource (ASMMessageIds.GET_EXECUTION_ID)
583 public long getExecutionId()
584 {
585 return getDefaultQueryRunner().getSequenceNextValueLong(EXECUTION_SEQ_NAME);
586 }
587
588 @AppMessageSource (ASMMessageIds.GET_EXECUTION_ID)
589 public Long getChainExecutionId()
590 {
591 return getDefaultQueryRunner().getSequenceNextValueLong(EXECUTION_CHAIN_SEQ_NAME);
592 }
593
594 @AppMessageSource (ASMMessageIds.CREATE_DATA_PROC_REQUEST)
595 public ASMDataProcRequest createDataProcRequest(ASMDataProcRequest request)
596 {
597 log.debug("Creating data processing request: " + request.toString());
598 Object[] params = new Object[3];
599 params[0] = request.getActionId();
600 params[1] = request.getUserId();
601 params[2] = request.getNotice();
602 Object[] result = getDefaultQueryRunner().update(
603 getQueryRepository().getQuery(CREATE_DATA_PROC_REQUEST),
604 new Class[]{Integer.class, Date.class}, params);
605 return new ASMDataProcRequest((Long)result[0], request.getActionId(),
606 request.getState(), request.getUserId(),
607 (Date)result[1], (Date)result[2], request.getNotice());
608 }
609
610 @Transactional
611 @AppMessageSource (ASMMessageIds.UPDATE_DATA_PROC_STATE)
612 public void updateDataProcState(ASMDataProcRequest dpr, ASMDataProcRequestStateEnum state)
613 {
614 log.debug(String.format("Updating data processing request:%s state to %s",
615 dpr.getId(), state.getName()));
616 if (createDPRStateChange(dpr) < 0)
617 {
618 log.error("Cannot create DPR state change.");
619 throw new SQLRuntimeException(
620 new SQLException("Cannot create DPR state change."));
621 }
622 else
623 getDefaultQueryRunner().update(getQueryRepository().getQuery(UPDATE_DATA_PROC_REQUEST_STATE),
624 state.getId(), dpr.getId());
625 }
626
627 /**
628 * used only in updateDataProcState()
629 */
630 @SuppressWarnings ("unchecked")
631 private Integer createDPRStateChange(ASMDataProcRequest dpr)
632 {
633 log.debug(String.format("Creating data proc request state change"));
634 Object[] params = new Object[5];
635 params[0] = dpr.getId();
636 params[1] = dpr.getState().getId();
637 params[2] = 10001;
638 params[3] = dpr.getEffectiveStateDate();
639 params[4] = dpr.getNotice();
640
641 Object[] result = getDefaultQueryRunner().update(
642 getQueryRepository().getQuery(CREATE_DPR_STATE_CHANGE),
643 new Class[]{Integer.class}, params);
644 return result.length == 0 ? null : (Integer)result[0];
645 }
646
647 @AppMessageSource (ASMMessageIds.CREATE_DPR_TARGET_ID)
648 public void createDPRTargetId(long dprId, long... ids)
649 {
650 log.debug(String.format("Creating dpr target ids"));
651 Object[][] params = new Object[ids.length][2];
652 for (int i = 0; i < ids.length; i++)
653 {
654 params[i][0] = dprId;
655 params[i][1] = ids[i];
656 }
657 getDefaultQueryRunner().batch(
658 getQueryRepository().getQuery(CREATE_DPR_TARGET_ID), params);
659 }
660
661 @AppMessageSource (ASMMessageIds.CREATE_EXECUTION)
662 public ASMExecution createExecution(ASMExecution execution)
663 {
664 log.debug("Creating asm action execution : " + execution);
665// String sql = getQueryRepository().getQuery(CREATE_ACTION_EXECUTION_SQL);
666
667 //language=Oracle
668 String sql = "INSERT INTO tbl$asm_action_executions\n" +
669 " (id, action_id, action_version_id, message_id, user_id, schedule_id, result_code, scheduled_dt, start_dt, duration, is_scheduled, chain_id, status_id, \n" +
670 " chain_execution_id, chain_item_id, chain_schedule_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
671
672 getDefaultQueryRunner().update(
673 sql,
674 execution.getId(),
675 execution.getActionId(),
676 execution.getActionVersionId(),
677 execution.getMessageId(),
678 execution.getUserId(),
679 execution.getScheduleId(),
680 execution.getResultCode(),
681 execution.getScheduleDate(),
682 execution.getStartDate(),
683 execution.getDuration(),
684 execution.getScheduledId(),
685 execution.getChainId(),
686 execution.getStatusId(),
687 execution.getChainExecutionId(),
688 execution.getChainItemId(),
689 execution.getChainScheduleId()
690 );
691 return execution;
692 }
693
694 @AppMessageSource (ASMMessageIds.CREATE_EXECUTION)
695 public ASMExecution updateExecution(ASMExecution execution)
696 {
697 log.debug("Updating execution : " + execution);
698 String sql = getQueryRepository().getQuery(UPDATE_ACTION_EXECUTION_SQL);
699 getDefaultQueryRunner().update(
700 sql,
701 execution.getActionId(),
702 execution.getActionVersionId(),
703 execution.getMessageId(),
704 execution.getUserId(),
705 execution.getScheduleId(),
706 execution.getResultCode(),
707 execution.getScheduleDate(),
708 execution.getStartDate(),
709 execution.getDuration(),
710 execution.getScheduledId(),
711 execution.getChainId(),
712 execution.getStatusId(),
713 execution.getChainExecutionId(),
714 execution.getChainItemId(),
715 execution.getChainScheduleId(),
716 execution.getId()
717 );
718 return execution;
719 }
720
721 @AppMessageSource (ASMMessageIds.CREATE_EXECUTION)
722 public Long createChainExecution(ASMChainExecution chainExecution ) //Long id, Integer chainId, Integer statusId)
723 {
724 //language=Oracle
725 String sql = "insert into tbl$asm_chain_executions (id, chain_id, chain_execution_status_id, start_dt, is_scheduled, user_id, scheduled_dt) " +
726 "values (?, ?, ?, ?, ?, ?, ?) returning id into ?";
727
728 Object[] result = getDefaultQueryRunner().update(
729 sql,
730 new Class[]{Long.class},
731 chainExecution.getId(),
732 chainExecution.getChainId(),
733 chainExecution.getStatusId(),
734 chainExecution.getStartDate(),
735 chainExecution.isScheduled(),
736 chainExecution.getUserId(),
737 chainExecution.getScheduleDate()
738 );
739 return (Long)result[0];
740 }
741
742 /** temp: getting sql by query repository replaced with direct sql in order to avoid thread blocking (synchronized block in AbstractQueryRepository#getQuery)
743 during mass chain invocations which would otherwise result in execution delay
744 */
745 public void updateChainExecutionStatus(Long chainExecutionId, Integer newStatusId, Integer messageId)
746 {
747 log.info(String.format("Updating chain execution status [id:%s, newStatusId:%s]", chainExecutionId, newStatusId));
748// String sql = getQueryRepository().getQuery(UPDATE_CHAIN_EXECUTION_STATUS);
749 //language=Oracle
750 String sql = "update tbl$asm_chain_executions SET chain_execution_status_id = ?, message_id = ?, finish_dt = ? WHERE id = ?";
751
752 Date finishDate = null;
753 if (newStatusId != ASMChainExecutionStatusEnum.STARTED.getId() && newStatusId != ASMChainExecutionStatusEnum.PAUSED.getId())
754 finishDate = new Date();
755 getDefaultQueryRunner().update(
756 sql,
757 newStatusId,
758 messageId,
759 finishDate,
760 chainExecutionId
761 );
762 }
763
764 /** temp: getting sql by query repository replaced with direct sql in order to avoid thread blocking (synchronized block in AbstractQueryRepository#getQuery)
765 during mass chain invocations which would otherwise result in execution delay
766 */
767 public ASMChainExecution getASMChainExecution(Long id)
768 {
769// String sql = getQueryRepository().getQuery(GET_ASM_CHAIN_EXECUTION,"byId");
770 //language=Oracle
771 String sql = "SELECT * from ASM_CHAIN_EXECUTIONS WHERE id = ?";
772 return getDefaultQueryRunner().query(sql, ASMChainExecutionProcessor.getOneRowHandler(), id);
773 }
774
775 public List<ASMChainExecution> getASMChainExecutions(Integer chainId)
776 {
777 String sql = getQueryRepository().getQuery(GET_ASM_CHAIN_EXECUTION,"byChainId");
778 return getDefaultQueryRunner().query(sql, ASMChainExecutionProcessor.getListHandler(), chainId);
779 }
780
781 public void updateChainExecutionParamToNotActive(Long chain_execution_id, Integer chain_param_id)
782 {
783 String sql = getQueryRepository().getQuery(UPDATE_CHAIN_EXEC_PARAM_TO_NOT_ACTIVE);
784 getDefaultQueryRunner().update(sql, chain_execution_id, chain_param_id);
785 }
786
787 public void updateChainExecutionParamValue(ASMChainExecutionParamValue param)
788 {
789 String sql = "update TBL$ASM_CHAIN_EXEC_PRM_VALS SET old_value = ? where chain_execution_id = ? and chain_param_id = ?";
790 getDefaultQueryRunner().update(sql,
791 param.getParameter().getDomain().getDatatypeEnum().getStringFromObject(param.getOldValue()) ,
792 param.getChainExecutionId(),
793 param.getChainParamId());
794 }
795
796 public void updateOutputExecutionParams(Long execution_id, Integer paramId, String paramvalue)
797 {
798 String sql = getQueryRepository().getQuery(UPDATE_OUTPUT_EXECUTION_PARAMETERS);
799 getDefaultQueryRunner().update(sql, paramvalue, execution_id, paramId);
800 }
801
802 public void createChainExecutionParam(ASMChainExecutionParamValue parameter)
803 {
804// String sql = getQueryRepository().getQuery(CREATE_CHAIN_EXECUTION_PARAMETER);
805 //language=Oracle
806 String sql = "insert into TBL$ASM_CHAIN_EXEC_PRM_VALS (chain_param_id,chain_execution_id,old_value,large_value,updated_chain_item_id,is_active) values(?, ?, ?, ?, ?, ?)";
807
808 boolean isLargeTypeData = parameter.getOldValue() != null && parameter.getOldValue().toString()
809 .length() > ASMExecutionConstants.LARGE_DATA_BORDER;
810 getDefaultQueryRunner().update(sql,
811 parameter.getChainParamId(),
812 parameter.getChainExecutionId(),
813 isLargeTypeData ? null : parameter.getParameter().getDomain().getDatatypeEnum()
814 .getStringFromObject(parameter.getOldValue()),
815 isLargeTypeData ? parameter.getParameter().getDomain().getDatatypeEnum()
816 .getStringFromObject(parameter.getOldValue()) : null,
817 parameter.getItemId(),
818 parameter.getActive());
819 }
820
821 @AppMessageSource (ASMMessageIds.CREATE_EXECUTION_PARAMETER)
822 public void createExecutionParameter(ASMExecutionParameter parameter)
823 {
824 Object newValue = parameter.getNewValue();
825
826 if (newValue instanceof List)
827 newValue = newValue.toString();
828
829// String paramSql = getQueryRepository().getQuery(CREATE_EXECUTION_PARAMETER_SQL);
830// String largeDataSql = getQueryRepository().getQuery(CREATE_LARGE_EXECUTION_PARAMETER_SQL);
831
832 //language=Oracle
833 String sql = "INSERT INTO tbl$asm_execution_param_values (parameter_id, execution_id, old_value, new_value)\n" +
834 "VALUES (?, ?, ?, ?)";
835 //language=Oracle
836 String largeDataSql ="INSERT INTO tbl$asm_execution_param_values (parameter_id, execution_id, old_large_value, new_large_value)\n" +
837 " VALUES (?, ?, ?, ?)";
838
839 boolean isLargeTypeData = parameter.getOldValue() != null && parameter.getOldValue().toString().length() > ASMExecutionConstants.LARGE_DATA_BORDER;
840 getDefaultQueryRunner().update(isLargeTypeData ? largeDataSql : sql,
841 parameter.getParameterId(),
842 parameter.getExecutionId(),
843 parameter.getOldValue(),
844 newValue
845 );
846 }
847
848 @AppMessageSource (ASMMessageIds.CREATE_EXECUTION_PARAMETER)
849 public void updateExecutionParameter(ASMExecutionParameter parameter)
850 {
851 Object newValue = parameter.getNewValue();
852
853 if (newValue instanceof List)
854 newValue = newValue.toString();
855
856// String sql = getQueryRepository().getQuery(UPDATE_EXECUTION_PARAMETER_SQL);
857 //language=Oracle
858 String sql = "UPDATE tbl$asm_execution_param_values SET old_value = ?, new_value = ?, old_large_value = ?, new_large_value = ? WHERE parameter_id = ? AND execution_id = ?";
859
860 boolean isLargeTypeData = parameter.getOldValue() != null &&
861 parameter.getOldValue().toString().length() > ASMExecutionConstants.LARGE_DATA_BORDER;
862 getDefaultQueryRunner().update(sql,
863 isLargeTypeData ? null : parameter.getOldValue(),
864 isLargeTypeData ? null : newValue,
865 isLargeTypeData ? parameter.getOldValue() : null,
866 isLargeTypeData ? newValue : null,
867 parameter.getParameterId(),
868 parameter.getExecutionId()
869 );
870 }
871
872 @AppMessageSource (ASMMessageIds.MAKE_TRIGGER)
873 public Trigger makeTrigger(ASMSchedule schedule, List<ASMExecutionParameter> parameters)
874 {
875 Trigger trigger = makeTriggerHelper(schedule, false);
876 if (parameters != null)
877 trigger.getJobDataMap().put(ASMExecutionConstants.EXECUTION_PARAMS, parameters);
878
879 return trigger;
880 }
881
882 @AppMessageSource (ASMMessageIds.MAKE_TRIGGER)
883 public Trigger makeTrigger(ASMSchedule schedule, Map<Integer, List<ASMExecutionParameter>> parameters,
884 boolean isScheduled)
885 {
886 Trigger trigger = makeTriggerHelper(schedule, isScheduled);
887 if (!Util.isEmpty(parameters))
888 {
889 /** parameters list of the action currently being executed */
890 trigger.getJobDataMap()
891 .put(ASMExecutionConstants.EXECUTION_PARAMS, parameters.remove(schedule.getChainItemId()));
892
893 /** parameters map of chain actions which have not yet been processed */
894 trigger.getJobDataMap().put(ASMExecutionConstants.CHAIN_COMING_ACTIONS_PARAMS, parameters);
895 }
896 return trigger;
897 }
898
899 private Trigger makeTriggerHelper(ASMSchedule schedule, boolean isScheduled)
900 {
901 Trigger trigger;
902 final String triggerName = ASMExecutionConstants.TRIGGER_NAME_PREFIX + schedule.getId();
903 final TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, TRIGGER_GROUP);
904
905 schedule.trimRepetition();
906 if (!Util.isEmpty(schedule.getRepetition()))
907 {
908// log.debug("Creating CronTrigger");
909
910 CronExpression cronExpression;
911 try
912 {
913 cronExpression = new CronExpression(schedule.getRepetition());
914 }
915 catch (ParseException e)
916 {
917 throw createAppMessageException(ASMMessageIds.INVALID_CRON_EXPRESSION);
918 }
919
920 Date currentDate = new Date();
921 Date startTime = schedule.getStartDate();
922
923 if (startTime.before(currentDate))
924 startTime = currentDate;
925
926 trigger = TriggerBuilder.newTrigger()
927 .withIdentity(triggerKey)
928 .withSchedule(CronScheduleBuilder.cronSchedule(cronExpression).withMisfireHandlingInstructionDoNothing()) // change to do nothing
929 .startAt(startTime)
930 .build();
931
932 // TODO - make this configurable on UI
933 //trigger.setMisfireInstruction(CronTrigger.MISFIRE_INSTRUCTION_FIRE_ONCE_NOW);
934
935 schedule.setScheduled(true);
936 }
937 else
938 {
939 trigger = TriggerBuilder.newTrigger()
940 .startAt(schedule.getStartDate())
941 .withIdentity(triggerKey)
942 .withSchedule(SimpleScheduleBuilder.simpleSchedule().withMisfireHandlingInstructionFireNow())
943 .build();
944
945 schedule.setScheduled(isScheduled);
946
947 if (!schedule.isForChain())
948 {
949 Long execId = schedule.getExecutionId();
950 if (execId == null)
951 execId = getExecutionId();
952 trigger.getJobDataMap().put(ASMExecutionConstants.EXECUTION_ID, execId);
953 log.debug("trigger.getJobDataMap().put(ASMExecutionConstants.EXECUTION_ID,execId); - execId: " + execId);
954 schedule.setExecutionId(execId);
955 }
956 }
957
958 trigger = trigger.getTriggerBuilder()
959 .endAt(schedule.getStopDate())
960 .withDescription(schedule.getNotice())
961 .build();
962
963 /* try
964 {
965 getScheduler(schedule.isScheduled()).getListenerManager()
966 .addTriggerListenerMatcher(ASMTriggerListener.ASM_TRIGGER_LISTENER_NAME, KeyMatcher.keyEquals(triggerKey));
967 }
968 catch (SchedulerException e)
969 {
970 log.error("Error while adding trigger listener matcher: " + triggerKey, e);
971 }*/
972
973 trigger.getJobDataMap().put(ASMExecutionConstants.SCHEDULE, schedule);
974
975 log.warn(String.format("Thread: %s - Chain execution: %s - chain action [name: %s, itemId: %s] should have started at: %s but trigger created at: %s ",
976 Thread.currentThread().getName(), schedule.getChainExecutionId(), schedule.getAction(), schedule.getChainItemId(), schedule.getStartDate(), new Date()));
977
978 return trigger;
979 }
980
981 @AppMessageSource (ASMMessageIds.MAKE_JOB_DETAIL)
982 public JobDetail makeJobDetail(ASMSchedule schedule)
983 {
984 return JobBuilder.newJob(ASMActionJob.class)
985 .withIdentity(ASMExecutionConstants.JOB_NAME_PREFIX + schedule.getId(), TRIGGER_GROUP)
986 .build();
987 }
988
989 @AppMessageSource (ASMMessageIds.GET_SCHEDULER)
990 public Scheduler getScheduler(boolean isCronTrigger)
991 {
992// try
993// {
994// return StdSchedulerFactory.getDefaultScheduler();
995// }
996// catch (SchedulerException e)
997// {
998// log.error(e);
999// throw new RuntimeException(e);
1000// }
1001 return isCronTrigger ? getCronScheduler() : getOneShotScheduler();
1002 }
1003
1004 private Scheduler getOneShotScheduler()
1005 {
1006
1007 //return asmOneShotScheduler.getScheduler();
1008 return null;
1009 }
1010
1011 private Scheduler getCronScheduler()
1012 {
1013 return asmScheduler.getScheduler();
1014 }
1015
1016 public ASMSchedule getSchedule(int id)
1017 {
1018 Trigger trigger = getTrigger(id);
1019 if (trigger != null)
1020 return (ASMSchedule)trigger.getJobDataMap().get(ASMExecutionConstants.SCHEDULE);
1021 else
1022 return null;
1023 }
1024
1025 @AppMessageSource (ASMMessageIds.GET_SCHEDULES)
1026 public List<ASMSchedule> getSchedules(Integer actionId, Integer versionId)
1027 {
1028 List<ASMSchedule> list = new ArrayList<ASMSchedule>();
1029 try
1030 {
1031// String[] names = getScheduler().getTriggerNames(TRIGGER_GROUP);
1032 Set<TriggerKey> triggerKeySet = getScheduler(true).getTriggerKeys(GroupMatcher.triggerGroupEquals(TRIGGER_GROUP));
1033 Trigger.TriggerState triggerState;
1034 for (TriggerKey key : triggerKeySet)
1035 {
1036 triggerState = getScheduler(true).getTriggerState(key);
1037 if (triggerState == Trigger.TriggerState.NORMAL || triggerState == Trigger.TriggerState.PAUSED)
1038 {
1039 Trigger trigger = getScheduler(true).getTrigger(key);
1040 ASMSchedule schedule = null;
1041 if (trigger != null)
1042 schedule = (ASMSchedule)trigger.getJobDataMap().get(ASMExecutionConstants.SCHEDULE);
1043 if (schedule != null && isProperSchedule(schedule, actionId, versionId) && !schedule.isForChain())
1044 list.add(schedule);
1045 }
1046 }
1047 }
1048 catch (SchedulerException e)
1049 {
1050 log.error("Error while getting action schedule: ", e);
1051 throw new RuntimeException(e);
1052 }
1053 return list;
1054 }
1055
1056 @AppMessageSource (ASMMessageIds.GET_SCHEDULES)
1057 public List<ASMExtSchedule> getSchedules()
1058 {
1059 List<ASMExtSchedule> list = new ArrayList<ASMExtSchedule>();
1060 try
1061 {
1062 Trigger trigger;
1063// log.debug("Getting trigger names");
1064 Set<TriggerKey> triggerKeySet = getScheduler(true).getTriggerKeys(GroupMatcher.triggerGroupEquals(TRIGGER_GROUP));
1065 for (TriggerKey key : triggerKeySet)
1066 {
1067// log.debug("Trigger name = " + name);
1068 /*if (getScheduler()
1069 .getTriggerState(name, TRIGGER_GROUP) == Trigger.STATE_NORMAL) // only running schedules
1070 {*/
1071 try
1072 {
1073// log.debug("Getting Trigger for name = " + name);
1074 trigger = getScheduler(true).getTrigger(key);
1075 }
1076 catch (SchedulerException e)
1077 {
1078 log.error("Error while getting schedule: ",e);
1079 continue;
1080 }
1081
1082// log.debug("Creating asmExtSchedule for name = " + name);
1083 ASMExtSchedule asmExtSchedule = new ASMExtSchedule(trigger);
1084// log.debug("Setting trigger state = " + name);
1085// asmExtSchedule.setScheduleState(String.valueOf(Trigger.STATE_NORMAL));
1086
1087 //todo - only for test - add to refbook
1088 Trigger.TriggerState triggerState = getScheduler(true).getTriggerState(key);
1089// ASMTriggerStateEnum triggerStateEnum = ASMTriggerStateEnum.fromId(triggerStateInt);
1090
1091// if (triggerStateEnum != null)
1092 asmExtSchedule.setScheduleState(triggerState.toString());
1093// else asmExtSchedule.setScheduleState("Unknown");
1094
1095 list.add(asmExtSchedule);
1096 //}
1097 }
1098 }
1099 catch (SchedulerException e)
1100 {
1101 throw new RuntimeException(e);
1102 }
1103 catch (RuntimeException e)
1104 {
1105 log.error(e.getMessage(),e);
1106 }
1107 return list;
1108 }
1109
1110 public Trigger.TriggerState getTriggerState(Integer asmScheduleId)
1111 {
1112 String triggerName = ASMExecutionConstants.TRIGGER_NAME_PREFIX + asmScheduleId;
1113 try
1114 {
1115 return getScheduler(true).getTriggerState(TriggerKey.triggerKey(triggerName, TRIGGER_GROUP));
1116 }
1117 catch (SchedulerException e)
1118 {
1119 return Trigger.TriggerState.NONE; // todo: check this
1120 }
1121 }
1122
1123 private boolean isProperSchedule(ASMSchedule schedule, Integer actionId, Integer versionId)
1124 {
1125 if (versionId != null && actionId == null)
1126 return isProperScheduleForVersion(schedule, versionId);
1127 else if (versionId == null && actionId != null)
1128 return isProperScheduleForAction(schedule, actionId);
1129 else
1130 throw new RuntimeException();
1131 }
1132
1133 private boolean isProperScheduleForVersion(ASMSchedule schedule, int versionId)
1134 {
1135 return schedule.getActionId() == null && schedule.getActionVersionId() == versionId;
1136 }
1137
1138 private boolean isProperScheduleForAction(ASMSchedule schedule, int actionId)
1139 {
1140 List<Integer> ids = getIds(asmDao.getActionVersions(actionId, null));
1141 return schedule.getActionId() != null && schedule.getActionId() == actionId
1142 || schedule.getActionId() == null && ids.contains(schedule.getActionVersionId());
1143 }
1144
1145 private List<Integer> getIds(List<? extends GenIdObject<Integer>> list)
1146 {
1147 List<Integer> ids = new ArrayList<Integer>();
1148 for (GenIdObject<Integer> object : list)
1149 ids.add(object.getId());
1150 return ids;
1151 }
1152
1153 @AppMessageSource (ASMMessageIds.DELETE_SCHEDULE_DAO)
1154 public void deleteSchedule(ASMSchedule schedule)
1155 {
1156 Trigger trigger = getTrigger(schedule.getId());
1157 if (trigger != null)
1158 {
1159 deleteTrigger(trigger);
1160 }
1161 }
1162
1163 public void deleteSchedule(Integer scheduleId)
1164 {
1165 Trigger trigger = getTrigger(scheduleId);
1166 if (trigger != null)
1167 {
1168 deleteTrigger(trigger);
1169 }
1170 }
1171
1172 @AppMessageSource (ASMMessageIds.DELETE_TRIGGER)
1173 public void deleteTrigger(Trigger trigger)
1174 {
1175 try
1176 {
1177 /*
1178 getScheduler().unscheduleJob(trigger.getName(), TRIGGER_GROUP);
1179 getScheduler().deleteJob(trigger.getJobName(), trigger.getJobGroup());*/
1180
1181 getScheduler(true).unscheduleJob(trigger.getKey()); // TriggerKey.triggerKey(trigger.getJobKey().getName(),trigger.getJobKey().getGroup()));
1182 log.info("Trigger(schedule): " + trigger.getKey() + " deleted.");
1183 }
1184 catch (SchedulerException e)
1185 {
1186 throw new RuntimeException(e);
1187 }
1188 }
1189
1190 @AppMessageSource (ASMMessageIds.GET_TRIGGER)
1191 public Trigger getTrigger(int scheduleId)
1192 {
1193 final String triggerName = ASMExecutionConstants.TRIGGER_NAME_PREFIX + scheduleId;
1194 try
1195 {
1196 return getScheduler(true).getTrigger(TriggerKey.triggerKey(triggerName, TRIGGER_GROUP));
1197 }
1198 catch (SchedulerException e)
1199 {
1200 return null;
1201 }
1202 }
1203
1204 @AppMessageSource (ASMMessageIds.DEACTIVATE_SCHEDULE)
1205 public void deactivateSchedule(int scheduleId)
1206 {
1207 Trigger trigger = getTrigger(scheduleId);
1208 try
1209 {
1210 /*if (trigger instanceof CronTrigger)
1211 {
1212 CronTrigger cronTrigger = (CronTrigger)trigger;
1213 getScheduler().pauseTrigger(cronTrigger.getName(), cronTrigger
1214 .getGroup()); // scheduler.pauseJob(), sql: { UPDATE TBL$QRTZ_TRIGGERS SET TRIGGER_STATE = "PAUSED"}
1215 }*/
1216
1217 getScheduler(true).pauseTrigger(trigger.getKey());
1218 log.info("Trigger(schedule): " + trigger.getKey() + " paused.");
1219
1220 }
1221 catch (SchedulerException e)
1222 {
1223 throw new RuntimeException(e);
1224 }
1225 }
1226
1227 @AppMessageSource (ASMMessageIds.ACTIVATE_SCHEDULE)
1228 public void activateSchedule(int scheduleId)
1229 {
1230 Trigger trigger = getTrigger(scheduleId);
1231 try
1232 {
1233 if (trigger instanceof CronTrigger)
1234 {
1235 CronTriggerImpl cronTrigger = (CronTriggerImpl)trigger;
1236
1237 /* to prevent a misfire */
1238 cronTrigger.setNextFireTime(cronTrigger.getFireTimeAfter(new Date())); // todo: check if next fireTime is excluded from firing
1239 cronTrigger.setMisfireInstruction(CronTrigger.MISFIRE_INSTRUCTION_DO_NOTHING);
1240
1241 getScheduler(true).resumeTrigger(cronTrigger.getKey());
1242// getScheduler().rescheduleJob(cronTrigger.getKey(), cronTrigger);
1243 log.info("Trigger(schedule): " + trigger.getKey() + " resumed.");
1244 }
1245 }
1246 catch (SchedulerException e)
1247 {
1248 throw new RuntimeException(e);
1249 }
1250 }
1251
1252 private boolean isProperQueueEntity(Integer actionId, ASMSchedule schedule)
1253 {
1254 if (actionId == null)
1255 return true;
1256 else
1257 {
1258 int id;
1259 if (schedule.getActionId() != null)
1260 id = schedule.getActionId();
1261 else
1262 id = schedule.getActionVersion().getActionId();
1263 return id == actionId;
1264 }
1265 }
1266
1267 private boolean isProperChainQueueEntity(Integer actionId, ASMSchedule schedule)
1268 {
1269 if (actionId == null)
1270 return true;
1271 else
1272 {
1273 int id;
1274 if (schedule.getActionId() != null)
1275 id = schedule.getActionId();
1276 else
1277 id = schedule.getActionVersion().getActionId();
1278 return (id == actionId) && schedule.isForChain();
1279 }
1280 }
1281
1282 @AppMessageSource (ASMMessageIds.GET_EXCLUSIONS_FLAG_KEY)
1283 public String getExclusionFlagKey(JobExecutionContext context)
1284 {
1285 return "Flag" + getExecutionId(context);
1286 }
1287
1288 protected Long getExecutionId(JobExecutionContext context)
1289 {
1290 return (Long)context.get(ASMExecutionConstants.EXECUTION_ID);
1291 }
1292
1293 public ASMExecutionQueue getExecutionQueue(Date dueDate, int rowLimit, Integer actionId, OrderInfo orderInfo,
1294 Boolean isChainExecutionQueue)
1295 {
1296 List<ASMExecutionQueueEntity> result = new ArrayList<ASMExecutionQueueEntity>();
1297 ASMExecutionQueue queue = new ASMExecutionQueue();
1298 try
1299 {
1300 List list = getScheduler(true).getCurrentlyExecutingJobs();
1301 for (Object obj : list)
1302 {
1303 JobExecutionContext context = (JobExecutionContext)obj;
1304// log.debug(context.getScheduler().getContext().get(getExclusionFlagKey(context)));
1305 ASMSchedule schedule =
1306 (ASMSchedule)context.getTrigger().getJobDataMap().get(ASMExecutionConstants.SCHEDULE);
1307 // add logic for currently running chains in execution queue
1308 if (isChainExecutionQueue)
1309 {
1310 if (!isProperChainQueueEntity(actionId, schedule))
1311 continue;
1312 }
1313 else
1314 {
1315 if (!isProperQueueEntity(actionId, schedule))
1316 continue;
1317 }
1318
1319 ASMExecutionQueueEntity entity = new ASMExecutionQueueEntity();
1320 entity.setExecutionDate(context.getFireTime());
1321
1322// Object flag = context.getScheduler().getContext().get(context.getTrigger().getName());
1323 Object flag = context.getScheduler().getContext().get(getExclusionFlagKey(context));
1324 if (flag == null)
1325 entity.setStatusEnum(ASMExecutionQueueEntityStatusEnum.IN_PROGRESS);
1326 else
1327 entity.setStatusEnum(ASMExecutionQueueEntityStatusEnum.EXCLUSION_WAITING);
1328 entity.setScheduleId(schedule.getId());
1329 if (result.size() < rowLimit)
1330 result.add(entity);
1331 else
1332 {
1333 queue.setQueue(result);
1334 queue.setComplite(false);
1335 return queue;
1336 }
1337 }
1338
1339 SortedSet<ASMTriggerInfo> set = new TreeSet<ASMTriggerInfo>();
1340
1341 Date currentDate = new Date();
1342
1343 // create separate lists for action and chains
1344 List<ASMExecutionQueueEntity> chainResult = new ArrayList<ASMExecutionQueueEntity>();
1345 List<ASMExecutionQueueEntity> actionResult = new ArrayList<ASMExecutionQueueEntity>();
1346
1347// String[] triggerNames = getScheduler().getTriggerNames(TRIGGER_GROUP);
1348 Set<TriggerKey> triggerKeySet = getScheduler(true).getTriggerKeys(GroupMatcher.triggerGroupEquals(TRIGGER_GROUP));
1349 for (TriggerKey key : triggerKeySet)
1350 {
1351 if (getScheduler(true).getTriggerState(key) == Trigger.TriggerState.NORMAL)
1352 {
1353 Trigger trigger = getScheduler(true).getTrigger(key);
1354 ASMSchedule schedule = (ASMSchedule)trigger.getJobDataMap().get(ASMExecutionConstants.SCHEDULE);
1355 if (trigger.getNextFireTime() != null && isProperQueueEntity(actionId, schedule))
1356 set.add(new ASMTriggerInfo(trigger.getNextFireTime(), trigger));
1357 }
1358 }
1359 while (!set.isEmpty() && set.first().getFireTime().before(dueDate) && result.size() < rowLimit)
1360 {
1361 Trigger trigger = set.first().getTrigger();
1362
1363// if ((trigger instanceof CronTrigger && set.first().getFireTime().after(currentDate)) || trigger instanceof SimpleTrigger)
1364// {
1365 ASMSchedule schedule = (ASMSchedule)trigger.getJobDataMap().get(ASMExecutionConstants.SCHEDULE);
1366
1367 ASMExecutionQueueEntity entity = new ASMExecutionQueueEntity();
1368 entity.setScheduleId(schedule.getId());
1369 entity.setExecutionDate(set.first().getFireTime());
1370 if (set.first().getFireTime().after(currentDate))
1371 entity.setStatusEnum(ASMExecutionQueueEntityStatusEnum.SCHEDULED);
1372 else
1373 entity.setStatusEnum(ASMExecutionQueueEntityStatusEnum.QUEUED);
1374 // split entities into action and chain lists
1375 if (schedule.isForChain())
1376 {
1377 chainResult.add(entity);
1378 }
1379 else
1380 {
1381 actionResult.add(entity);
1382 }
1383
1384 Date date = set.first().getFireTime();
1385
1386 set.remove(set.first());
1387 if (trigger.getFireTimeAfter(date) != null)
1388 set.add(new ASMTriggerInfo(trigger.getFireTimeAfter(date), trigger));
1389 }
1390 // add only chain or action result list to the main result list which will be displayed, logic can be changed here if needed
1391 if (isChainExecutionQueue)
1392 {
1393 result.addAll(chainResult);
1394 }
1395 else
1396 {
1397 result.addAll(actionResult);
1398 }
1399 queue.setQueue(result);
1400 queue.setComplite(set.isEmpty() || !set.first().getFireTime().before(dueDate));
1401 }
1402 catch (SchedulerException e)
1403 {
1404 throw createAppMessageException(ASMMessageIds.SCHEDULER_EXCEPTION, e);
1405 }
1406
1407 OrderInfoComparator.sort(queue.getQueue(), orderInfo);
1408
1409 return queue;
1410 }
1411
1412 @AppMessageSource (ASMMessageIds.CREATE_SCHEDULE)
1413 public void createSchedule(ASMSchedule schedule, List<ASMExecutionParameter> overrideParams)
1414 {
1415 Trigger trigger = makeTrigger(schedule, overrideParams);
1416 createScheduleHelper(schedule, trigger);
1417 }
1418
1419 @AppMessageSource (ASMMessageIds.CREATE_SCHEDULE)
1420 public void createSchedule(ASMSchedule schedule, Map<Integer, List<ASMExecutionParameter>> actionsMap,
1421 boolean isScheduled)
1422 {
1423 Trigger trigger = makeTrigger(schedule, actionsMap, isScheduled);
1424 createScheduleHelper(schedule, trigger);
1425 }
1426
1427 private void createScheduleHelper(ASMSchedule schedule, Trigger trigger)
1428 {
1429 JobDetail jobDetail = makeJobDetail(schedule);
1430
1431 /* set chain execution id to the schedule so the chain caller can have it immediately */
1432 if (schedule.isForChain() && ASMExecutionHelper.isStartingChainItem(schedule.getChainId(), schedule.getChainItemId()))
1433 {
1434 Long chainExecId = schedule.getChainExecutionId();
1435 if (chainExecId == null)
1436 {
1437 chainExecId = getChainExecutionId();
1438 schedule.setChainExecutionId(chainExecId);
1439 }
1440
1441 jobDetail.getJobDataMap().put(ASMExecutionConstants.CHAIN_EXECUTION_ID, chainExecId);
1442 log.debug("jobDetail.getJobDataMap().put(ASMExecutionConstants.CHAIN_EXECUTION_ID, chainExecId); - chainExecId: " + chainExecId);
1443 }
1444
1445 try
1446 {
1447 /* getScheduler(schedule.isScheduled()).getListenerManager()
1448 .addJobListenerMatcher(ASMJobListener.LISTENER_NAME, KeyMatcher.keyEquals(jobDetail.getKey()) );*/
1449
1450 getScheduler(schedule.isScheduled()).scheduleJob(jobDetail, trigger);
1451 log.info("Scheduling trigger for: " + schedule);
1452 }
1453 catch (SchedulerException e)
1454 {
1455 log.error(e);
1456 throw createAppMessageException(ASMMessageIds.SCHEDULER_EXCEPTION, e);
1457 }
1458 }
1459
1460 public ASMSchedule updateSchedule(ASMSchedule schedule)
1461 {
1462 Trigger oldTrigger = getTrigger(schedule.getId());
1463
1464 // to handle case when trigger is expired
1465 if (oldTrigger != null)
1466 {
1467
1468 @SuppressWarnings ("unchecked")
1469 List<ASMExecutionParameter> parameters = (List<ASMExecutionParameter>)oldTrigger.getJobDataMap()
1470 .get(ASMExecutionConstants.EXECUTION_PARAMS);
1471
1472 schedule.setChangeDate(new Date());
1473 Trigger newTrigger = makeTrigger(schedule, parameters);
1474
1475 //todo: check this part
1476 TriggerBuilder newTriggerBuilder = newTrigger.getTriggerBuilder();
1477 newTrigger = newTriggerBuilder.
1478 forJob(oldTrigger.getJobKey())
1479 .build();
1480
1481 if (!newTrigger.getClass().equals(oldTrigger.getClass()))
1482 throw createAppMessageException(ASMMessageIds.CANNOT_CHANGE_SCHEDULE_TYPE);
1483 try
1484 {
1485 getScheduler(true).rescheduleJob(oldTrigger.getKey(), newTrigger);
1486 }
1487 catch (SchedulerException e)
1488 {
1489 log.error(e);
1490 throw createAppMessageException(ASMMessageIds.SCHEDULER_EXCEPTION, e);
1491 }
1492 }
1493 return schedule;
1494 }
1495
1496 /**
1497 * used only for reporting service scheduling
1498 */
1499 public void scheduleReportGeneration(Map<String, Object> parameters)
1500 {
1501 int serviceId = asmDao.getReportingServiceId();
1502 List<ASMServiceParameter> serviceParams = asmDao.getServiceParameters(serviceId, null);
1503 ASMServiceParameterValue value;
1504 List<ASMExecutionParameter> params = new ArrayList<ASMExecutionParameter>();
1505
1506 List<ASMAction> asmActions = asmDao.getActionsByServiceId(serviceId, null);
1507 int actionId = asmActions.get(0).getId();
1508
1509 for (ASMServiceParameter p : serviceParams)
1510 {
1511 /** should be only one version with production state*/
1512 value = asmDao.getParameterValue(
1513 asmDao.getActionVersionsByStateEnum(actionId,
1514 TSObjectVersionStateEnum.PRODUCTION, null).get(0).getId(), p.getId());
1515 if (value != null)
1516 {
1517 ASMExecutionParameter param = new ASMExecutionParameter();
1518 param.setParameterId(value.getParameterId());
1519 if (value.getParameter().getTypeId().equals(ASMServiceParameterTypeEnum.IN)
1520 || value.getParameter().getTypeId().equals(ASMServiceParameterTypeEnum.INOUT))
1521 param.setOldValue(parameters.get(value.getParameter().getName()));
1522 params.add(param);
1523 }
1524 }
1525
1526 ASMSchedule schedule = new ASMSchedule();
1527 schedule.setActionId(actionId);
1528 if (!parameters.containsKey("startDate"))
1529 {
1530 schedule.setStartDate(new Date());
1531 }
1532 else
1533 {
1534 schedule.setStartDate((Date)parameters.get("startDate"));
1535 }
1536 checkSchedule(schedule, null);
1537 schedule.setId(getScheduleId());
1538 /** TODO: use sys user id from configuration */
1539 schedule.setUserId(10001);
1540 schedule.setCreateDate(new Date());
1541 schedule.setChangeDate(schedule.getCreateDate());
1542 createSchedule(schedule, params);
1543 }
1544
1545 public List<ASMExecutionParameter> convertChainParametersToSimple(List<ASMChainExecutionItemParameter> values)
1546 {
1547 List<ASMExecutionParameter> executionParameters = new ArrayList<ASMExecutionParameter>();
1548 for (ASMChainExecutionItemParameter para : values)
1549 {
1550 ASMExecutionParameter copyParam = new ASMExecutionParameter();
1551 copyParam.setOldValue(para.getValue());
1552 copyParam.setParameterId(para.getParameterId());
1553 executionParameters.add(copyParam);
1554 }
1555 return executionParameters;
1556 }
1557
1558 public Long runASMAction(ASMActionXML asmActionXML)
1559 {
1560 try
1561 {
1562 Long execId = getExecutionId();
1563
1564 ASMAction asmAction = getASMActionFromXML(asmActionXML);
1565 List<ASMExecutionParameter> executionParameters = getASMExecutionParameters(asmAction.getProductionVersion().getId());
1566 ExecParamsMapperUtility.mapParameters(executionParameters, asmActionXML.getAsmParameterXMLList()); //getActionParameters());
1567
1568 scheduleAction(asmAction.getId(), asmActionXML.getUserId(), null, executionParameters, null, execId);
1569
1570 return execId;
1571 }
1572 catch (RuntimeException e)
1573 {
1574 log.error(e.getMessage(), e);
1575 throw e;
1576 }
1577 }
1578
1579 /*todo: refactor asm internal api (replace ASMchainParameterXML with ASMParameterXML or Map<String, Object>... */
1580 public Long runASMchain(ASMChainXML asmChainXML)
1581 {
1582 ASMChain chainObject = asmDao.getASMChainByUcode(asmChainXML.getUcode());
1583 if (chainObject == null)
1584 throw new IllegalArgumentException(String.format("ASMChain with <uCode>:%s does not exist!", asmChainXML.getUcode()));
1585
1586 List<ASMParameterXML> passedChainStringParams = asmChainXML.getChainParameters();
1587 List<ASMchainParameterXML> passedChainObjectParams = new ArrayList<ASMchainParameterXML>();
1588
1589 List<ASMChainParameter> chainNativeParams = asmDao.getChainParameters(chainObject.getId());
1590
1591 Map<String, String> passedChainStringParamsMap = ExecParamsMapperUtility.xmlParamListToMap(passedChainStringParams);
1592
1593 for (ASMChainParameter chainNativeParam : chainNativeParams)
1594 {
1595 if (passedChainStringParamsMap.containsKey(chainNativeParam.getName()))
1596 {
1597 String passedChainParamValString = passedChainStringParamsMap.get(chainNativeParam.getName());
1598 Object passedObject;
1599 try
1600 {
1601 passedObject = chainNativeParam.getDomain().getDatatypeEnum().getObjectFromString(passedChainParamValString);
1602 passedChainObjectParams.add(new ASMchainParameterXML(chainNativeParam.getName(), passedObject));
1603 }
1604 catch (Exception e)
1605 {
1606 throw new IllegalArgumentException(String.format("Wrong chain param value: (param name, value) = (%s, %s)", chainNativeParam.getName(), passedChainParamValString));
1607 }
1608 }
1609 }
1610 return runASMchain(asmChainXML, passedChainObjectParams);
1611 }
1612
1613 /* called through asm internal api from mdm/fam- initial implementation (hard to change in prod) */
1614 public Long runASMchain(ASMChainXML asmChainXML, List<ASMchainParameterXML> chainExecTimeParams)
1615 {
1616 log.info("Chain with uCode: " + asmChainXML.getUcode() + " is being invoked from another module...");
1617 try
1618 {
1619 ASMChain asmChain = getASMChainFromXML(asmChainXML);
1620 Long chainExecutionId = getChainExecutionId();
1621
1622 /** default param values */
1623 Map<Integer, List<ASMExecutionParameter>> chainItemsParamsMap = new HashMap<Integer, List<ASMExecutionParameter>>();
1624 List<Integer> chainItemsIDs = new ArrayList<Integer>();
1625 List<ASMChainItem> asmChainItems = asmDao.getChainItems(asmChain.getId());
1626
1627 for (ASMChainItem chainItem : asmChainItems)
1628 {
1629 ASMAction action = chainItem.getAsmAction();
1630 chainItemsIDs.add(chainItem.getId());
1631 List<ASMExecutionParameter> itemParams = getASMExecutionParameters(action.getProductionVersion().getId());
1632 chainItemsParamsMap.put(chainItem.getId(), itemParams);
1633 }
1634
1635 Map<Integer, List<ASMParameterXML>> xmlParamsMap = new HashMap<Integer, List<ASMParameterXML>>();
1636 List<ASMChainItemXML> asmChainItemXMLs = asmChainXML.getChainItems();
1637
1638 for (ASMChainItemXML asmChainItemXML : asmChainItemXMLs)
1639 {
1640 ASMChainItem actionItem = asmDao.getChainItemByChainIdAndUcode(asmChain.getId(), asmChainItemXML.getUcode());
1641 xmlParamsMap.put(actionItem.getId(), asmChainItemXML.getItemParameters());
1642 }
1643
1644 /** override default chain actions params with ones passed */
1645 for (Integer id : chainItemsIDs)
1646 {
1647 ExecParamsMapperUtility.mapParameters(chainItemsParamsMap.get(id), xmlParamsMap.get(id));
1648 }
1649
1650 scheduleChain(asmChain.getStartingAction().getId(), null, chainItemsParamsMap, asmChain.getId(),
1651 chainExecTimeParams, chainExecutionId, asmChainXML.getUserId(), asmChain.getStartingItemId(), false, null);
1652
1653 return chainExecutionId;
1654 }
1655 catch (RuntimeException e)
1656 {
1657 log.error(e.getMessage(), e);
1658 throw e;
1659 }
1660 }
1661
1662 private void validateUser(Integer userId)
1663 {
1664 if (userId == null)
1665 throw new IllegalArgumentException("<userId> param is required!");
1666 User user = springSecurityDAO.getUser(userId);
1667 if (user == null)
1668 throw new IllegalArgumentException("User with id: " + userId + " does not exist!");
1669 }
1670
1671 private ASMAction getASMActionFromXML(ASMActionXML actionXML)
1672 {
1673 validateUser(actionXML.getUserId());
1674 ASMAction asmAction = asmDao.getActionByUcode(actionXML.getUcode());
1675 if (asmAction == null)
1676 throw new IllegalArgumentException(String.format("ASMAction with <uCode>:%s does not exist!", actionXML.getUcode()));
1677 return asmAction;
1678 }
1679
1680 private ASMChain getASMChainFromXML(ASMChainXML chainXML)
1681 {
1682 validateUser(chainXML.getUserId());
1683 ASMChain asmChain = asmDao.getASMChainByUcode(chainXML.getUcode());
1684 if (asmChain == null)
1685 throw new IllegalArgumentException(String.format("ASMChain with <uCode>:%s does not exist!", chainXML.getUcode()));
1686 return asmChain;
1687 }
1688
1689 public SpringASMDAO getASMDao()
1690 {
1691 return asmDao;
1692 }
1693
1694 class ASMDPRConsumer extends TimerTask
1695 {
1696 @Override
1697 public void run()
1698 {
1699 ASMDPRConsumerMethod();
1700 }
1701 }
1702
1703 private class ASMTriggerInfo implements Comparable<ASMTriggerInfo>
1704 {
1705 private Date fireTime;
1706 private Trigger trigger;
1707
1708 private ASMTriggerInfo(Date fireTime, Trigger trigger)
1709 {
1710 this.fireTime = fireTime;
1711 this.trigger = trigger;
1712 }
1713
1714 @Override
1715 public int compareTo(ASMTriggerInfo o)
1716 {
1717 if (fireTime.compareTo(o.getFireTime()) != 0)
1718 return fireTime.compareTo(o.getFireTime());
1719 else
1720 return trigger.getKey().getName().compareTo(o.getTrigger().getKey().getName());
1721 }
1722
1723 public Date getFireTime()
1724 {
1725 return fireTime;
1726 }
1727
1728 @SuppressWarnings ("unused")
1729 public void setFireTime(Date fireTime)
1730 {
1731 this.fireTime = fireTime;
1732 }
1733
1734 public Trigger getTrigger()
1735 {
1736 return trigger;
1737 }
1738
1739 @SuppressWarnings ("unused")
1740 public void setTrigger(Trigger trigger)
1741 {
1742 this.trigger = trigger;
1743 }
1744 }
1745}