[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