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