001: /*--
002:
003: Copyright (C) 2002-2005 Adrian Price.
004: All rights reserved.
005:
006: Redistribution and use in source and binary forms, with or without
007: modification, are permitted provided that the following conditions
008: are met:
009:
010: 1. Redistributions of source code must retain the above copyright
011: notice, this list of conditions, and the following disclaimer.
012:
013: 2. Redistributions in binary form must reproduce the above copyright
014: notice, this list of conditions, and the disclaimer that follows
015: these conditions in the documentation and/or other materials
016: provided with the distribution.
017:
018: 3. The names "OBE" and "Open Business Engine" must not be used to
019: endorse or promote products derived from this software without prior
020: written permission. For written permission, please contact
021: adrianprice@sourceforge.net.
022:
023: 4. Products derived from this software may not be called "OBE" or
024: "Open Business Engine", nor may "OBE" or "Open Business Engine"
025: appear in their name, without prior written permission from
026: Adrian Price (adrianprice@users.sourceforge.net).
027:
028: THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
029: WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
030: OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
031: DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
032: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
033: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
034: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
035: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
036: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
037: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
038: POSSIBILITY OF SUCH DAMAGE.
039:
040: For more information on OBE, please see
041: <http://obe.sourceforge.net/>.
042:
043: */
044:
045: package org.obe.util;
046:
047: import org.apache.commons.logging.Log;
048: import org.apache.commons.logging.LogFactory;
049: import org.obe.xpdl.FormalParameterNotFoundException;
050: import org.obe.xpdl.model.activity.Activity;
051: import org.obe.xpdl.model.activity.ActivitySet;
052: import org.obe.xpdl.model.application.Application;
053: import org.obe.xpdl.model.data.FormalParameter;
054: import org.obe.xpdl.model.data.ParameterMode;
055: import org.obe.xpdl.model.data.TypeDeclaration;
056: import org.obe.xpdl.model.misc.RedefinableHeader;
057: import org.obe.xpdl.model.participant.Participant;
058: import org.obe.xpdl.model.pkg.ExternalPackage;
059: import org.obe.xpdl.model.pkg.XPDLPackage;
060: import org.obe.xpdl.model.workflow.WorkflowProcess;
061: import org.wfmc.wapi.WMInvalidActivityNameException;
062: import org.wfmc.wapi.WMInvalidProcessDefinitionException;
063: import org.wfmc.wapi.WMInvalidTargetUserException;
064: import org.wfmc.wapi.WMInvalidToolException;
065:
066: import java.util.ArrayList;
067: import java.util.List;
068: import java.util.StringTokenizer;
069:
070: /**
071: * Utility class for searching activity/workflow/package for settings and
072: * definitions.
073: *
074: * @author Anthony Eden
075: * @author Adrian Price
076: */
077: public final class WorkflowUtilities {
078: private static final int DEFAULT_PRIORITY = 5;
079: private static final Log log = LogFactory
080: .getLog(WorkflowUtilities.class);
081:
082: /**
083: * Finds an activity within a workflow process definition.
084: *
085: * @param workflow The workflow process definition to search.
086: * @param activityId The activity ID.
087: * @return The activity definition.
088: * @throws WMInvalidActivityNameException if the activity was not found.
089: */
090: public static Activity findActivity(WorkflowProcess workflow,
091: String activityId) throws WMInvalidActivityNameException {
092:
093: for (int i = 0, n = workflow.getActivity().length; i < n; i++) {
094: Activity activity = workflow.getActivity(i);
095: if (activity.getId().equals(activityId))
096: return activity;
097: }
098: for (int i = 0, m = workflow.getActivitySet().length; i < m; i++) {
099: ActivitySet as = workflow.getActivitySet(i);
100: for (int j = 0, n = as.getActivity().length; j < n; j++) {
101: Activity activity = as.getActivity(j);
102: if (activity.getId().equals(activityId))
103: return activity;
104: }
105: }
106: throw new WMInvalidActivityNameException(activityId);
107: }
108:
109: /**
110: * Finds the priority to assign to an activity. The priority is taken from
111: * the activity itself if defined therein, or from its associated workflow
112: * priority if not.
113: *
114: * @param activity The activity definition.
115: * @return The activity priority.
116: */
117: public static int findActivityPriority(Activity activity) {
118: String priorityStr = activity.getPriority();
119: return priorityStr != null ? Integer.parseInt(priorityStr)
120: : findWorkflowPriority(activity.getWorkflowProcess());
121: }
122:
123: /**
124: * Gets the ParameterMode for the named parameter in the given application.
125: *
126: * @param app The Application
127: * @param paramName The parameter name
128: * @return The ParameterMode
129: * @throws FormalParameterNotFoundException
130: * If the named parameter could
131: * be found.
132: */
133: public static ParameterMode findParameterMode(Application app,
134: String paramName) throws FormalParameterNotFoundException {
135:
136: if (log.isDebugEnabled())
137: log.debug("findParameterMode(" + app + ", " + paramName
138: + ')');
139:
140: for (int i = 0, n = app.getFormalParameter().length; i < n; i++) {
141: FormalParameter fp = app.getFormalParameter(i);
142: if (fp.getId().equals(paramName)) {
143: if (log.isDebugEnabled())
144: log.debug("Parameter mode: " + fp.getMode());
145: return fp.getMode();
146: }
147: }
148: throw new FormalParameterNotFoundException(paramName);
149: }
150:
151: /**
152: * Finds the Participant with the specified ID in the given workflow or
153: * package.
154: *
155: * @param wp The workflow process definition.
156: * @param participantId The participant ID. This can be a comma-separated
157: * list if there are two or more participants.
158: * @return The participant definition.
159: * @throws WMInvalidTargetUserException if any of the participants could
160: * not be located.
161: */
162: public static Participant findParticipant(WorkflowProcess wp,
163: String participantId) throws WMInvalidTargetUserException {
164:
165: if (log.isDebugEnabled()) {
166: log.debug("Searching workflow '" + wp.getId()
167: + "' for participant '" + participantId + '\'');
168: }
169:
170: for (int i = 0, n = wp.getParticipant().length; i < n; i++) {
171: Participant p = wp.getParticipant(i);
172: if (p.getId().equals(participantId)) {
173: if (log.isDebugEnabled()) {
174: log.debug("Participant '" + participantId
175: + "' found in workflow '" + wp.getId()
176: + '\'');
177: }
178: return p;
179: }
180: }
181:
182: XPDLPackage pkg = wp.getPackage();
183: if (log.isDebugEnabled()) {
184: log.debug("Searching package '" + pkg.getId()
185: + "' for participant '" + participantId + '\'');
186: }
187:
188: for (int i = 0, n = pkg.getParticipant().length; i < n; i++) {
189: Participant p = pkg.getParticipant(i);
190: if (p.getId().equals(participantId)) {
191: if (log.isDebugEnabled()) {
192: log.debug("Participant '" + participantId
193: + "' found in package '" + pkg.getId()
194: + '\'');
195: }
196: return p;
197: }
198: }
199:
200: // perhaps this should be optional?
201: if (log.isDebugEnabled()) {
202: log.debug("Searching external packages for participant '"
203: + participantId + '\'');
204: }
205:
206: for (int i = 0, m = pkg.getExternalPackage().length; i < m; i++) {
207: ExternalPackage extPkg = pkg.getExternalPackage(i);
208: pkg = extPkg.getPackage();
209: for (int j = 0, n = pkg.getParticipant().length; j < n; j++) {
210: Participant p = pkg.getParticipant(j);
211: if (p.getId().equals(participantId)) {
212: if (log.isDebugEnabled()) {
213: log.debug("Participant '" + participantId
214: + "' found in external package '"
215: + extPkg.getHref() + '\'');
216: }
217: return p;
218: }
219: }
220: }
221: throw new WMInvalidTargetUserException(participantId);
222: }
223:
224: /**
225: * Find the Participants with the specified IDs in the given workflow or
226: * package.
227: *
228: * @param wp The workflow process definition.
229: * @param particips The participant ID(s). This can be a comma-separated
230: * list if there are two or more participants.
231: * @return The participant definition.
232: * @throws WMInvalidTargetUserException if any of the participants could
233: * not be located.
234: */
235: public static Participant[] findParticipants(WorkflowProcess wp,
236: String particips) throws WMInvalidTargetUserException {
237:
238: List participants = new ArrayList();
239: StringTokenizer strTok = new StringTokenizer(particips, ", ");
240: outer: while (strTok.hasMoreTokens()) {
241: String id = strTok.nextToken();
242: if (log.isDebugEnabled()) {
243: log.debug("Searching workflow '" + wp.getId()
244: + "' for participant '" + id + '\'');
245: }
246:
247: for (int i = 0, n = wp.getParticipant().length; i < n; i++) {
248: Participant p = wp.getParticipant(i);
249: if (p.getId().equals(id)) {
250: if (log.isDebugEnabled()) {
251: log.debug("Participant '" + id
252: + "' found in workflow '" + wp.getId()
253: + '\'');
254: }
255: participants.add(p);
256: continue outer;
257: }
258: }
259:
260: XPDLPackage pkg = wp.getPackage();
261: if (log.isDebugEnabled()) {
262: log.debug("Searching package '" + pkg.getId()
263: + "' for participant '" + id + '\'');
264: }
265:
266: for (int i = 0, n = pkg.getParticipant().length; i < n; i++) {
267: Participant p = pkg.getParticipant(i);
268: if (p.getId().equals(id)) {
269: if (log.isDebugEnabled()) {
270: log.debug("Participant '" + id
271: + "' found in package '" + pkg.getId()
272: + '\'');
273: }
274: participants.add(p);
275: continue outer;
276: }
277: }
278:
279: // perhaps this should be optional?
280: if (log.isDebugEnabled()) {
281: log
282: .debug("Searching external packages for participant '"
283: + id + '\'');
284: }
285: for (int i = 0, m = pkg.getExternalPackage().length; i < m; i++) {
286: ExternalPackage extPkg = pkg.getExternalPackage(i);
287: pkg = extPkg.getPackage();
288: for (int j = 0, n = pkg.getParticipant().length; j < n; j++) {
289: Participant p = pkg.getParticipant(j);
290: if (p.getId().equals(id)) {
291: if (log.isDebugEnabled()) {
292: log.debug("Participant '" + id
293: + "' found in external package '"
294: + extPkg.getHref() + '\'');
295: }
296: participants.add(p);
297: continue outer;
298: }
299: }
300: }
301: throw new WMInvalidTargetUserException(id);
302: }
303: return (Participant[]) participants
304: .toArray(new Participant[participants.size()]);
305: }
306:
307: private static Application findToolDefinition(
308: Application[] toolDefs, String id) {
309:
310: for (int i = 0, n = toolDefs.length; i < n; i++) {
311: Application toolDef = toolDefs[i];
312: if (toolDef.getId().equals(id))
313: return toolDef;
314: }
315: return null;
316: }
317:
318: /**
319: * Finds the definition of the specified tool in a workflow or package.
320: *
321: * @param wp The WorkflowProcess to search.
322: * @param toolId The ID of the tool for which the definition is required.
323: * @return The tool definition.
324: * @throws WMInvalidToolException if the tool definition could not be
325: * located.
326: */
327: public static Application findToolDefinition(WorkflowProcess wp,
328: String toolId) throws WMInvalidToolException {
329:
330: Application toolDef;
331:
332: if (log.isDebugEnabled()) {
333: log.debug("Searching workflow '" + wp.getId()
334: + "' for tool '" + toolId + '\'');
335: }
336: toolDef = findToolDefinition(wp.getApplication(), toolId);
337: if (toolDef == null) {
338: XPDLPackage pkg = wp.getPackage();
339: if (log.isDebugEnabled()) {
340: log.debug("Searching package '" + pkg.getId()
341: + "' for tool '" + toolId + '\'');
342: }
343: toolDef = findToolDefinition(pkg.getApplication(), toolId);
344: if (toolDef == null) {
345: if (log.isDebugEnabled()) {
346: log.debug("Searching external packages for tool '"
347: + toolId + '\'');
348: }
349: for (int i = 0, n = pkg.getExternalPackage().length; i < n; i++) {
350: ExternalPackage externalPackage = pkg
351: .getExternalPackage(i);
352: toolDef = findToolDefinition(externalPackage
353: .getPackage().getApplication(), toolId);
354: if (toolDef != null) {
355: if (log.isDebugEnabled()) {
356: log.debug("Tool '" + toolId
357: + "' found in external package '"
358: + externalPackage.getHref() + '\'');
359: }
360: break;
361: }
362: }
363: if (toolDef == null)
364: throw new WMInvalidToolException(toolId);
365: } else {
366: if (log.isDebugEnabled()) {
367: log.debug("Tool '" + toolId
368: + "' found in package '" + pkg.getId()
369: + '\'');
370: }
371: }
372: } else {
373: if (log.isDebugEnabled()) {
374: log.debug("Tool '" + toolId + "' found in workflow '"
375: + wp.getId() + '\'');
376: }
377: }
378:
379: return toolDef;
380: }
381:
382: /**
383: * Finds a type declaration within a package.
384: *
385: * @param pkg The package to search.
386: * @param declaredTypeId The ID of the declared type.
387: * @return The type declaration.
388: * @throws WMInvalidProcessDefinitionException
389: * if the type declaration could
390: * not be found.
391: */
392: public static TypeDeclaration findTypeDeclaration(XPDLPackage pkg,
393: String declaredTypeId)
394: throws WMInvalidProcessDefinitionException {
395:
396: for (int i = 0, n = pkg.getTypeDeclaration().length; i < n; i++) {
397: TypeDeclaration typeDecl = pkg.getTypeDeclaration(i);
398: if (typeDecl.getId().equals(declaredTypeId))
399: return typeDecl;
400: }
401: throw new WMInvalidProcessDefinitionException(declaredTypeId);
402: }
403:
404: /**
405: * Finds the workflow priority from the workflow or its package.
406: *
407: * @param workflow The workflow definition to search.
408: * @return The workflow or package priority.
409: */
410: public static int findWorkflowPriority(WorkflowProcess workflow) {
411: String priorityStr = workflow.getProcessHeader().getPriority();
412: return priorityStr != null ? Integer.parseInt(priorityStr)
413: : DEFAULT_PRIORITY;
414: }
415:
416: /**
417: * Finds a workflow definition within a package.
418: *
419: * @param pkg The package to search.
420: * @param processDefinitionId The ID of the process definition required.
421: * @return The process definition.
422: * @throws WMInvalidProcessDefinitionException
423: * if the process definition
424: * could not be found in the package.
425: */
426: public static WorkflowProcess findWorkflowProcess(XPDLPackage pkg,
427: String processDefinitionId)
428: throws WMInvalidProcessDefinitionException {
429:
430: if (log.isDebugEnabled()) {
431: log.debug("Searching package '" + pkg.getId()
432: + "' for workflow '" + processDefinitionId + '\'');
433: }
434: for (int i = 0, n = pkg.getWorkflowProcess().length; i < n; i++) {
435: WorkflowProcess wf = pkg.getWorkflowProcess(i);
436: if (wf.getId().equals(processDefinitionId)) {
437: return wf;
438: }
439: }
440:
441: for (int i = 0, n = pkg.getExternalPackage().length; i < n; i++) {
442: ExternalPackage extPkg = pkg.getExternalPackage(i);
443: // BUG: this can throw an exception before all the external
444: // packages have been searched.
445: WorkflowProcess wf = findWorkflowProcess(extPkg
446: .getPackage(), processDefinitionId);
447: if (wf != null) {
448: if (log.isDebugEnabled()) {
449: log.debug("Workflow '" + processDefinitionId
450: + "' found in external package '"
451: + extPkg.getHref() + '\'');
452: }
453: break;
454: }
455: }
456: throw new WMInvalidProcessDefinitionException(
457: processDefinitionId);
458: }
459:
460: public static String[] getResponsibles(WorkflowProcess workflow) {
461: RedefinableHeader rhdr = workflow.getRedefinableHeader();
462: String[] responsibles = null;
463: if (rhdr != null)
464: responsibles = rhdr.getResponsible();
465: if (responsibles == null || responsibles.length == 0) {
466: rhdr = workflow.getPackage().getRedefinableHeader();
467: if (rhdr != null)
468: responsibles = rhdr.getResponsible();
469: }
470: return responsibles;
471: }
472:
473: private WorkflowUtilities() {
474: }
475: }
|