1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.opencastproject.workflow.api;
23
24 import java.util.Collections;
25 import java.util.Date;
26 import java.util.Map;
27 import java.util.Objects;
28 import java.util.Set;
29 import java.util.TreeMap;
30
31 import javax.persistence.Access;
32 import javax.persistence.AccessType;
33 import javax.persistence.CollectionTable;
34 import javax.persistence.Column;
35 import javax.persistence.ElementCollection;
36 import javax.persistence.Entity;
37 import javax.persistence.FetchType;
38 import javax.persistence.GeneratedValue;
39 import javax.persistence.Id;
40 import javax.persistence.Index;
41 import javax.persistence.JoinColumn;
42 import javax.persistence.Lob;
43 import javax.persistence.ManyToOne;
44 import javax.persistence.MapKeyColumn;
45 import javax.persistence.Table;
46 import javax.persistence.Temporal;
47 import javax.persistence.TemporalType;
48
49
50
51
52 @Entity(name = "WorkflowOperationInstance")
53 @Access(AccessType.FIELD)
54 @Table(name = "oc_workflow_operation", indexes = {
55 @Index(name = "IX_oc_workflow_operation_workflow_id", columnList = ("workflow_id"))})
56 public class WorkflowOperationInstance implements Configurable {
57 public enum OperationState {
58 INSTANTIATED, RUNNING, PAUSED, SUCCEEDED, FAILED, SKIPPED, RETRY
59 }
60
61 @Id
62 @GeneratedValue
63 @Column(name = "id")
64 private Long id;
65
66 @Column(name = "template")
67 protected String template;
68
69 @Column(name = "job")
70 protected Long jobId;
71
72 @Column(name = "state")
73 protected OperationState state;
74
75 @Column(name = "description")
76 @Lob
77 protected String description;
78
79 @ElementCollection
80 @CollectionTable(
81 name = "oc_workflow_operation_configuration",
82 joinColumns = @JoinColumn(name = "workflow_operation_id"),
83 indexes = {
84 @Index(name = "IX_oc_workflow_operation_configuration_workflow_operation_id", columnList = ("workflow_operation_id")),
85 }
86 )
87 @MapKeyColumn(name = "configuration_key", nullable = false)
88 @Lob
89 @Column(name = "configuration_value")
90 protected Map<String, String> configurations;
91
92 @Column(name = "fail_on_error")
93 protected boolean failOnError;
94
95 @Column(name = "if_condition")
96 @Lob
97 protected String executeCondition;
98
99 @Column(name = "exception_handler_workflow")
100 protected String exceptionHandlingWorkflow;
101
102 @Column(name = "abortable")
103 protected Boolean abortable;
104
105 @Column(name = "continuable")
106 protected Boolean continuable;
107
108 @Column(name = "started")
109 @Temporal(TemporalType.TIMESTAMP)
110 protected Date dateStarted;
111
112 @Column(name = "completed")
113 @Temporal(TemporalType.TIMESTAMP)
114 protected Date dateCompleted;
115
116 @Column(name = "time_in_queue")
117 protected Long timeInQueue;
118
119 @Column(name = "max_attempts")
120 protected int maxAttempts;
121
122 @Column(name = "failed_attempts")
123 protected int failedAttempts;
124
125 @Column(name = "execution_host")
126 protected String executionHost;
127
128 @Column(name = "retry_strategy", length = 128)
129 protected RetryStrategy retryStrategy;
130
131 @ManyToOne(fetch = FetchType.LAZY)
132 @JoinColumn(name = "workflow_id", nullable = false)
133 private WorkflowInstance instance;
134
135
136
137
138 public WorkflowOperationInstance() {
139 this.maxAttempts = 1;
140 this.retryStrategy = RetryStrategy.NONE;
141 }
142
143
144
145
146
147
148
149 public WorkflowOperationInstance(WorkflowOperationDefinition def) {
150 this();
151 setTemplate(def.getId());
152 setState(OperationState.INSTANTIATED);
153 setDescription(def.getDescription());
154 setMaxAttempts(def.getMaxAttempts());
155 setFailOnError(def.isFailWorkflowOnException());
156 setExceptionHandlingWorkflow(def.getExceptionHandlingWorkflow());
157 setExecutionCondition(def.getExecutionCondition());
158 setRetryStrategy(def.getRetryStrategy());
159 Set<String> defConfigs = def.getConfigurationKeys();
160 this.configurations = new TreeMap<>();
161 if (defConfigs != null) {
162 for (String key : defConfigs) {
163 configurations.put(key, def.getConfiguration(key));
164 }
165 }
166
167 if ((retryStrategy == RetryStrategy.RETRY || retryStrategy == RetryStrategy.HOLD) && maxAttempts < 2) {
168 maxAttempts = 2;
169 }
170 }
171
172
173
174
175
176
177
178
179
180 public WorkflowOperationInstance(String id, OperationState state) {
181 this();
182 setTemplate(id);
183 setState(state);
184 }
185
186 public WorkflowOperationInstance(
187 String template,
188 Long jobId,
189 OperationState state,
190 String description,
191 Map<String, String> configurations,
192 boolean failOnError,
193 String executeCondition,
194 String exceptionHandlingWorkflow,
195 Boolean abortable,
196 Boolean continuable,
197 Date dateStarted,
198 Date dateCompleted,
199 Long timeInQueue,
200 int maxAttempts,
201 int failedAttempts,
202 String executionHost,
203 RetryStrategy retryStrategy) {
204 this.template = template;
205 this.jobId = jobId;
206 this.state = state;
207 this.description = description;
208 this.configurations = configurations;
209 this.failOnError = failOnError;
210 this.executeCondition = executeCondition;
211 this.exceptionHandlingWorkflow = exceptionHandlingWorkflow;
212 this.abortable = abortable;
213 this.continuable = continuable;
214 this.dateStarted = dateStarted;
215 this.dateCompleted = dateCompleted;
216 this.timeInQueue = timeInQueue;
217 this.maxAttempts = maxAttempts;
218 this.failedAttempts = failedAttempts;
219 this.executionHost = executionHost;
220 this.retryStrategy = retryStrategy;
221 }
222
223
224
225
226
227
228
229 public void setTemplate(String template) {
230 this.template = template;
231 }
232
233
234
235
236
237
238 public String getTemplate() {
239 return template;
240 }
241
242
243
244
245
246
247 public Long getId() {
248 return jobId;
249 }
250
251
252
253
254
255
256
257 public void setId(Long jobId) {
258 this.jobId = jobId;
259 }
260
261
262
263
264
265
266 public String getDescription() {
267 return description;
268 }
269
270
271
272
273
274
275 public void setDescription(String description) {
276 this.description = description;
277 }
278
279
280
281
282 public OperationState getState() {
283 return state;
284 }
285
286
287
288
289
290
291
292 public void setState(OperationState state) {
293 Date now = new Date();
294 if (OperationState.RUNNING.equals(state)) {
295 this.dateStarted = now;
296 } else if (OperationState.FAILED.equals(state) || OperationState.SUCCEEDED.equals(state)) {
297 this.dateCompleted = now;
298 }
299 this.state = state;
300 }
301
302
303
304
305
306
307
308 public Map<String, String> getConfigurations() {
309 return configurations;
310 }
311
312
313
314
315
316
317 @Override
318 public String getConfiguration(String key) {
319 if (key == null || configurations == null)
320 return null;
321 return configurations.get(key);
322 }
323
324
325
326
327
328
329 @Override
330 public void removeConfiguration(String key) {
331 if (key == null || configurations == null)
332 return;
333 configurations.remove(key);
334 }
335
336
337
338
339
340
341 @Override
342 public void setConfiguration(String key, String value) {
343 if (key == null)
344 return;
345 if (configurations == null)
346 configurations = new TreeMap<>();
347
348 configurations.put(key, value);
349 }
350
351
352
353
354
355
356 @Override
357 public Set<String> getConfigurationKeys() {
358 if (configurations == null) {
359 return Collections.emptySet();
360 }
361 return configurations.keySet();
362 }
363
364
365 public String getExceptionHandlingWorkflow() {
366 return exceptionHandlingWorkflow;
367 }
368
369 public void setExceptionHandlingWorkflow(String exceptionHandlingWorkflow) {
370 this.exceptionHandlingWorkflow = exceptionHandlingWorkflow;
371 }
372
373
374
375
376
377 public boolean isFailOnError() {
378 return failOnError;
379 }
380
381 public void setFailOnError(boolean failOnError) {
382 this.failOnError = failOnError;
383 }
384
385
386
387
388 public Date getDateStarted() {
389 return dateStarted;
390 }
391
392
393 public Long getTimeInQueue() {
394 return timeInQueue;
395 }
396
397 public void setTimeInQueue(long timeInQueue) {
398 this.timeInQueue = timeInQueue;
399 }
400
401
402 public Date getDateCompleted() {
403 return dateCompleted;
404 }
405
406
407
408
409
410
411
412
413
414
415
416
417
418 public String getExecutionCondition() {
419 return executeCondition;
420 }
421
422 public void setExecutionCondition(String condition) {
423 this.executeCondition = condition;
424 }
425
426
427
428
429
430
431
432 public Boolean isContinuable() {
433 return continuable;
434 }
435
436
437
438
439
440
441
442
443 public void setContinuable(Boolean continuable) {
444 this.continuable = continuable;
445 }
446
447
448
449
450
451
452
453
454
455 public Boolean isAbortable() {
456 return abortable;
457 }
458
459
460
461
462
463
464
465 public void setAbortable(Boolean abortable) {
466 this.abortable = abortable;
467 }
468
469
470
471
472
473
474 public RetryStrategy getRetryStrategy() {
475 return retryStrategy;
476 }
477
478 private void setRetryStrategy(RetryStrategy retryStrategy) {
479 this.retryStrategy = retryStrategy;
480 }
481
482
483
484
485
486
487 public int getMaxAttempts() {
488 return maxAttempts;
489 }
490
491
492
493
494
495
496
497 private void setMaxAttempts(int maxAttempts) {
498 if (maxAttempts < 1) {
499 throw new IllegalArgumentException("maxAttempts must be >=1");
500 }
501 this.maxAttempts = maxAttempts;
502 }
503
504
505
506
507
508
509 public int getFailedAttempts() {
510 return failedAttempts;
511 }
512
513 public void setFailedAttempts(int failedAttempts) {
514 this.failedAttempts = failedAttempts;
515 }
516
517
518
519
520
521
522 public String getExecutionHost() {
523 return executionHost;
524 }
525
526
527
528
529
530
531
532 public void setExecutionHost(String executionHost) {
533 this.executionHost = executionHost;
534 }
535
536 public WorkflowInstance getWorkflowInstance() {
537 return instance;
538 }
539
540 public void setWorkflowInstance(WorkflowInstance instance) {
541 this.instance = instance;
542 }
543
544 @Override
545 public int hashCode() {
546 return Long.valueOf(id).hashCode();
547 }
548
549 @Override
550 public boolean equals(Object o) {
551 if (this == o) {
552 return true;
553 }
554 if (o instanceof WorkflowOperationInstance) {
555 WorkflowOperationInstance other = (WorkflowOperationInstance) o;
556 return other.getTemplate().equals(this.getTemplate()) && Objects.equals(other.id, this.id);
557 }
558 return false;
559 }
560
561
562
563
564
565
566 @Override
567 public String toString() {
568 return "operation:'" + template + ", state:'" + this.state + "'";
569 }
570 }