001: /*
002: * This file is part of the WfMOpen project.
003: * Copyright (C) 2001-2003 Danet GmbH (www.danet.de), GS-AN.
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: ActImplBase.java,v 1.3.2.1 2007/11/02 16:00:33 drmlipp Exp $
021: *
022: * $Log: ActImplBase.java,v $
023: * Revision 1.3.2.1 2007/11/02 16:00:33 drmlipp
024: * Merged bug fixes from HEAD.
025: *
026: * Revision 1.4 2007/09/20 21:25:43 mlipp
027: * Fixed line length.
028: *
029: * Revision 1.3 2007/05/03 21:58:16 mlipp
030: * Internal refactoring for making better use of local EJBs.
031: *
032: * Revision 1.2 2006/09/29 12:32:08 drmlipp
033: * Consistently using WfMOpen as projct name now.
034: *
035: * Revision 1.1.1.5 2004/08/18 15:17:38 drmlipp
036: * Update to 1.2
037: *
038: * Revision 1.12 2004/03/25 15:52:45 lipp
039: * Ensure backward compatibility of serialzed instances.
040: *
041: * Revision 1.11 2004/03/25 14:41:47 lipp
042: * Added possibility to specify actual parameters as XML.
043: *
044: * Revision 1.10 2003/10/24 20:23:06 lipp
045: * Fixed exception handling.
046: *
047: * Revision 1.9 2003/09/25 11:01:20 lipp
048: * Fixed usage of jsScope (may not be used remotely).
049: *
050: * Revision 1.8 2003/09/04 08:46:44 lipp
051: * Fixed client dependency on rhino.jar.
052: *
053: * Revision 1.7 2003/07/02 18:44:38 lipp
054: * Removed inappropriate and annoying info messages.
055: *
056: * Revision 1.6 2003/07/01 15:49:55 montag
057: * jaxen-dom for XSLTTool.
058: *
059: * Revision 1.5 2003/06/27 08:51:45 lipp
060: * Fixed copyright/license information.
061: *
062: * Revision 1.4 2003/05/16 09:26:38 lipp
063: * Fixed actual parameter evaluation.
064: *
065: * Revision 1.3 2003/05/07 14:45:50 lipp
066: * Implemented synchronous subflow.
067: *
068: * Revision 1.2 2003/05/06 13:21:29 lipp
069: * Resolved cyclic dependency.
070: *
071: * Revision 1.1 2003/05/05 07:04:51 lipp
072: * Handling parameters for sub-flow now.
073: *
074: */
075: package de.danet.an.workflow.domain;
076:
077: import java.io.Serializable;
078:
079: import java.util.ArrayList;
080: import java.util.HashMap;
081: import java.util.HashSet;
082: import java.util.Iterator;
083: import java.util.List;
084: import java.util.Map;
085: import java.util.Set;
086:
087: import de.danet.an.workflow.internalapi.ExtImplementationLocal;
088: import de.danet.an.workflow.internalapi.ExtProcessLocal;
089: import de.danet.an.workflow.localapi.ActivityLocal;
090: import de.danet.an.workflow.localapi.ProcessLocal;
091: import de.danet.an.workflow.omgcore.InvalidDataException;
092: import de.danet.an.workflow.omgcore.ProcessData;
093: import de.danet.an.workflow.omgcore.UpdateNotAllowedException;
094:
095: import de.danet.an.workflow.api.DefaultProcessData;
096: import de.danet.an.workflow.api.FormalParameter;
097:
098: /**
099: * This class provides some base functionallity for both tool and
100: * sub-process based activity implementations.
101: *
102: * @author <a href="mailto:lipp@danet.de">Michael Lipp</a>
103: * @version $Revision: 1.3.2.1 $
104: */
105: public abstract class ActImplBase implements ExtImplementationLocal,
106: Serializable {
107:
108: /** Unique id. */
109: static final long serialVersionUID = -2129987329744599747L;
110:
111: private static final org.apache.commons.logging.Log logger = org.apache.commons.logging.LogFactory
112: .getLog(ActImplBase.class);
113:
114: /**
115: * Creates an instance of <code>ActImplBase</code>
116: * with all attributes initialized to default values.
117: */
118: public ActImplBase() {
119: }
120:
121: /**
122: * Return the actual parameters.
123: * @return actualParameters.
124: */
125: public abstract Object[] actualParameters();
126:
127: /**
128: * Create the parameter map for an invocation based on the
129: * given activity, its container and the formal parameters.
130: *
131: * @param process the process which the activity belongs to
132: * @param act the activity to which this tool implementation description
133: * is to be applied
134: * @param fps the formal parameters
135: * @return the parameter map
136: */
137: public Map parameterMap(ExtProcessLocal process, ActivityLocal act,
138: FormalParameter[] fps) {
139: Map procDataMap = act.processContext();
140: Map params = new HashMap();
141: List evals = new ArrayList();
142: List evalExprs = new ArrayList();
143: for (int i = 0; i < fps.length; i++) {
144: if (fps[i].mode() == FormalParameter.Mode.OUT) {
145: params.put(fps[i].id(), null);
146: continue;
147: }
148: Object actParamExpr = actualParameters()[i];
149: Object actParam = null;
150: if (procDataMap.containsKey(actParamExpr)) {
151: actParam = procDataMap.get(actParamExpr);
152: logger.debug("Value of \""
153: + actParamExpr
154: + "\" for parameter \""
155: + fps[i].id()
156: + "\" of "
157: + toString()
158: + " called in "
159: + act
160: + " is "
161: + (actParam == null ? "null" : actParam
162: .toString()));
163: } else if (fps[i].mode() == FormalParameter.Mode.IN) {
164: evals.add(fps[i].id());
165: evalExprs.add(new Object[] { fps[i].type(),
166: actParamExpr });
167: continue;
168: }
169: params.put(fps[i].id(), actParam);
170: }
171: Object[] evald = ((ExtProcessLocal) act.containerLocal())
172: .evalExpressions((Object[][]) evalExprs
173: .toArray(new Object[evalExprs.size()][]));
174: for (int i = 0; i < evals.size(); i++) {
175: Object actParam = evald[i];
176: if (actParam instanceof Byte) {
177: actParam = new Long(((Byte) actParam).longValue());
178: } else if (actParam instanceof Exception) {
179: logger.error("Problem evaluating parameter \""
180: + evalExprs.get(i) + "\": "
181: + ((Exception) actParam).getMessage());
182: actParam = "";
183: }
184: if (logger.isDebugEnabled()) {
185: logger.debug("Expression \""
186: + evalExprs.get(i)
187: + "\" for parameter \""
188: + evals.get(i)
189: + "\" of "
190: + toString()
191: + " called in "
192: + act
193: + " evaluates to "
194: + (actParam == null ? "null" : actParam
195: .toString()));
196: }
197: params.put(evals.get(i), actParam);
198: }
199: return params;
200: }
201:
202: /**
203: * Merge the result returned by an implementation into the process
204: * data. The names of the result data items must be formal parameter
205: * names which are mapped to process data items as defined by the
206: * actual parameters.
207: *
208: * @param process the process whose activity has invoked the implementation
209: * @param fps the formal parameters
210: * @param result the result data
211: * @throws InvalidDataException if the entries in the result do not
212: * match formal parameter names or excessive entries exist
213: */
214: protected void mergeResult(ProcessLocal process,
215: FormalParameter[] fps, Map result)
216: throws InvalidDataException {
217: try {
218: ProcessData pd = new DefaultProcessData();
219: Set items = new HashSet(result.keySet());
220: for (int i = 0; i < fps.length; i++) {
221: FormalParameter fp = fps[i];
222: if (fp.mode() == FormalParameter.Mode.IN) {
223: continue;
224: }
225: Object actParam = actualParameters()[i];
226: if (!result.containsKey(fp.id())) {
227: throw new InvalidDataException(
228: "Result does not include out parameter \""
229: + fp.id() + "\".");
230: }
231: pd.put(actParam, result.get(fp.id()));
232: items.remove(fp.id());
233: }
234: if (items.size() > 0) {
235: Iterator itr = items.iterator();
236: throw new InvalidDataException(
237: "Result includes excessive parameter \""
238: + (String) itr.next() + "\".");
239: }
240: process.setProcessContext(pd);
241: } catch (UpdateNotAllowedException e) {
242: // This is a bit curious, but the only possible
243: // mapping. And the OMG considers it "legal": "...or when
244: // an invalid attempt is made to update the results of an
245: // activity; lack of access rights might be one of those
246: // reasons."
247: throw new InvalidDataException("Caused by: "
248: + e.getMessage());
249: }
250: }
251: }
|