[jbpm-commits] JBoss JBPM SVN: r5415 - in jbpm4/trunk/modules/bpmn/src: main/java/com and 6 other directories.
do-not-reply at jboss.org
do-not-reply at jboss.org
Mon Aug 3 14:34:11 EDT 2009
Author: kukeltje
Date: 2009-08-03 14:34:11 -0400 (Mon, 03 Aug 2009)
New Revision: 5415
Added:
jbpm4/trunk/modules/bpmn/src/main/java/com/
jbpm4/trunk/modules/bpmn/src/main/java/com/sun/
jbpm4/trunk/modules/bpmn/src/main/java/com/sun/script/
jbpm4/trunk/modules/bpmn/src/main/java/com/sun/script/xpath/
jbpm4/trunk/modules/bpmn/src/main/java/com/sun/script/xpath/XPathScriptEngine.java
jbpm4/trunk/modules/bpmn/src/main/java/com/sun/script/xpath/XPathScriptEngineFactory.java
jbpm4/trunk/modules/bpmn/src/test/resources/org/jbpm/bpmn/flownodes/exclusiveGatewayXPath.bpmn.xml
jbpm4/trunk/modules/bpmn/src/test/resources/org/jbpm/bpmn/flownodes/xmlTestDocument.xml
Modified:
jbpm4/trunk/modules/bpmn/src/main/java/org/jbpm/bpmn/flownodes/BpmnActivity.java
jbpm4/trunk/modules/bpmn/src/test/java/org/jbpm/bpmn/flownodes/ExclusiveGatewayTest.java
Log:
perliminary support for xpath as expressionlanguage in conditionExpressions
Added: jbpm4/trunk/modules/bpmn/src/main/java/com/sun/script/xpath/XPathScriptEngine.java
===================================================================
--- jbpm4/trunk/modules/bpmn/src/main/java/com/sun/script/xpath/XPathScriptEngine.java (rev 0)
+++ jbpm4/trunk/modules/bpmn/src/main/java/com/sun/script/xpath/XPathScriptEngine.java 2009-08-03 18:34:11 UTC (rev 5415)
@@ -0,0 +1,440 @@
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met: Redistributions of source code
+ * must retain the above copyright notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution. Neither the name of the Sun Microsystems nor the names of
+ * is contributors may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * XPathScriptEngine.java
+ * @author A. Sundararajan
+ */
+
+package com.sun.script.xpath;
+
+import javax.script.*;
+import java.io.*;
+import java.lang.reflect.*;
+import java.util.*;
+import javax.xml.XMLConstants;
+import javax.xml.namespace.*;
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.xpath.*;
+
+import org.apache.tools.ant.input.InputRequest;
+import org.dom4j.DocumentFactory;
+import org.dom4j.io.SAXReader;
+import org.dom4j.io.SAXWriter;
+import org.jbpm.bpmn.xpath.BpmnFunctionResolver;
+import org.jbpm.pvm.internal.util.IoUtil;
+import org.jbpm.pvm.internal.util.XmlUtil;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.xml.sax.*;
+import org.xml.sax.helpers.XMLReaderAdapter;
+
+import com.sun.xml.bind.v2.runtime.output.XMLStreamWriterOutput;
+
+public class XPathScriptEngine extends AbstractScriptEngine
+ implements Compilable {
+ // my factory, may be null
+ private ScriptEngineFactory factory;
+ private XPathFactory xpathFactory;
+
+ // special context variables for XPath result type and input
+ public static final String XPATH_RESULT_TYPE = "com.sun.script.xpath.resultType";
+ public static final String XPATH_INPUT_SRC = "com.sun.script.xpath.inputSource";
+
+ // XML namespace prefixes and URIs.
+ public static final String XMLNS_COLON = "xmlns:";
+ public static final String XPATH_CONTEXT_PREFIX = "context";
+ public static final String XPATH_CONTEXT_URI = "http://www.sun.com/java/jsr223/xpath/context";
+
+ private Document objectData;
+
+ public XPathScriptEngine() {
+ xpathFactory = XPathFactory.newInstance();
+ }
+
+ // my implementation for CompiledScript
+ private class XPathCompiledScript extends CompiledScript {
+ private XPathExpression expr;
+
+ XPathCompiledScript (XPathExpression expr) {
+ this.expr = expr;
+ }
+
+ public ScriptEngine getEngine() {
+ return XPathScriptEngine.this;
+ }
+
+ public Object eval(ScriptContext ctx) throws ScriptException {
+ return evalXPath(expr, ctx);
+ }
+ }
+
+ public CompiledScript compile (String script) throws ScriptException {
+ XPathExpression expr = compileXPath(script, context);
+ return new XPathCompiledScript(expr);
+ }
+
+ public CompiledScript compile (Reader reader) throws ScriptException {
+ return compile(readFully(reader));
+ }
+
+ public Object eval(String str, ScriptContext ctx)
+ throws ScriptException {
+ XPathExpression expr = compileXPath(str, ctx);
+ return evalXPath(expr, ctx);
+ }
+
+ public Object eval(Reader reader, ScriptContext ctx)
+ throws ScriptException {
+ return eval(readFully(reader), ctx);
+ }
+
+ public ScriptEngineFactory getFactory() {
+ synchronized (this) {
+ if (factory == null) {
+ factory = new XPathScriptEngineFactory();
+ }
+ }
+ return factory;
+ }
+
+ public Bindings createBindings() {
+ return new SimpleBindings();
+ }
+
+
+ void setFactory(ScriptEngineFactory factory) {
+ this.factory = factory;
+ }
+
+
+ // Internals only below this point
+
+ // find a variable of given qname in given context
+ private static Object findVariable(QName qname, ScriptContext ctx) {
+ String name;
+ int scope;
+
+ if (XPATH_CONTEXT_URI.equals(qname.getNamespaceURI())) {
+ name = qname.getLocalPart();
+ synchronized (ctx) {
+ scope = ctx.getAttributesScope(name);
+ if (scope != -1) {
+ return ctx.getAttribute(name, scope);
+ } // else fallthru
+ }
+ }
+ name = qname.getPrefix() + ":" + qname.getLocalPart();
+ synchronized (ctx) {
+ scope = ctx.getAttributesScope(name);
+ if (scope != -1) {
+ return ctx.getAttribute(name, scope);
+ } // else fallthru
+ }
+ return null;
+ }
+
+ private static void collectNamespaces(Map<String, String> map, Bindings scope) {
+ for (String key : scope.keySet()) {
+ if (key.startsWith(XMLNS_COLON)) {
+ Object uri = scope.get(key);
+ // collect all variables starting with "xmlns:" and
+ // collect the prefix to URI mappings.
+ String prefix = key.substring(XMLNS_COLON.length());
+ if (uri instanceof String) {
+ String tmp = (String) uri;
+ if (tmp.length() != 0) {
+ map.put(prefix, tmp);
+ }
+ }
+ }
+ }
+ }
+
+ private static NamespaceContext makeNamespaceContext(ScriptContext ctx) {
+ // namespace prefix-to-URI mappings
+ final Map<String, String> namespaces = new HashMap<String, String>();
+ for (int scope : ctx.getScopes()) {
+ Bindings bind = ctx.getBindings(scope);
+ if (bind != null) {
+ // TODO: See what needs to be done....
+ //collectNamespaces(namespaces, bind);
+ }
+ }
+
+ // look for mapping for default XML namespace
+ Object def = ctx.getAttribute(XMLConstants.XMLNS_ATTRIBUTE);
+ if (def instanceof String) {
+ namespaces.put(XMLConstants.DEFAULT_NS_PREFIX, (String)def);
+ }
+
+ // standard required mappings by XPath standard
+ namespaces.put(XMLConstants.XML_NS_PREFIX, XMLConstants.XML_NS_URI);
+ namespaces.put(XMLConstants.XMLNS_ATTRIBUTE, XMLConstants.XMLNS_ATTRIBUTE_NS_URI);
+
+ // add prefix mapping for XPATH_CONTEXT_PREFIX
+ namespaces.put(XPATH_CONTEXT_PREFIX, XPATH_CONTEXT_URI);
+
+ return new NamespaceContext() {
+ public String getNamespaceURI(String prefix) {
+ if (prefix == null) {
+ throw new IllegalArgumentException();
+ }
+ String uri = namespaces.get(prefix);
+ if (uri == null) {
+ return XMLConstants.NULL_NS_URI;
+ } else {
+ return uri;
+ }
+ }
+
+ public String getPrefix(String namespaceURI) {
+ if (namespaceURI == null) {
+ throw new IllegalArgumentException();
+ }
+ for (String prefix : namespaces.keySet()) {
+ String uri = namespaces.get(prefix);
+ if (namespaceURI.equals(uri)) {
+ return prefix;
+ }
+ }
+ return null;
+ }
+
+ public Iterator getPrefixes(String namespaceURI) {
+ if (namespaceURI == null) {
+ throw new IllegalArgumentException();
+ }
+ List list = new ArrayList();
+ for (String prefix : namespaces.keySet()) {
+ String uri = namespaces.get(prefix);
+ if (namespaceURI.equals(uri)) {
+ list.add(prefix);
+ }
+ }
+ return Collections.unmodifiableList(list).iterator();
+ }
+ };
+ }
+
+ private static XPathFunction makeXPathFunction(final Constructor ctr, int arity) {
+ if (ctr.getParameterTypes().length != arity) {
+ return null;
+ }
+ return new XPathFunction() {
+ public Object evaluate(List args) {
+ try {
+ return ctr.newInstance(args.toArray());
+ } catch (Exception exp) {
+ throw new RuntimeException(exp);
+ }
+ }
+ };
+ }
+
+ private static XPathFunction makeXPathFunction(final Method method, int arity) {
+ int modifiers = method.getModifiers();
+ int numArgs = method.getParameterTypes().length;
+ if (Modifier.isStatic(modifiers) && numArgs == arity) {
+ // static method. expose "as is".
+ return new XPathFunction() {
+ public Object evaluate(List args) {
+ try {
+ return method.invoke(null, args.toArray());
+ } catch (Exception exp) {
+ throw new RuntimeException(exp);
+ }
+ }
+ };
+ } else if ((numArgs + 1) == arity) {
+ // instance method. treat the first arg as 'this'
+ return new XPathFunction() {
+ public Object evaluate(List args) {
+ List tmp = args.subList(1, args.size());
+ try {
+ return method.invoke(args.get(0), tmp.toArray());
+ } catch (Exception exp) {
+ throw new RuntimeException(exp);
+ }
+ }
+ };
+ } else {
+ return null;
+ }
+ }
+
+ private static XPathFunction makeXPathFunction(final String funcName,
+ final Invocable invocable) {
+ return new XPathFunction() {
+ public Object evaluate(List args) {
+ try {
+ return invocable.invokeFunction(funcName, args.toArray());
+ } catch (Exception exp) {
+ throw new RuntimeException(exp);
+ }
+ }
+ };
+ }
+
+
+ // make a XPathFunction from given object
+ private static XPathFunction makeXPathFunction(QName qname, Object obj, int arity) {
+ if (obj == null) {
+ return null;
+ } else if (obj instanceof XPathFunction) {
+ // already XPathFunction - just return
+ return (XPathFunction) obj;
+ } else if (obj instanceof Method) {
+ // a Method object. wrap as XPathFunction
+ return makeXPathFunction((Method)obj, arity);
+ } else if (obj instanceof Constructor) {
+ // a Constructor object. wrap as XPathFunction
+ return makeXPathFunction((Constructor)obj, arity);
+ } else if (obj instanceof Invocable) {
+ // wrap a script function as XPathFunction. Using this,
+ // scripts from other languages (for eg. JavaScript) can use
+ // this engine and pass script functions as XPathFunction extensions
+
+ return makeXPathFunction(qname.getLocalPart(), (Invocable)obj);
+ } else {
+ // can't map the object as XPathFunction.
+ return null;
+ }
+ }
+
+ // Internals only below this point
+ private XPathExpression compileXPath(String str, final ScriptContext ctx)
+ throws ScriptException {
+ // JSR-223 requirement
+ ctx.setAttribute("context", ctx, ScriptContext.ENGINE_SCOPE);
+ try {
+ XPath xpath = xpathFactory.newXPath();
+ xpath.setXPathVariableResolver(new XPathVariableResolver() {
+ public Object resolveVariable(QName qname) {
+ return findVariable(qname, ctx);
+ }
+ });
+
+ xpath.setXPathFunctionResolver(new XPathFunctionResolver() {
+ public XPathFunction resolveFunction(QName qname, int arity) {
+ Object obj = findVariable(qname, ctx);
+ return makeXPathFunction(qname, obj, arity);
+ }
+ });
+ xpath.setNamespaceContext(makeNamespaceContext(ctx));
+ //xpath.setNamespaceContext(new BpmnFunctionResolver());
+ //xpath.setXPathFunctionResolver(new BpmnFunctionResolver());
+ int begin = str.indexOf("getObjectData") > -1 ? 14 : 0;
+ if (begin > 0 ) {
+ String objectDataRef = str.substring(begin+1, str.indexOf(")")-1);
+
+ objectData = (Document) ctx.getAttribute(objectDataRef);
+ //ctx.setAttribute(XPATH_INPUT_SRC, objectData , 100);
+
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ Source xmlSource = new DOMSource(objectData);
+ Result outputTarget = new StreamResult(outputStream);
+ TransformerFactory.newInstance().newTransformer().transform(xmlSource, outputTarget);
+ InputStream is = new ByteArrayInputStream(outputStream.toByteArray());
+ ctx.setReader(new InputStreamReader(is));
+
+ str = str.substring(str.indexOf(")")+1);
+ }
+ XPathExpression xpe = xpath.compile(str);
+ return xpe;
+ } catch (Exception exp) {
+ throw new ScriptException(exp);
+ }
+ }
+
+ private Object getVariable(ScriptContext ctx, String name) {
+ synchronized (ctx) {
+ int scope = ctx.getAttributesScope(name);
+ if (scope != -1) {
+ return ctx.getAttribute(name, scope);
+ }
+ }
+ return null;
+ }
+ private Object evalXPath(XPathExpression expr, final ScriptContext ctx)
+ throws ScriptException {
+
+ try {
+ Object resultType = getVariable(ctx, XPATH_RESULT_TYPE);
+ Object input = getVariable(ctx, XPATH_INPUT_SRC);
+
+ InputSource src;
+ if (input == null) {
+ // no input specified, use context reader
+ src = new InputSource(ctx.getReader());
+ } else {
+ // explicit InputSource specified
+ if (input instanceof InputSource) {
+ src = (InputSource) input;
+ } else if (input instanceof String) {
+ src = new InputSource((String)input);
+ } else if (input instanceof Reader) {
+ src = new InputSource((Reader)input);
+ } else if (input instanceof InputStream) {
+ src = new InputSource((InputStream)input);
+ } else {
+ // some other object input type specified (Node/NodeList)
+ src = null;
+ }
+ }
+
+ resultType = XPathConstants.BOOLEAN;
+
+ if (resultType instanceof QName) {
+ return (src != null) ?
+ expr.evaluate(src, (QName) resultType) :
+ expr.evaluate(input, (QName) resultType);
+ } else {
+ return (src != null) ?
+ expr.evaluate(src) :
+ expr.evaluate(input);
+ }
+ } catch (Exception exp) {
+ throw new ScriptException(exp);
+ }
+ }
+
+ private String readFully(Reader reader) throws ScriptException {
+ char[] arr = new char[8*1024]; // 8K at a time
+ StringBuilder buf = new StringBuilder();
+ int numChars;
+ try {
+ while ((numChars = reader.read(arr, 0, arr.length)) > 0) {
+ buf.append(arr, 0, numChars);
+ }
+ } catch (IOException exp) {
+ throw new ScriptException(exp);
+ }
+ return buf.toString();
+ }
+}
Added: jbpm4/trunk/modules/bpmn/src/main/java/com/sun/script/xpath/XPathScriptEngineFactory.java
===================================================================
--- jbpm4/trunk/modules/bpmn/src/main/java/com/sun/script/xpath/XPathScriptEngineFactory.java (rev 0)
+++ jbpm4/trunk/modules/bpmn/src/main/java/com/sun/script/xpath/XPathScriptEngineFactory.java 2009-08-03 18:34:11 UTC (rev 5415)
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met: Redistributions of source code
+ * must retain the above copyright notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution. Neither the name of the Sun Microsystems nor the names of
+ * is contributors may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * XPathScriptEngineFactory.java
+ * @author A. Sundararajan
+ */
+
+package com.sun.script.xpath;
+
+import javax.script.*;
+import java.util.*;
+
+public class XPathScriptEngineFactory implements ScriptEngineFactory {
+ public String getEngineName() {
+ return "xpath";
+ }
+
+ public String getEngineVersion() {
+ return "1.0";
+ }
+
+ public List<String> getExtensions() {
+ return extensions;
+ }
+
+ public String getLanguageName() {
+ return "jaxp";
+ }
+
+ public String getLanguageVersion() {
+ return "1.4";
+ }
+
+ public String getMethodCallSyntax(String obj, String m, String... args) {
+ throw new UnsupportedOperationException("getMethodCallSyntax");
+ }
+
+ public List<String> getMimeTypes() {
+ return mimeTypes;
+ }
+
+ public List<String> getNames() {
+ return names;
+ }
+
+ public String getOutputStatement(String str) {
+ throw new UnsupportedOperationException("getOutputStatement");
+ }
+
+ public String getParameter(String key) {
+ if (key.equals(ScriptEngine.ENGINE)) {
+ return getEngineName();
+ } else if (key.equals(ScriptEngine.ENGINE_VERSION)) {
+ return getEngineVersion();
+ } else if (key.equals(ScriptEngine.NAME)) {
+ return getEngineName();
+ } else if (key.equals(ScriptEngine.LANGUAGE)) {
+ return getLanguageName();
+ } else if (key.equals(ScriptEngine.LANGUAGE_VERSION)) {
+ return getLanguageVersion();
+ } else if (key.equals("THREADING")) {
+ return "MULTITHREADED";
+ } else {
+ return null;
+ }
+ }
+
+ public String getProgram(String... statements) {
+ throw new UnsupportedOperationException("getProgram");
+ }
+
+ public ScriptEngine getScriptEngine() {
+ XPathScriptEngine engine = new XPathScriptEngine();
+ engine.setFactory(this);
+ return engine;
+ }
+
+ private static List<String> names;
+ private static List<String> extensions;
+ private static List<String> mimeTypes;
+ static {
+ names = new ArrayList<String>(1);
+ names.add("xpath");
+ names = Collections.unmodifiableList(names);
+ extensions = names;
+ mimeTypes = new ArrayList<String>(0);
+ mimeTypes = Collections.unmodifiableList(mimeTypes);
+ }
+}
Modified: jbpm4/trunk/modules/bpmn/src/main/java/org/jbpm/bpmn/flownodes/BpmnActivity.java
===================================================================
--- jbpm4/trunk/modules/bpmn/src/main/java/org/jbpm/bpmn/flownodes/BpmnActivity.java 2009-07-31 22:09:42 UTC (rev 5414)
+++ jbpm4/trunk/modules/bpmn/src/main/java/org/jbpm/bpmn/flownodes/BpmnActivity.java 2009-08-03 18:34:11 UTC (rev 5415)
@@ -24,10 +24,13 @@
import java.util.ArrayList;
import java.util.List;
+import javax.xml.xpath.XPathFactory;
+
import org.jbpm.api.Execution;
import org.jbpm.api.JbpmException;
import org.jbpm.api.activity.ActivityBehaviour;
import org.jbpm.bpmn.parser.BindingsParser;
+import org.jbpm.bpmn.xpath.BpmnFunctionResolver;
import org.jbpm.internal.log.Log;
import org.jbpm.pvm.internal.model.Activity;
import org.jbpm.pvm.internal.model.Condition;
@@ -50,7 +53,10 @@
private static final boolean FORK_DISALLOWED = !FORK_ALLOWED;
private static final boolean CONDITIONS_CHECKED = true;
private static final boolean CONDITIONS_IGNORED = !CONDITIONS_CHECKED;
+
+ private final XPathFactory xpathFactory = XPathFactory.newInstance();
+
protected void leaveBpmnActivity(ExecutionImpl execution) {
proceedForkedIfAllowed(execution, FORK_ALLOWED, CONDITIONS_CHECKED, null);
@@ -58,7 +64,6 @@
}
protected void leaveBpmnActivitySingle(ExecutionImpl execution, String default_) {
-
proceedForkedIfAllowed(execution, FORK_DISALLOWED, CONDITIONS_CHECKED, default_);
}
@@ -75,13 +80,20 @@
* Code copied basically from jPDL fork.
*/
private void proceedForkedIfAllowed(ExecutionImpl execution, boolean forkAllowed, boolean checkConditions, String default_) {
+ log.debug("Proceeding");
Activity activity = execution.getActivity();
+
+// xpathFactory.setXPathFunctionResolver(new BpmnFunctionResolver());
+// xpath
// evaluate the conditions and find the transitions that should be forked
List<Transition> forkingTransitions = new ArrayList<Transition>();
List<Transition> outgoingTransitions = activity.getOutgoingTransitions();
+ log.debug("Analyzing "+ outgoingTransitions.size() + " transitions for " + activity.getName());
for (Transition transition : outgoingTransitions) {
+ log.debug("Analyzing "+ transition.getName());
Condition condition = transition.getCondition();
+ //condition.evaluate(execution); log.debug("Evaluated");
// also ignore the default transition of the exclusive gateway
if (((condition == null) || (!checkConditions) || (condition.evaluate(execution))) && (!transition.getName().equals(default_))) {
forkingTransitions.add(transition);
Modified: jbpm4/trunk/modules/bpmn/src/test/java/org/jbpm/bpmn/flownodes/ExclusiveGatewayTest.java
===================================================================
--- jbpm4/trunk/modules/bpmn/src/test/java/org/jbpm/bpmn/flownodes/ExclusiveGatewayTest.java 2009-07-31 22:09:42 UTC (rev 5414)
+++ jbpm4/trunk/modules/bpmn/src/test/java/org/jbpm/bpmn/flownodes/ExclusiveGatewayTest.java 2009-08-03 18:34:11 UTC (rev 5415)
@@ -21,16 +21,24 @@
*/
package org.jbpm.bpmn.flownodes;
+import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.dom4j.DocumentFactory;
import org.jbpm.api.ProcessInstance;
import org.jbpm.api.TaskQuery;
import org.jbpm.api.task.Task;
import org.jbpm.bpmn.parser.BpmnParser;
+import org.jbpm.pvm.internal.util.XmlUtil;
import org.jbpm.pvm.internal.xml.Problem;
import org.jbpm.test.JbpmTestCase;
+import org.w3c.dom.Document;
+import org.xml.sax.SAXException;
/**
* @author Tom Baeyens
@@ -56,6 +64,15 @@
}
}
+ public void testNormalXPath() {
+
+ List<Problem> problems = parse("org/jbpm/bpmn/flownodes/exclusiveGatewayXPath.bpmn.xml");
+
+ if (!problems.isEmpty()) {
+ fail("No problems should have occured. Problems: " + problems);
+ }
+ }
+
public void testNormalExecuteDecisionCondition() {
String deploymentId = repositoryService.createDeployment().addResourceFromClasspath("org/jbpm/bpmn/flownodes/exclusiveGateway.bpmn.xml").deploy();
@@ -115,8 +132,46 @@
repositoryService.deleteDeploymentCascade(deploymentId);
}
}
+
+ public void testNormalExecuteDecisionConditionXPath() {
+ String deploymentId = repositoryService.createDeployment().addResourceFromClasspath("org/jbpm/bpmn/flownodes/exclusiveGatewayXPath.bpmn.xml").deploy();
+ try {
+ Map variables = new HashMap();
+ Document objectData;
+
+ objectData = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(this.getClass().getResourceAsStream("xmlTestDocument.xml"));
+ variables.put("test", objectData);
+
+ ProcessInstance pi = executionService.startProcessInstanceByKey("ExclusiveGateway", variables );
+ String pid = pi.getId();
+
+ TaskQuery taskQuery = taskService.createTaskQuery();
+ List<Task> allTasks = taskQuery.list();
+
+ assertEquals(1, allTasks.size());
+ assertEquals("doSomething", allTasks.get(0).getActivityName());
+
+ taskService.completeTask( allTasks.get(0).getId());
+
+ // process instance should be ended
+ pi = executionService.findProcessInstanceById(pid);
+ assertNull(pi);
+
+ } catch (SAXException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (ParserConfigurationException e) {
+ e.printStackTrace();
+ }
+ finally {
+ repositoryService.deleteDeploymentCascade(deploymentId);
+ }
+ }
+
+
public void testNonBoundDefault() {
List<Problem> problems = parse("org/jbpm/bpmn/flownodes/exclusiveGatewayNonBoundDefault.bpmn.xml");
Added: jbpm4/trunk/modules/bpmn/src/test/resources/org/jbpm/bpmn/flownodes/exclusiveGatewayXPath.bpmn.xml
===================================================================
--- jbpm4/trunk/modules/bpmn/src/test/resources/org/jbpm/bpmn/flownodes/exclusiveGatewayXPath.bpmn.xml (rev 0)
+++ jbpm4/trunk/modules/bpmn/src/test/resources/org/jbpm/bpmn/flownodes/exclusiveGatewayXPath.bpmn.xml 2009-08-03 18:34:11 UTC (rev 5415)
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<bpmn:definitions id="ExclusiveGatewayNormal"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://schema.omg.org/spec/BPMN/2.0 ../../../../../../main/resources/BPMN20.xsd"
+ xmlns:bpmn="http://schema.omg.org/spec/BPMN/2.0" typeLanguage="http://www.w3.org/2001/XMLSchema"
+ expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://sample.bpmn.camunda.com/">
+
+ <bpmn:process id="ExclusiveGateway" name="ExclusiveGateway">
+ <!-- Start-Event -->
+ <bpmn:startEvent id="Start" />
+
+ <bpmn:sequenceFlow id="flow1" sourceRef="Start"
+ targetRef="exclusiveGatewayDecision" name="Start->exclusiveGateway" />
+
+ <bpmn:exclusiveGateway id="exclusiveGatewayDecision"
+ name="Just a gateway" default="flow3"/>
+
+ <!-- Sequence Flow -->
+
+ <bpmn:sequenceFlow id="flow2" sourceRef="exclusiveGatewayDecision"
+ targetRef="doSomething">
+ <bpmn:conditionExpression xsi:type="bpmn:tFormalExpression" language="xpath">getObjectData("test")/root/child1/text()="just"</bpmn:conditionExpression>
+ </bpmn:sequenceFlow>
+ <bpmn:sequenceFlow id="flow3" sourceRef="exclusiveGatewayDecision"
+ targetRef="doSomethingElse">
+ </bpmn:sequenceFlow>
+
+ <bpmn:userTask id="doSomething" name="Anything at all"
+ implementation="other"></bpmn:userTask>
+ <bpmn:sequenceFlow id="flow4" sourceRef="doSomething"
+ targetRef="End" />
+
+ <bpmn:userTask id="doSomethingElse" name="But completely different"
+ implementation="other" />
+ <bpmn:sequenceFlow id="flow5" sourceRef="doSomethingElse"
+ targetRef="End" />
+
+ <!-- End Events -->
+ <bpmn:endEvent id="End" name="End" />
+ </bpmn:process>
+</bpmn:definitions>
Added: jbpm4/trunk/modules/bpmn/src/test/resources/org/jbpm/bpmn/flownodes/xmlTestDocument.xml
===================================================================
--- jbpm4/trunk/modules/bpmn/src/test/resources/org/jbpm/bpmn/flownodes/xmlTestDocument.xml (rev 0)
+++ jbpm4/trunk/modules/bpmn/src/test/resources/org/jbpm/bpmn/flownodes/xmlTestDocument.xml 2009-08-03 18:34:11 UTC (rev 5415)
@@ -0,0 +1,6 @@
+<root>
+ <child1>just</child1>
+ <child2>for</child2>
+ <child3>demo</child3>
+ <child4>purposes</child4>
+</root>
\ No newline at end of file
More information about the jbpm-commits
mailing list