1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package org.imixs.workflow;
29
30 import java.text.DateFormat;
31 import java.util.Date;
32 import java.util.List;
33 import java.util.Vector;
34 import java.util.logging.Logger;
35
36 import org.imixs.workflow.exceptions.ModelException;
37 import org.imixs.workflow.exceptions.PluginException;
38 import org.imixs.workflow.exceptions.ProcessingErrorException;
39
40
41
42
43
44
45
46
47
48
49
50
51 public class WorkflowKernel {
52
53
54 public static final int LOG_LEVEL_SEVERE = 0;
55 public static final int LOG_LEVEL_WARNING = 1;
56 public static final int LOG_LEVEL_FINE = 2;
57
58
59 private Vector vectorPluginsClassNames = null;
60 private Vector vectorPlugins = null;
61 private WorkflowContext ctx = null;
62 private ItemCollection documentContext = null;
63 private ItemCollection documentActivity = null;
64
65 private Vector vectorEdgeHistory = new Vector();
66
67 private static Logger logger = Logger.getLogger("org.imixs.workflow");
68
69
70
71
72 public WorkflowKernel(WorkflowContext actx) {
73 ctx = actx;
74
75 vectorPluginsClassNames = new Vector();
76 vectorPlugins = new Vector();
77 }
78
79 public void registerPlugin(String aClassName) {
80 vectorPluginsClassNames.addElement(aClassName);
81 if (ctx.getLogLevel() == LOG_LEVEL_FINE)
82 logger.info("[WorkflowKernel] register Plugin: " + aClassName);
83 }
84
85
86
87
88
89
90
91
92 public void process(ItemCollection document)
93 throws ProcessingErrorException {
94
95 vectorEdgeHistory = new Vector();
96 documentContext = document;
97
98
99 if (document == null)
100 throw new ProcessingErrorException(
101 "[WorkflowKernel] processing error: document==null");
102
103
104 if (document.getItemValueInteger("$processid") <= 0)
105 throw new ProcessingErrorException(
106 "[WorkflowKernel] processing error: $processid undefined ("
107 + document.getItemValueInteger("$processid") + ")");
108
109
110
111 if (document.getItemValueInteger("$activityid") <= 0)
112 throw new ProcessingErrorException(
113 "[WorkflowKernel] processing error: $activityid undefined ("
114 + document.getItemValueInteger("$activityid") + ")");
115
116
117 if ("".equals(documentContext.getItemValueString("$UniqueID"))) {
118
119 documentContext.replaceItemValue("$UniqueID", generateUniqueID());
120 }
121
122
123 String msg = "[WorkflowKernel] processing="
124 + documentContext.getItemValueString("$UniqueID")
125 + ", $modelversion="
126 + document.getItemValueString("$modelversion")
127 + ", $processid=" + document.getItemValueInteger("$processid")
128 + ", $activityid="
129 + document.getItemValueInteger("$activityid");
130
131 if (ctx.getLogLevel() == LOG_LEVEL_FINE)
132 msg += ", Log-Level=FINE ";
133 else if (ctx.getLogLevel() == LOG_LEVEL_WARNING)
134 msg += ", Log-Level=WARNING ";
135 else
136 msg += ", Log-Level=SEVERE ";
137
138 logger.info(msg);
139
140
141 if ("".equals(documentContext.getItemValueString("$WorkItemID"))) {
142 documentContext.replaceItemValue("$WorkItemID", generateUniqueID());
143 }
144
145
146 while (hasMoreActivities())
147 processActivity();
148
149 }
150
151
152
153
154
155
156
157 private boolean hasMoreActivities() {
158 int integerID;
159
160
161 integerID = documentContext.getItemValueInteger("$activityid");
162
163 if ((integerID > 0))
164 return true;
165 else {
166
167 List v = documentContext.getItemValue("$activityidlist");
168
169
170 while (v.indexOf(Integer.valueOf(0)) > -1) {
171 v.remove(v.indexOf(Integer.valueOf(0)));
172 }
173
174
175 if (v.size() > 0) {
176
177 int iNextID = 0;
178 Object oA = v.get(0);
179 if (oA instanceof Integer)
180 iNextID = ((Integer) oA).intValue();
181 if (oA instanceof Double)
182 iNextID = ((Double) oA).intValue();
183
184 if (iNextID > 0) {
185
186 if (ctx.getLogLevel() == LOG_LEVEL_FINE)
187 logger.info("[WorkflowKernel] loading next activityID from $activityidlist="
188 + iNextID);
189 v.remove(0);
190
191 documentContext.replaceItemValue("$activityid",
192 Integer.valueOf(iNextID));
193 documentContext.replaceItemValue("$activityidlist", v);
194 return true;
195 }
196 }
197
198 return false;
199 }
200
201 }
202
203
204
205
206
207
208
209
210
211
212
213 public static String generateUniqueID() {
214 String sIDPart1 = Long.toHexString(System.currentTimeMillis());
215 double d = Math.random() * 900000000;
216 int i = new Double(d).intValue();
217 String sIDPart2 = Integer.toHexString(i);
218 String id = sIDPart1 + "-" + sIDPart2;
219
220 return id;
221 }
222
223
224
225
226
227
228
229
230
231
232 private void processActivity() throws ProcessingErrorException {
233
234 loadActivity();
235
236
237 loadPlugins();
238 int iStatus = runPlugins();
239 closePlugins(iStatus);
240
241 if (iStatus == Plugin.PLUGIN_ERROR) {
242 throw new ProcessingErrorException(
243 "[WorkflowKernel] Error in Plugin detected.");
244 }
245
246 writeLog();
247
248
249 vectorEdgeHistory.addElement(documentActivity
250 .getItemValueInteger("numprocessid")
251 + "."
252 + documentActivity.getItemValueInteger("numactivityid"));
253
254
255 int iNewProcessID = documentActivity
256 .getItemValueInteger("numnextprocessid");
257 if (ctx.getLogLevel() == LOG_LEVEL_FINE)
258 logger.info("[WorkflowKernel] next $processid=" + iNewProcessID
259 + "");
260
261
262 if (iNewProcessID > 0) {
263 documentContext.replaceItemValue("$processid",
264 Integer.valueOf(iNewProcessID));
265 }
266
267
268 documentContext.replaceItemValue("$activityid", Integer.valueOf(0));
269
270
271 String sFollowUp = documentActivity.getItemValueString("keyFollowUp");
272 int iNextActivityID = documentActivity
273 .getItemValueInteger("numNextActivityID");
274 if ("1".equals(sFollowUp) && iNextActivityID > 0) {
275 this.appendActivityID(iNextActivityID);
276 }
277
278 }
279
280
281
282
283
284
285 @SuppressWarnings("unchecked")
286 private void appendActivityID(int aID) {
287
288
289 List v = documentContext.getItemValue("$ActivityIDList");
290 if (v == null)
291 v = new Vector();
292
293 if ((v.size() == 1) && ("".equals(v.get(0).toString())))
294 v = new Vector();
295
296 v.add(Integer.valueOf(aID));
297
298
299 while (v.indexOf(Integer.valueOf(0)) > -1) {
300 v.remove(v.indexOf(Integer.valueOf(0)));
301 }
302
303 documentContext.replaceItemValue("$ActivityIDList", v);
304 if (ctx.getLogLevel() == LOG_LEVEL_FINE)
305 logger.info("[WorkflowKernel] append new Activity ID=" + aID);
306
307 }
308
309
310
311
312
313
314 private void writeLog() {
315
316 String sLog = DateFormat.getDateTimeInstance(DateFormat.MEDIUM,
317 DateFormat.MEDIUM).format(new Date());
318
319
320 sLog = sLog + "|"
321 + documentActivity.getItemValueInteger("numprocessid") + "."
322 + documentActivity.getItemValueInteger("numactivityid") + ":="
323 + documentActivity.getItemValueInteger("numnextprocessid");
324
325 List vLog = documentContext
326 .getItemValue("txtworkflowactivitylog");
327 if (vLog == null)
328 vLog = new Vector();
329
330 vLog.add(sLog);
331 documentContext.replaceItemValue("txtworkflowactivitylog", vLog);
332 documentContext
333 .replaceItemValue("numlastactivityid", Integer
334 .valueOf(documentActivity
335 .getItemValueInteger("numactivityid")));
336
337 }
338
339
340
341
342
343
344
345
346 private void loadActivity() throws ProcessingErrorException {
347
348 int aProcessID = documentContext.getItemValueInteger("$processid");
349 int aActivityID = documentContext.getItemValueInteger("$activityid");
350
351
352 String sModelVersion = documentContext
353 .getItemValueString("$modelversion");
354
355
356 if (ctx instanceof ExtendedWorkflowContext)
357 documentActivity = ((ExtendedWorkflowContext) ctx)
358 .getExtendedModel().getActivityEntityByVersion(aProcessID,
359 aActivityID, sModelVersion);
360 else
361 documentActivity = ctx.getModel().getActivityEntity(aProcessID,
362 aActivityID);
363
364 if (documentActivity == null)
365 throw new ProcessingErrorException("[WorkflowKernel] model entry "
366 + aProcessID + "." + aActivityID + " not found");
367
368 if (ctx.getLogLevel() == LOG_LEVEL_FINE)
369 logger.info("[WorkflowKernel] loadActivity: " + aProcessID + "."
370 + aActivityID + " successfully");
371
372
373 if (vectorEdgeHistory != null) {
374 if (vectorEdgeHistory.indexOf((aProcessID + "." + aActivityID)) != -1)
375 throw new ModelException("[WorkflowKernel] loop detected "
376 + aProcessID + "." + aActivityID + ","
377 + vectorEdgeHistory.toString());
378 }
379
380 }
381
382
383
384
385
386
387 private void loadPlugins() throws PluginException {
388
389
390 if (vectorPluginsClassNames.size() == 0
391 && ctx.getLogLevel() >= LOG_LEVEL_FINE)
392 logger.info("[WorkflowKernel] Warning loadPlugins: no plugins defined!");
393
394 for (int i = 0; i < vectorPluginsClassNames.size(); i++) {
395
396 String sPluginClass = vectorPluginsClassNames.elementAt(i)
397 .toString();
398
399 if ((sPluginClass != null) && (!"".equals(sPluginClass))) {
400 if (ctx.getLogLevel() == LOG_LEVEL_FINE) {
401 logger.info("[WorkflowKernel] loading Plugin "
402 + sPluginClass + "...");
403 }
404 Class clazz = null;
405 try {
406 clazz = Class.forName(sPluginClass);
407 Plugin plugin = (Plugin) clazz.newInstance();
408 plugin.init(ctx);
409 vectorPlugins.add(plugin);
410
411 } catch (ClassNotFoundException e) {
412 throw new PluginException(
413 "[WorkflowKernel] Could not create Plugin: "
414 + sPluginClass + " Reason: " + e.toString(),
415 e);
416 } catch (InstantiationException e) {
417 throw new PluginException(
418 "[WorkflowKernel] Could not create Plugin: "
419 + sPluginClass + " Reason: " + e.toString(),
420 e);
421 } catch (IllegalAccessException e) {
422 throw new PluginException(
423 "[WorkflowKernel] Could not create Plugin: "
424 + sPluginClass + " Reason: " + e.toString(),
425 e);
426 }
427
428 }
429
430 }
431
432 }
433
434
435
436
437
438
439
440
441
442 private int runPlugins() throws PluginException {
443 int iStatus;
444 String sPluginName = null;
445 List<String> localPluginLog = new Vector<String>();
446 List<String> vectorPluginLog;
447
448 try {
449
450 vectorPluginLog = documentContext
451 .getItemValue("txtWorkflowPluginLog");
452 for (int i = 0; i < vectorPlugins.size(); i++) {
453 Plugin plugin = (Plugin) vectorPlugins.elementAt(i);
454 sPluginName = plugin.getClass().getName();
455 if (ctx.getLogLevel() == LOG_LEVEL_FINE)
456 logger.info("[WorkflowKernel] running Plugin: "
457 + sPluginName + "...");
458
459 try {
460 iStatus = plugin.run(documentContext, documentActivity);
461 } catch (PluginException e) {
462 throw new PluginException(
463 "[WorkflowKernel] Error running Plugin: "
464 + sPluginName + " Reason: " + e.toString(),
465 e);
466 }
467
468 String sLog = DateFormat.getDateTimeInstance(DateFormat.LONG,
469 DateFormat.MEDIUM).format(new Date());
470
471 sLog = sLog + " " + plugin.getClass().getName() + "=" + iStatus;
472
473 localPluginLog.add(sLog);
474 vectorPluginLog.add(sLog);
475
476 if (iStatus == Plugin.PLUGIN_ERROR) {
477
478 documentContext.replaceItemValue("txtWorkflowPluginLog",
479 vectorPluginLog);
480
481
482 logger.severe("[WorkflowKernel] Error processing Plugin: "
483 + sPluginName);
484 logger.severe("[WorkflowKernel] Plugin-Log: ");
485 for (String sLogEntry : localPluginLog)
486 logger.severe("[WorkflowKernel] " + sLogEntry);
487
488 return Plugin.PLUGIN_ERROR;
489 }
490 }
491
492 documentContext.replaceItemValue("txtWorkflowPluginLog",
493 vectorPluginLog);
494 return Plugin.PLUGIN_OK;
495
496 } catch (PluginException e) {
497
498 logger.severe("[WorkflowKernel] Plugin-Stack: ");
499 for (String sLogEntry : localPluginLog)
500 logger.severe("[WorkflowKernel] " + sLogEntry);
501
502 throw e;
503 }
504
505 }
506
507 private void closePlugins(int astatus) throws PluginException {
508
509 for (int i = 0; i < vectorPlugins.size(); i++) {
510 Plugin plugin = (Plugin) vectorPlugins.elementAt(i);
511 if (ctx.getLogLevel() == LOG_LEVEL_FINE)
512 logger.info("[WorkflowKernel] closing Plugin: "
513 + plugin.getClass().getName() + "...");
514 try {
515 plugin.close(astatus);
516 } catch (PluginException e) {
517 throw new PluginException(
518 "[WorkflowKernel] Could not close Plugin: "
519 + plugin.getClass().getName() + " Reason: "
520 + e.toString(), e);
521 }
522 }
523
524 vectorPlugins = new Vector();
525
526 }
527
528 }