001: /*
002: * This file is part of the WfMOpen project.
003: * Copyright (C) 2005 Danet GmbH (www.danet.de), BU TEL.
004: * All rights reserved.
005: *
006: * This program is free software; you can redistribute it and/or modify
007: * it under the terms of the GNU General Public License as published by
008: * the Free Software Foundation; either version 2 of the License, or
009: * (at your option) any later version.
010: *
011: * This program is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014: * GNU General Public License for more details.
015: *
016: * You should have received a copy of the GNU General Public License
017: * along with this program; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: *
020: * $Id: ProcessWrapper.java,v 1.34 2007/03/04 20:09:41 mlipp Exp $
021: *
022: * $Log: ProcessWrapper.java,v $
023: * Revision 1.34 2007/03/04 20:09:41 mlipp
024: * Optimized table model loading.
025: *
026: * Revision 1.33 2007/03/01 13:10:26 drmlipp
027: * Added special handling for empty names.
028: *
029: * Revision 1.32 2006/12/04 14:18:42 drmlipp
030: * Added navigation between invoking and subprocess and fixed multiple deletes.
031: *
032: * Revision 1.31 2006/12/03 22:45:42 mlipp
033: * Obtain requester information.
034: *
035: * Revision 1.30 2006/11/23 16:40:20 drmlipp
036: * Optimized.
037: *
038: * Revision 1.29 2006/11/23 08:58:45 drmlipp
039: * Moved signature retrieval to mutable wrapper (only needed there).
040: *
041: * Revision 1.28 2006/11/22 12:49:47 drmlipp
042: * Improved error handling.
043: *
044: * Revision 1.27 2006/11/21 18:38:29 drmlipp
045: * Improving exception handling.
046: *
047: * Revision 1.26 2006/09/29 12:32:11 drmlipp
048: * Consistently using WfMOpen as projct name now.
049: *
050: * Revision 1.25 2006/09/15 11:43:04 drmlipp
051: * Minor improvements
052: *
053: * Revision 1.24 2006/09/06 09:31:06 drmlipp
054: * Cleaned up event display.
055: *
056: * Revision 1.23 2006/07/18 16:36:51 mlipp
057: * Added String and Integer data input fileds.
058: *
059: * Revision 1.22 2006/07/17 14:57:35 drmlipp
060: * Started data display.
061: *
062: * Revision 1.21 2005/11/07 14:36:11 drmlipp
063: * Adapted to revised request attribute handling.
064: *
065: * Revision 1.20 2005/11/06 22:01:46 mlipp
066: * Got remove selected working.
067: *
068: * Revision 1.19 2005/11/03 22:27:38 mlipp
069: * Started multiple selection implementation.
070: *
071: * Revision 1.18 2005/11/03 20:50:17 mlipp
072: * Simplified a bit.
073: *
074: * Revision 1.17 2005/10/21 15:05:51 drmlipp
075: * Continued audit event display and cleaned up some things.
076: *
077: * Revision 1.16 2005/10/20 13:52:19 drmlipp
078: * Implementation of audit event display continued.
079: *
080: * Revision 1.15 2005/10/19 20:52:07 mlipp
081: * Various fixes.
082: *
083: * Revision 1.14 2005/10/19 14:36:40 drmlipp
084: * Improved process editing.
085: *
086: * Revision 1.13 2005/10/18 20:54:31 mlipp
087: * Finished process state changing.
088: *
089: * Revision 1.12 2005/10/18 15:28:16 drmlipp
090: * Started editable process state.
091: *
092: * Revision 1.11 2005/10/14 12:45:35 drmlipp
093: * Added information.
094: *
095: * Revision 1.10 2005/10/12 15:16:28 drmlipp
096: * Implementation continued.
097: *
098: * Revision 1.9 2005/10/04 14:28:32 drmlipp
099: * Improved debug messages.
100: *
101: * Revision 1.8 2005/10/02 21:04:03 mlipp
102: * Added activity list sorting.
103: *
104: * Revision 1.7 2005/10/01 20:53:55 mlipp
105: * Improved status display.
106: *
107: * Revision 1.6 2005/09/30 21:48:58 mlipp
108: * Basic process detail display working.
109: *
110: * Revision 1.5 2005/09/29 21:59:08 mlipp
111: * Continued process detail view implementation.
112: *
113: * Revision 1.4 2005/09/27 17:05:15 drmlipp
114: * Process display continued.
115: *
116: * Revision 1.3 2005/09/26 21:34:01 mlipp
117: * Started detail view.
118: *
119: * Revision 1.2 2005/09/23 21:03:31 mlipp
120: * Added attributes.
121: *
122: * Revision 1.1 2005/09/23 14:55:03 drmlipp
123: * Basic process list implemented.
124: *
125: */
126: package de.danet.an.workflow.clients.mgmtportlets.process;
127:
128: import java.io.Serializable;
129: import java.lang.reflect.InvocationTargetException;
130: import java.rmi.RemoteException;
131: import java.util.ArrayList;
132: import java.util.Date;
133: import java.util.Iterator;
134: import java.util.List;
135:
136: import javax.faces.application.FacesMessage;
137: import javax.faces.context.FacesContext;
138: import javax.faces.model.DataModel;
139: import javax.faces.model.ListDataModel;
140:
141: import de.danet.an.util.BeanSorter;
142: import de.danet.an.util.jsf.JSFUtil;
143: import de.danet.an.workflow.api.Activity;
144: import de.danet.an.workflow.api.CannotRemoveException;
145: import de.danet.an.workflow.api.InvalidKeyException;
146: import de.danet.an.workflow.api.MethodInvocationBatch;
147: import de.danet.an.workflow.api.Process;
148: import de.danet.an.workflow.api.ProcessDirectory;
149: import de.danet.an.workflow.api.WorkflowService;
150: import de.danet.an.workflow.clients.mgmtportlets.WorkflowServiceConnection;
151: import de.danet.an.workflow.domain.SubProcRequester;
152: import de.danet.an.workflow.omgcore.WfActivity;
153: import de.danet.an.workflow.omgcore.WfRequester;
154:
155: /**
156: * A wrapper class that makes processes look like JavaBeans.
157: */
158: public class ProcessWrapper implements Serializable {
159:
160: private static final org.apache.commons.logging.Log logger = org.apache.commons.logging.LogFactory
161: .getLog(ProcessWrapper.class);
162:
163: protected static String L10N_MSGS = "de.danet.an.workflow.clients.mgmtportlets.process.L10n";
164:
165: private transient Process processCache;
166: private String packageId;
167: private String packageName;
168: private String processId;
169: private String processName;
170: private String mgrName = null;
171: private String processKey = null;;
172: private String name;
173: private int priority;
174: private String state;
175: private Date createTime;
176: private Date lastStateTime;
177: private String invokingMgrName = null;
178: private String invokingProcKey = null;
179: private String invokingActName = null;
180: private String invokingActKey = null;
181: private transient DataModel activities = null;
182: private BeanSorter activitySorter = null;
183: private boolean selected = false;
184:
185: /**
186: * Create a new instance for the given process definition.
187: * @param pd the process definition to wrap
188: */
189: public ProcessWrapper(String processMgrName, String processKey)
190: throws RemoteException {
191: this .mgrName = processMgrName;
192: this .processKey = processKey;
193: update();
194: }
195:
196: /**
197: * Create a new instance for the given process definition.
198: * @param pd the process definition to wrap
199: */
200: public ProcessWrapper(Process proc) throws RemoteException {
201: this .processCache = proc;
202: update();
203: }
204:
205: /**
206: * Update data if not already updated in this lifecycle.
207: * @throws RemoteException
208: */
209: protected void update() throws RemoteException {
210: MethodInvocationBatch mib = new MethodInvocationBatch();
211: WorkflowService wfs = WorkflowServiceConnection.instance(
212: "workflowServiceConnection").getWorkflowService();
213: if (processCache == null) {
214: ProcessDirectory pd = wfs.processDirectory();
215: mib.addInvocation(pd, "lookupProcess", new String[] {
216: "java.lang.String", "java.lang.String" },
217: new Object[] { mgrName, processKey });
218: mib.addInvocation(-1, "processDefinition", null, null,
219: false);
220: mib.addInvocation(-1, "packageId", null, null, false);
221: mib.addInvocation(-2, "packageName", null, null, false);
222: mib.addInvocation(-3, "processId", null, null, false);
223: mib.addInvocation(-4, "processName", null, null, true);
224: mib.addInvocation(-5, "name", null, null, false);
225: mib.addInvocation(-6, "priority", null, null, false);
226: mib.addInvocation(-7, "state", null, null, false);
227: mib.addInvocation(-8, "createTime", null, null, false);
228: mib.addInvocation(-9, "lastStateTime", null, null, false);
229: mib.addInvocation(-10, "requester", null, null, false);
230: } else {
231: mib.addInvocation(processCache, "key", null, null);
232: mib.addInvocation(processCache, "processDefinition", null,
233: null);
234: mib.addInvocation(-1, "mgrName", null, null, false);
235: mib.addInvocation(-2, "packageId", null, null, false);
236: mib.addInvocation(-3, "packageName", null, null, false);
237: mib.addInvocation(-4, "processId", null, null, false);
238: mib.addInvocation(-5, "processName", null, null, true);
239: mib.addInvocation(processCache, "name", null, null);
240: mib.addInvocation(processCache, "priority", null, null);
241: mib.addInvocation(processCache, "state", null, null);
242: mib.addInvocation(processCache, "createTime", null, null);
243: mib
244: .addInvocation(processCache, "lastStateTime", null,
245: null);
246: mib.addInvocation(processCache, "requester", null, null);
247: }
248: MethodInvocationBatch.Result mir = null;
249: try {
250: mir = (MethodInvocationBatch.Result) wfs.executeBatch(mib);
251: } catch (InvocationTargetException e) {
252: throw (IllegalStateException) (new IllegalStateException(e
253: .getMessage())).initCause(e);
254: }
255: if (mir.hasExceptions()) {
256: Exception e = mir.firstException();
257: if (e instanceof RemoteException) {
258: throw (RemoteException) e;
259: }
260: throw (IllegalStateException) (new IllegalStateException(e
261: .getMessage())).initCause(e);
262: }
263: int resPos = 0;
264: if (processCache == null) {
265: processCache = (Process) mir.result(resPos++);
266: } else {
267: processKey = mir.resultAsString(resPos++);
268: mgrName = mir.resultAsString(resPos++);
269: }
270: packageId = mir.resultAsString(resPos++);
271: packageName = mir.resultAsString(resPos++);
272: processId = mir.resultAsString(resPos++);
273: processName = mir.resultAsString(resPos++);
274: name = mir.resultAsString(resPos++);
275: priority = mir.resultAsInt(resPos++);
276: state = mir.resultAsString(resPos++);
277: createTime = mir.resultAsDate(resPos++);
278: lastStateTime = mir.resultAsDate(resPos++);
279: WfRequester requester = (WfRequester) mir.result(resPos++);
280: if (requester instanceof WfActivity) {
281: mib = new MethodInvocationBatch();
282: mib.addInvocation(requester, "name", null, null);
283: mib.addInvocation(requester, "key", null, null);
284: mib.addInvocation(requester, "container", null, null);
285: mib.addInvocation(-1, "manager", null, null, false);
286: mib.addInvocation(-1, "name", null, null, true);
287: mib.addInvocation(-2, "key", null, null, true);
288: mir = null;
289: try {
290: mir = (MethodInvocationBatch.Result) wfs
291: .executeBatch(mib);
292: } catch (InvocationTargetException e) {
293: throw (IllegalStateException) (new IllegalStateException(
294: e.getMessage())).initCause(e);
295: }
296: if (mir.hasExceptions()) {
297: Exception e = mir.firstException();
298: if (e instanceof RemoteException) {
299: throw (RemoteException) e;
300: }
301: throw (IllegalStateException) (new IllegalStateException(
302: e.getMessage())).initCause(e);
303: }
304: invokingActName = mir.resultAsString(0);
305: invokingActKey = mir.resultAsString(1);
306: invokingMgrName = mir.resultAsString(2);
307: invokingProcKey = mir.resultAsString(3);
308: }
309: }
310:
311: /**
312: * Return the process management bean.
313: * @return the result
314: */
315: protected ProcessMgmt processMgmt() {
316: FacesContext fc = FacesContext.getCurrentInstance();
317: return (ProcessMgmt) fc.getApplication().getVariableResolver()
318: .resolveVariable(fc, "processMgmt");
319: }
320:
321: /**
322: * @return the process
323: */
324: public Process process() throws RemoteException {
325: if (processCache == null) {
326: try {
327: WorkflowService wfs = WorkflowServiceConnection
328: .instance("workflowServiceConnection")
329: .getWorkflowService();
330: ProcessDirectory pd = wfs.processDirectory();
331: processCache = pd.lookupProcess(mgrName, processKey);
332: } catch (InvalidKeyException e) {
333: return null;
334: }
335: }
336: return processCache;
337: }
338:
339: /**
340: * @return Returns the packageName.
341: */
342: public String getPackageName() {
343: return packageName == null || packageName.length() == 0 ? "("
344: + packageId + ")" : packageName;
345: }
346:
347: /**
348: * @return Returns the processName.
349: */
350: public String getProcessName() {
351: return processName == null || processName.length() == 0 ? "("
352: + processId + ")" : processName;
353: }
354:
355: /**
356: * @return Returns the mgrName.
357: */
358: public String getMgrName() {
359: return mgrName;
360: }
361:
362: /**
363: * Returns the process name.
364: * @return the process name
365: */
366: public String getName() {
367: return name != null && name.length() > 0 ? name : "("
368: + processKey + ")";
369: }
370:
371: /**
372: * @return Returns the priority.
373: */
374: public int getPriority() {
375: return priority;
376: }
377:
378: /**
379: * @param priority The priority to set.
380: */
381: public void setPriority(int priority) {
382: this .priority = priority;
383: }
384:
385: /**
386: * @return Returns the createTime.
387: */
388: public Date getCreateTime() {
389: return createTime;
390: }
391:
392: /**
393: * @return Returns the lastStateTime.
394: */
395: public Date getLastStateTime() {
396: return lastStateTime;
397: }
398:
399: /**
400: * @return Returns the processKey.
401: */
402: public String getProcessKey() {
403: return processKey;
404: }
405:
406: /**
407: * @return Returns the state.
408: */
409: public String getStateName() {
410: return StateNameMapper.mapState(state);
411: }
412:
413: /**
414: * @return Returns the state.
415: */
416: public String getState() {
417: return state;
418: }
419:
420: /**
421: * @param state The state to set.
422: */
423: public void setState(String state) {
424: this .state = state;
425: }
426:
427: /**
428: * Return if process is removable.
429: */
430: public boolean isRemovable() {
431: return state.startsWith("closed.");
432: }
433:
434: /**
435: * Return if process is updatable.
436: */
437: public boolean isUpdatable() {
438: return !state.startsWith("closed.");
439: }
440:
441: /**
442: * @return URL of state icon or null
443: */
444: public String getStateIconUrl() throws RemoteException {
445: return StateNameMapper.stateIconUrl(getState());
446: }
447:
448: /**
449: * @return the activities
450: */
451: public DataModel getActivities() throws RemoteException {
452: FacesContext fc = FacesContext.getCurrentInstance();
453: if (activitySorter == null) {
454: activitySorter = processMgmt().getActivitySorter();
455: }
456: if (activities == null) {
457: if (logger.isDebugEnabled()) {
458: logger.debug("Retrieving activity list of process "
459: + this );
460: }
461: WorkflowService wfs = ((WorkflowServiceConnection) fc
462: .getApplication().getVariableResolver()
463: .resolveVariable(fc, "workflowServiceConnection"))
464: .getWorkflowService();
465: List actList = new ArrayList();
466: for (Iterator i = process().steps().iterator(); i.hasNext();) {
467: Activity act = (Activity) i.next();
468: actList.add(new ActivityWrapper(wfs, act));
469: }
470: activitySorter.sort(actList);
471: activities = new ListDataModel(actList);
472: } else {
473: logger.debug("Re-using activities");
474: if (activitySorter.isModified()) {
475: activitySorter.sort((List) activities.getWrappedData());
476: }
477: }
478: return activities;
479: }
480:
481: /**
482: * @return invoker's name or <code>null</code>
483: */
484: public String getRequester() {
485: if (invokingActKey == null) {
486: return null;
487: }
488: if (invokingActName != null) {
489: return invokingActName;
490: }
491: return "(" + invokingActKey + ")";
492: }
493:
494: /**
495: * @return outcome
496: */
497: public String showDetail() {
498: FacesContext fc = FacesContext.getCurrentInstance();
499: fc.getExternalContext().getSessionMap().put("processSelection",
500: new ProcessSelection(mgrName, processKey));
501: return "showProcessDetail";
502: }
503:
504: /**
505: * @return outcome
506: */
507: public String showRequesterDetail() {
508: FacesContext fc = FacesContext.getCurrentInstance();
509: fc.getExternalContext().getSessionMap().put("processSelection",
510: new ProcessSelection(invokingMgrName, invokingProcKey));
511: return "showProcessDetail";
512: }
513:
514: /**
515: * Remove.
516: */
517: public String remove() throws RemoteException {
518: processMgmt().remove(process());
519:
520: FacesContext fc = FacesContext.getCurrentInstance();
521: fc.getExternalContext().getSessionMap().remove(
522: "processSelection");
523: return "showProcessList";
524: }
525:
526: public String toString() {
527: return "ProcessWrapper[name=" + name + ",processKey="
528: + processKey + "]";
529: }
530:
531: /**
532: * @return Returns the selected.
533: */
534: public boolean isSelected() throws RemoteException {
535: FacesContext fc = FacesContext.getCurrentInstance();
536: if (fc.getExternalContext().getRequestMap().containsKey(
537: "processAllSelection")) {
538: return isRemovable();
539: }
540: return selected;
541: }
542:
543: /**
544: * @param selected The selected to set.
545: */
546: public void setSelected(boolean selected) throws RemoteException {
547: if (!this.selected && selected) {
548: processMgmt().addSelected(process());
549: }
550: this.selected = selected;
551: }
552: }
|