/*
* This file is part of the WfMOpen project.
* Copyright (C) 2001-2005 Danet GmbH (www.danet.de), BU BTS.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* $Id: ProcessMutableWrapper.java 2457 2007-09-13 07:47:08Z drmlipp $
*
* $Log$
* Revision 1.18 2006/11/23 14:55:03 drmlipp
* Improved performance.
*
* Revision 1.17 2006/11/23 08:58:45 drmlipp
* Moved signature retrieval to mutable wrapper (only needed there).
*
* Revision 1.16 2006/11/22 22:25:22 mlipp
* Removed not required phase listener.
*
* Revision 1.15 2006/11/22 12:49:47 drmlipp
* Improved error handling.
*
* Revision 1.14 2006/11/21 18:38:29 drmlipp
* Improving exception handling.
*
* Revision 1.13 2006/09/29 12:32:11 drmlipp
* Consistently using WfMOpen as projct name now.
*
* Revision 1.12 2006/09/15 11:43:04 drmlipp
* Minor improvements
*
* Revision 1.11 2006/09/07 15:04:43 drmlipp
* Added XML support.
*
* Revision 1.10 2006/09/06 15:26:22 drmlipp
* Added double support.
*
* Revision 1.9 2006/09/06 09:31:06 drmlipp
* Cleaned up event display.
*
* Revision 1.8 2006/09/04 14:58:35 drmlipp
* Proceeding with data editing.
*
* Revision 1.7 2006/09/01 11:14:25 drmlipp
* Fixed exceeding row index problem.
*
* Revision 1.6 2006/07/18 16:36:51 mlipp
* Added String and Integer data input fileds.
*
* Revision 1.5 2006/07/17 14:57:35 drmlipp
* Started data display.
*
* Revision 1.4 2005/10/21 15:05:51 drmlipp
* Continued audit event display and cleaned up some things.
*
* Revision 1.3 2005/10/20 09:54:34 drmlipp
* Improved process selection
*
* Revision 1.2 2005/10/19 20:52:07 mlipp
* Various fixes.
*
* Revision 1.1 2005/10/19 14:36:40 drmlipp
* Improved process editing.
*
*/
package de.danet.an.workflow.clients.mgmtportlets.process;
import java.lang.reflect.InvocationTargetException;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import de.danet.an.util.BeanSorter;
import de.danet.an.util.jsf.JSFUtil;
import de.danet.an.workflow.api.DefaultProcessData;
import de.danet.an.workflow.api.MethodInvocationBatch;
import de.danet.an.workflow.api.WorkflowService;
import de.danet.an.workflow.clients.mgmtportlets.WorkflowServiceConnection;
import de.danet.an.workflow.omgcore.InvalidDataException;
import de.danet.an.workflow.omgcore.InvalidStateException;
import de.danet.an.workflow.omgcore.ProcessData;
import de.danet.an.workflow.omgcore.ProcessDataInfo;
import de.danet.an.workflow.omgcore.TransitionNotAllowedException;
import de.danet.an.workflow.omgcore.UpdateNotAllowedException;
/**
* @author Michael Lipp
*
*/
public class ProcessMutableWrapper extends ProcessWrapper {
private static final org.apache.commons.logging.Log logger
= org.apache.commons.logging.LogFactory.getLog
(ProcessMutableWrapper.class);
private List dataFields;
private BeanSorter dataFieldSorter = null;
private Map selectionAttrs;
/**
* @param wfs
* @param proc
* @throws RemoteException
*/
public ProcessMutableWrapper
(WorkflowService wfs, String processMgrName, String processKey)
throws RemoteException {
super(processMgrName, processKey);
FacesContext fc = FacesContext.getCurrentInstance();
selectionAttrs = ((ProcessSelection)fc.getExternalContext()
.getSessionMap().get("processSelection")).getSelectionAttributes();
Map dataFieldAttrs = (Map)selectionAttrs.get("dataFieldAttributes");
if (dataFieldAttrs == null) {
dataFieldAttrs = new HashMap ();
selectionAttrs.put("dataFieldAttributes", dataFieldAttrs);
}
retrieveDataFields(dataFieldAttrs);
}
/**
* @throws RemoteException
*/
private void retrieveDataFields(Map dataFieldAttrs)
throws RemoteException {
MethodInvocationBatch mib = new MethodInvocationBatch ();
mib.addInvocation (process(), "processDefinition", null, null);
mib.addInvocation(-1, "contextSignature", null, null, true);
mib.addInvocation(process(), "processContext", null, null);
MethodInvocationBatch.Result mir = null;
try {
WorkflowService wfs = WorkflowServiceConnection
.instance("workflowServiceConnection").getWorkflowService();
mir = (MethodInvocationBatch.Result)wfs.executeBatch(mib);
} catch (InvocationTargetException e) {
throw (IllegalStateException)
(new IllegalStateException (e.getMessage())).initCause(e);
}
if (mir.hasExceptions ()) {
Exception e = mir.firstException ();
if (e instanceof RemoteException) {
throw (RemoteException)e;
}
throw (IllegalStateException)
(new IllegalStateException(e.getMessage())).initCause(e);
}
ProcessDataInfo sig = (ProcessDataInfo)mir.result(0);
ProcessData data = (ProcessData)mir.result(1);
dataFields = new ArrayList ();
for (Iterator i = data.entrySet().iterator();
i.hasNext();) {
Map.Entry e = (Map.Entry)i.next();
dataFields.add
(new DataFieldWrapper
(dataFieldAttrs, (String)e.getKey(),
sig.get(e.getKey()), e.getValue()));
}
}
/**
* Returns the process name.
* @return the process name
*/
public String getName() {
String name = selectionAttrs.containsKey("newName")
? (String)selectionAttrs.get("newName") : super.getName();
return name != null
? name : "(" + getProcessKey() + ")";
}
/**
* @param name The name to set.
*/
public void setName(String name) {
if (!name.equals(getName())) {
selectionAttrs.put("newName", name);
}
}
/**
* Checks if name has been modified.
* @return result
*/
public boolean isNameModified () {
return selectionAttrs.containsKey("newName");
}
/**
* @return Returns the state.
*/
public String getState() {
return selectionAttrs.containsKey("newState")
? (String)selectionAttrs.get("newState") : super.getState();
}
/**
* @param state The state to set.
*/
public void setState(String state) {
if (!state.equals(getState())) {
selectionAttrs.put ("newState", state);
}
}
/**
* Check if state has been modified.
* @return result
*/
public boolean isStateModified () {
return selectionAttrs.containsKey("newState");
}
/**
* @return the valid (subsequent) states.
*/
public Map getValidStates () throws RemoteException {
Map res = new HashMap ();
res.put(StateNameMapper.mapState(getState()), getState());
for (Iterator i = process().validStates().iterator(); i.hasNext();) {
String state = (String)i.next();
res.put(StateNameMapper.mapState(state), state);
}
return res;
}
public List getDataFields () {
if (dataFieldSorter == null) {
dataFieldSorter = processMgmt().getDataFieldSorter();
}
dataFieldSorter.sort(dataFields);
return dataFields;
}
/**
* Save modified values of process.
*/
public void save () throws RemoteException {
if (isNameModified()) {
process().setName(getName());
}
if (isStateModified()) {
try {
process().changeState(getState());
} catch (InvalidStateException e) {
logger.debug ("Invalid state (shouldn't happen): " + getState());
} catch (TransitionNotAllowedException e) {
JSFUtil.addMessage (FacesMessage.SEVERITY_ERROR, L10N_MSGS,
"cannotChangeState", null, e);
}
}
selectionAttrs.clear();
}
/**
* Save modified data.
*/
public void saveData () throws RemoteException {
ProcessData pd = new DefaultProcessData();
for (Iterator i = dataFields.iterator(); i.hasNext();) {
DataFieldWrapper df = (DataFieldWrapper)i.next();
if (df.isModified()) {
if (df.isString() || df.isLong() || df.isDouble()
|| df.isBoolean() || df.isDate() || df.isXml()) {
pd.put(df.getName(), df.getValue());
}
}
}
try {
process().setProcessContext(pd);
} catch (InvalidDataException e) {
} catch (UpdateNotAllowedException e) {
}
}
}