001: /*
002: * This file is part of the WfMOpen project.
003: * Copyright (C) 2001-2005 Danet GmbH (www.danet.de), BU BTS.
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: ProcessMutableWrapper.java,v 1.19 2007/09/13 07:47:08 drmlipp Exp $
021: *
022: * $Log: ProcessMutableWrapper.java,v $
023: * Revision 1.19 2007/09/13 07:47:08 drmlipp
024: * Made string fields expandable.
025: *
026: * Revision 1.18 2006/11/23 14:55:03 drmlipp
027: * Improved performance.
028: *
029: * Revision 1.17 2006/11/23 08:58:45 drmlipp
030: * Moved signature retrieval to mutable wrapper (only needed there).
031: *
032: * Revision 1.16 2006/11/22 22:25:22 mlipp
033: * Removed not required phase listener.
034: *
035: * Revision 1.15 2006/11/22 12:49:47 drmlipp
036: * Improved error handling.
037: *
038: * Revision 1.14 2006/11/21 18:38:29 drmlipp
039: * Improving exception handling.
040: *
041: * Revision 1.13 2006/09/29 12:32:11 drmlipp
042: * Consistently using WfMOpen as projct name now.
043: *
044: * Revision 1.12 2006/09/15 11:43:04 drmlipp
045: * Minor improvements
046: *
047: * Revision 1.11 2006/09/07 15:04:43 drmlipp
048: * Added XML support.
049: *
050: * Revision 1.10 2006/09/06 15:26:22 drmlipp
051: * Added double support.
052: *
053: * Revision 1.9 2006/09/06 09:31:06 drmlipp
054: * Cleaned up event display.
055: *
056: * Revision 1.8 2006/09/04 14:58:35 drmlipp
057: * Proceeding with data editing.
058: *
059: * Revision 1.7 2006/09/01 11:14:25 drmlipp
060: * Fixed exceeding row index problem.
061: *
062: * Revision 1.6 2006/07/18 16:36:51 mlipp
063: * Added String and Integer data input fileds.
064: *
065: * Revision 1.5 2006/07/17 14:57:35 drmlipp
066: * Started data display.
067: *
068: * Revision 1.4 2005/10/21 15:05:51 drmlipp
069: * Continued audit event display and cleaned up some things.
070: *
071: * Revision 1.3 2005/10/20 09:54:34 drmlipp
072: * Improved process selection
073: *
074: * Revision 1.2 2005/10/19 20:52:07 mlipp
075: * Various fixes.
076: *
077: * Revision 1.1 2005/10/19 14:36:40 drmlipp
078: * Improved process editing.
079: *
080: */
081: package de.danet.an.workflow.clients.mgmtportlets.process;
082:
083: import java.lang.reflect.InvocationTargetException;
084: import java.rmi.RemoteException;
085: import java.util.ArrayList;
086: import java.util.HashMap;
087: import java.util.Iterator;
088: import java.util.List;
089: import java.util.Map;
090:
091: import javax.faces.application.FacesMessage;
092: import javax.faces.context.FacesContext;
093:
094: import de.danet.an.util.BeanSorter;
095: import de.danet.an.util.jsf.JSFUtil;
096: import de.danet.an.workflow.api.DefaultProcessData;
097: import de.danet.an.workflow.api.MethodInvocationBatch;
098: import de.danet.an.workflow.api.WorkflowService;
099: import de.danet.an.workflow.clients.mgmtportlets.WorkflowServiceConnection;
100: import de.danet.an.workflow.omgcore.InvalidDataException;
101: import de.danet.an.workflow.omgcore.InvalidStateException;
102: import de.danet.an.workflow.omgcore.ProcessData;
103: import de.danet.an.workflow.omgcore.ProcessDataInfo;
104: import de.danet.an.workflow.omgcore.TransitionNotAllowedException;
105: import de.danet.an.workflow.omgcore.UpdateNotAllowedException;
106:
107: /**
108: * @author Michael Lipp
109: *
110: */
111: public class ProcessMutableWrapper extends ProcessWrapper {
112:
113: private static final org.apache.commons.logging.Log logger = org.apache.commons.logging.LogFactory
114: .getLog(ProcessMutableWrapper.class);
115:
116: private List dataFields;
117: private BeanSorter dataFieldSorter = null;
118: private Map selectionAttrs;
119:
120: /**
121: * @param wfs
122: * @param proc
123: * @throws RemoteException
124: */
125: public ProcessMutableWrapper(WorkflowService wfs,
126: String processMgrName, String processKey)
127: throws RemoteException {
128: super (processMgrName, processKey);
129: FacesContext fc = FacesContext.getCurrentInstance();
130:
131: selectionAttrs = ((ProcessSelection) fc.getExternalContext()
132: .getSessionMap().get("processSelection"))
133: .getSelectionAttributes();
134: Map dataFieldAttrs = (Map) selectionAttrs
135: .get("dataFieldAttributes");
136: if (dataFieldAttrs == null) {
137: dataFieldAttrs = new HashMap();
138: selectionAttrs.put("dataFieldAttributes", dataFieldAttrs);
139: }
140:
141: retrieveDataFields(dataFieldAttrs);
142: }
143:
144: /**
145: * @throws RemoteException
146: */
147: private void retrieveDataFields(Map dataFieldAttrs)
148: throws RemoteException {
149: MethodInvocationBatch mib = new MethodInvocationBatch();
150: mib.addInvocation(process(), "processDefinition", null, null);
151: mib.addInvocation(-1, "contextSignature", null, null, true);
152: mib.addInvocation(process(), "processContext", null, null);
153: MethodInvocationBatch.Result mir = null;
154: try {
155: WorkflowService wfs = WorkflowServiceConnection.instance(
156: "workflowServiceConnection").getWorkflowService();
157: mir = (MethodInvocationBatch.Result) wfs.executeBatch(mib);
158: } catch (InvocationTargetException e) {
159: throw (IllegalStateException) (new IllegalStateException(e
160: .getMessage())).initCause(e);
161: }
162: if (mir.hasExceptions()) {
163: Exception e = mir.firstException();
164: if (e instanceof RemoteException) {
165: throw (RemoteException) e;
166: }
167: throw (IllegalStateException) (new IllegalStateException(e
168: .getMessage())).initCause(e);
169: }
170: ProcessDataInfo sig = (ProcessDataInfo) mir.result(0);
171: ProcessData data = (ProcessData) mir.result(1);
172: dataFields = new ArrayList();
173: for (Iterator i = data.entrySet().iterator(); i.hasNext();) {
174: Map.Entry e = (Map.Entry) i.next();
175: dataFields.add(new DataFieldWrapper(dataFieldAttrs,
176: (String) e.getKey(), sig.get(e.getKey()), e
177: .getValue()));
178: }
179: }
180:
181: /**
182: * Returns the process name.
183: * @return the process name
184: */
185: public String getName() {
186: String name = selectionAttrs.containsKey("newName") ? (String) selectionAttrs
187: .get("newName")
188: : super .getName();
189: return name != null ? name : "(" + getProcessKey() + ")";
190: }
191:
192: /**
193: * @param name The name to set.
194: */
195: public void setName(String name) {
196: if (!name.equals(getName())) {
197: selectionAttrs.put("newName", name);
198: }
199: }
200:
201: /**
202: * Checks if name has been modified.
203: * @return result
204: */
205: public boolean isNameModified() {
206: return selectionAttrs.containsKey("newName");
207: }
208:
209: /**
210: * @return Returns the state.
211: */
212: public String getState() {
213: return selectionAttrs.containsKey("newState") ? (String) selectionAttrs
214: .get("newState")
215: : super .getState();
216: }
217:
218: /**
219: * @param state The state to set.
220: */
221: public void setState(String state) {
222: if (!state.equals(getState())) {
223: selectionAttrs.put("newState", state);
224: }
225: }
226:
227: /**
228: * Check if state has been modified.
229: * @return result
230: */
231: public boolean isStateModified() {
232: return selectionAttrs.containsKey("newState");
233: }
234:
235: /**
236: * @return the valid (subsequent) states.
237: */
238: public Map getValidStates() throws RemoteException {
239: Map res = new HashMap();
240: res.put(StateNameMapper.mapState(getState()), getState());
241: for (Iterator i = process().validStates().iterator(); i
242: .hasNext();) {
243: String state = (String) i.next();
244: res.put(StateNameMapper.mapState(state), state);
245: }
246: return res;
247: }
248:
249: public List getDataFields() {
250: if (dataFieldSorter == null) {
251: dataFieldSorter = processMgmt().getDataFieldSorter();
252: }
253: dataFieldSorter.sort(dataFields);
254: return dataFields;
255: }
256:
257: /**
258: * Save modified values of process.
259: */
260: public void save() throws RemoteException {
261: if (isNameModified()) {
262: process().setName(getName());
263: }
264: if (isStateModified()) {
265: try {
266: process().changeState(getState());
267: } catch (InvalidStateException e) {
268: logger.debug("Invalid state (shouldn't happen): "
269: + getState());
270: } catch (TransitionNotAllowedException e) {
271: JSFUtil.addMessage(FacesMessage.SEVERITY_ERROR,
272: L10N_MSGS, "cannotChangeState", null, e);
273: }
274: }
275: selectionAttrs.clear();
276: }
277:
278: /**
279: * Save modified data.
280: */
281: public void saveData() throws RemoteException {
282: ProcessData pd = new DefaultProcessData();
283: for (Iterator i = dataFields.iterator(); i.hasNext();) {
284: DataFieldWrapper df = (DataFieldWrapper) i.next();
285: if (df.isModified()) {
286: if (df.isString() || df.isLong() || df.isDouble()
287: || df.isBoolean() || df.isDate() || df.isXml()) {
288: pd.put(df.getName(), df.getValue());
289: }
290: }
291: }
292: try {
293: process().setProcessContext(pd);
294: } catch (InvalidDataException e) {
295: } catch (UpdateNotAllowedException e) {
296: }
297: }
298: }
|