diff --git a/open-bpmn.metamodel/src/main/java/org/openbpmn/bpmn/BPMNModel.java b/open-bpmn.metamodel/src/main/java/org/openbpmn/bpmn/BPMNModel.java index 4f0bcf39..4df3392e 100644 --- a/open-bpmn.metamodel/src/main/java/org/openbpmn/bpmn/BPMNModel.java +++ b/open-bpmn.metamodel/src/main/java/org/openbpmn/bpmn/BPMNModel.java @@ -1499,7 +1499,7 @@ public void save(File file) { } // finally write the xml to disk - writeXml(doc, output); + writeToOutputStream(doc, output); } catch (TransformerException | IOException e) { logger.warning("Failed to save BPMN file: " + e.getMessage()); e.printStackTrace(); @@ -1539,7 +1539,7 @@ public void save(String filePath) { } // finally write the xml to disk - writeXml(doc, output); + writeToOutputStream(doc, output); } catch (TransformerException | IOException e) { logger.warning("Failed to save BPMN file: " + e.getMessage()); e.printStackTrace(); @@ -2004,7 +2004,7 @@ private void loadMessageList() throws BPMNModelException { * @param output * @throws TransformerException */ - private void writeXml(Document doc, OutputStream output) throws TransformerException { + public void writeToOutputStream(Document doc, OutputStream output) throws TransformerException { TransformerFactory transformerFactory = TransformerFactory.newInstance(); Transformer transformer = transformerFactory.newTransformer(); DOMSource source = new DOMSource(doc); diff --git a/open-bpmn.metamodel/src/main/java/org/openbpmn/bpmn/exceptions/BPMNModelException.java b/open-bpmn.metamodel/src/main/java/org/openbpmn/bpmn/exceptions/BPMNModelException.java index 2e18f207..9339285e 100644 --- a/open-bpmn.metamodel/src/main/java/org/openbpmn/bpmn/exceptions/BPMNModelException.java +++ b/open-bpmn.metamodel/src/main/java/org/openbpmn/bpmn/exceptions/BPMNModelException.java @@ -29,16 +29,18 @@ package org.openbpmn.bpmn.exceptions; /** - * BPMNModelException is the abstract super class for all BPMN - * Exception classes. A BPMNModelException signals an error in the Model + * BPMNModelException is the abstract super class for all BPMN + * Exception classes. A BPMNModelException signals an error in the Model * logic. BPMNModelException need to be caught. * * @author rsoika */ public abstract class BPMNModelException extends Exception { + public static final String INVALID_MODEL = "INVALID_MODEL"; + private static final long serialVersionUID = 1L; - + protected String errorContext = "UNDEFINED"; protected String errorCode = "UNDEFINED"; diff --git a/open-bpmn.metamodel/src/main/java/org/openbpmn/bpmn/navigation/BPMNFlowIterator.java b/open-bpmn.metamodel/src/main/java/org/openbpmn/bpmn/navigation/BPMNFlowIterator.java deleted file mode 100644 index a7fbd282..00000000 --- a/open-bpmn.metamodel/src/main/java/org/openbpmn/bpmn/navigation/BPMNFlowIterator.java +++ /dev/null @@ -1,54 +0,0 @@ -package org.openbpmn.bpmn.navigation; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.function.Predicate; - -import org.openbpmn.bpmn.elements.SequenceFlow; -import org.openbpmn.bpmn.elements.core.BPMNElementNode; - -public class BPMNFlowIterator implements Iterator { - - private Predicate filter; - private int index; - BPMNElementNode bpmnElementNode = null; - List outgoingFlows; - Iterator flowIterator; - BPMNElementNode targetNode = null; - - public BPMNFlowIterator(BPMNElementNode bpmnElementNode, Predicate filter) { - this.bpmnElementNode = bpmnElementNode; - this.filter = filter; - this.index = 0; - - // find outgoing flows - outgoingFlows = new ArrayList<>(bpmnElementNode.getOutgoingSequenceFlows()); - - } - - @Override - public boolean hasNext() { - while (index < outgoingFlows.size()) { - - SequenceFlow flow = outgoingFlows.get(index); - - targetNode = flow.getTargetElement(); - - if (filter.test(targetNode)) { - return true; - } - index++; - } - return false; - } - - @Override - public BPMNElementNode next() { - if (!hasNext()) { - throw new IllegalStateException("No more elements"); - } - index++; - return (BPMNElementNode) targetNode; - } -} diff --git a/open-bpmn.metamodel/src/main/java/org/openbpmn/bpmn/navigation/BPMNFlowNavigator.java b/open-bpmn.metamodel/src/main/java/org/openbpmn/bpmn/navigation/BPMNFlowNavigator.java index 95b33777..bd3b0384 100644 --- a/open-bpmn.metamodel/src/main/java/org/openbpmn/bpmn/navigation/BPMNFlowNavigator.java +++ b/open-bpmn.metamodel/src/main/java/org/openbpmn/bpmn/navigation/BPMNFlowNavigator.java @@ -1,69 +1,167 @@ package org.openbpmn.bpmn.navigation; import java.util.ArrayList; +import java.util.Comparator; import java.util.Iterator; +import java.util.LinkedHashSet; import java.util.List; +import java.util.Set; import java.util.function.Predicate; +import java.util.logging.Logger; +import org.openbpmn.bpmn.elements.Gateway; import org.openbpmn.bpmn.elements.SequenceFlow; import org.openbpmn.bpmn.elements.core.BPMNElementNode; import org.openbpmn.bpmn.exceptions.BPMNValidationException; +/** + * The BPMNFlowNavigator can be used to navigate through a BPMN model. Based on + * a Source BPMNElement the navigator routes to the next Flow Element fulfilling + * a + * given criteria. For example you can find all Event Nodes followed by an + * Activity Node. Or you can navigate to the next Activity from an Event. + *

+ * The BPMNFlowNavigator expects a filter argument (Functional Interface + * Predicate) with one BPMNElementNode argument that return a boolean value. + *

+ * In case the filter does not specify a Gateway, Gateway Nodes are ignored. + * + */ public class BPMNFlowNavigator implements Iterator { - private Predicate filter; + protected static Logger logger = Logger.getLogger(BPMNElementNode.class.getName()); + + private Predicate filter = null; + private Predicate conditionEvaluator = null; private int index; BPMNElementNode bpmnElementNode = null; List outgoingFlows; - Iterator flowIterator; - BPMNElementNode targetNode = null; + private List targetNodes; + /** + * Creates a new BPMNFlowNavigator with a given filter criteria. + * The method collects all BPMNElements following the given start element and + * matching the given filter + * + * @param bpmnElementNode + * @param filter + * @throws BPMNValidationException + */ public BPMNFlowNavigator(BPMNElementNode bpmnElementNode, Predicate filter) throws BPMNValidationException { - this.bpmnElementNode = bpmnElementNode; this.filter = filter; + this.targetNodes = new ArrayList<>(); this.index = 0; - - // find outgoing flows - outgoingFlows = new ArrayList<>(bpmnElementNode.getOutgoingSequenceFlows()); - - // if we have more than one outgoing flow, we thrown an exception - if (outgoingFlows.size() > 1) { - throw new BPMNValidationException( - "Element '" + bpmnElementNode.getId() + "' should not have more than one outgoing SequenceFlow!"); - } - + // find all elements + findValidNodes(bpmnElementNode); } - public BPMNElementNode findTarget(Predicate filter) { - BPMNElementNode result = null; - - return result; + /** + * Creates a new BPMNFlowNavigator with a given filter criteria. + * The method collects all BPMNElements following the given start element and + * matching the given filter + * + * @param bpmnElementNode + * @param filter + * @param conditionEvaluator optional conditional evaluator + * @throws BPMNValidationException + */ + public BPMNFlowNavigator(BPMNElementNode bpmnElementNode, Predicate filter, + Predicate conditionEvaluator) + throws BPMNValidationException { + this.filter = filter; + this.conditionEvaluator = conditionEvaluator; + this.targetNodes = new ArrayList<>(); + this.index = 0; + // find all elements + findValidNodes(bpmnElementNode); } @Override public boolean hasNext() { - while (index < outgoingFlows.size()) { + return index < targetNodes.size(); + } - SequenceFlow flow = outgoingFlows.get(index); + @Override + public BPMNElementNode next() { + if (!hasNext()) { + throw new IllegalStateException("No more elements"); + } + return targetNodes.get(index++); + } - targetNode = flow.getTargetElement(); + /** + * Iterates tough all outgoing sequence flows and tests if the target element + * matches the filter criteria. + *

+ * If a element does not match the filter criteria and is an instance of a + * Gateway, the method will recursive call all following elements of the gateway + * node. + * + * @param currentNode + */ + private void findValidNodes(BPMNElementNode currentNode) { + Set flowSet = currentNode.getOutgoingSequenceFlows(); + // Check if the sequence flow has a condition and evaluate it if a + // conditionEvaluator is defined + if (currentNode instanceof Gateway && conditionEvaluator != null) { + flowSet = filterConditionalFlows((Gateway) currentNode, flowSet); + } - if (filter.test(targetNode)) { - return true; + for (SequenceFlow flow : flowSet) { + BPMNElementNode node = flow.getTargetElement(); + if (filter.test(node)) { + targetNodes.add(node); + } else { + // if the node is a Gateway, recursively search its outgoing flows + if (node instanceof Gateway) { + findValidNodes(node); + } } - index++; + } - return false; } - @Override - public BPMNElementNode next() { - if (!hasNext()) { - throw new IllegalStateException("No more elements"); + /** + * This method filters all conditional flows outgoing from a gateway that did + * not eval to true by the given conditionEvaluator. The result is a Set with + * exactly one flow ! + * + * + * @return + */ + private Set filterConditionalFlows(Gateway gateway, Set flowSet) { + LinkedHashSet result = new LinkedHashSet(); + + List sortedList = new ArrayList<>(flowSet); + // Sort the list using a comparator that places empty conditions at the end + sortedList.sort(Comparator.comparing(flow -> { + String condition = flow.getConditionExpression(); + return (condition == null || condition.trim().isEmpty()) ? 1 : 0; + })); + + // now we eval each condition. As soon as we have a match or the condition is + // empty we stop. + for (SequenceFlow flow : sortedList) { + String condition = flow.getConditionExpression(); + if (condition != null && (conditionEvaluator.test(condition) == true)) { + // the condition matches - return this as the result; + result.add(flow); + return result; + + } + // In case the condition is empty this is the default flow... + if (condition == null || condition.trim().isEmpty()) { + // default condition + result.add(flow); + return result; + } } - // return (T) outgoingFlows.get(index++); - index++; - return targetNode; + // no match - should not happen + logger.warning("Gateway " + gateway.getName() + " (" + gateway.getId() + + ") has conditional flows but non of the outgoing sequence flows is matching the condition!"); + return result; + } + } diff --git a/open-bpmn.metamodel/src/main/java/org/openbpmn/bpmn/util/BPMNModelFactory.java b/open-bpmn.metamodel/src/main/java/org/openbpmn/bpmn/util/BPMNModelFactory.java index a8abf1a5..460ce532 100644 --- a/open-bpmn.metamodel/src/main/java/org/openbpmn/bpmn/util/BPMNModelFactory.java +++ b/open-bpmn.metamodel/src/main/java/org/openbpmn/bpmn/util/BPMNModelFactory.java @@ -12,6 +12,7 @@ import javax.xml.parsers.ParserConfigurationException; import org.openbpmn.bpmn.BPMNModel; +import org.openbpmn.bpmn.exceptions.BPMNInvalidIDException; import org.openbpmn.bpmn.exceptions.BPMNModelException; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -139,8 +140,14 @@ public static BPMNModel read(String modelFilePath) throws BPMNModelException { */ public static BPMNModel read(InputStream is) throws BPMNModelException { logger.fine("read from inputStream..."); - DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); - docFactory.setIgnoringElementContentWhitespace(true); // because of a bug this does not have any effect! + if (is == null) { + throw new BPMNInvalidIDException(BPMNModelException.INVALID_MODEL, + "Model can not be parsed: InputStream is null"); + } + DocumentBuilderFactory docFactory = DocumentBuilderFactory + .newInstance(); + docFactory.setIgnoringElementContentWhitespace(true); // because of a bug this does not have + // any effect! docFactory.setNamespaceAware(true); try { diff --git a/open-bpmn.metamodel/src/test/java/org/openbpmn/metamodel/navigation/TestNavigation.java b/open-bpmn.metamodel/src/test/java/org/openbpmn/metamodel/navigation/TestNavigation.java index 68a7c6f6..40a9509f 100644 --- a/open-bpmn.metamodel/src/test/java/org/openbpmn/metamodel/navigation/TestNavigation.java +++ b/open-bpmn.metamodel/src/test/java/org/openbpmn/metamodel/navigation/TestNavigation.java @@ -4,153 +4,215 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; -import java.util.Set; +import java.util.ArrayList; +import java.util.List; import java.util.logging.Logger; import org.junit.jupiter.api.Test; import org.openbpmn.bpmn.BPMNModel; -import org.openbpmn.bpmn.BPMNTypes; import org.openbpmn.bpmn.elements.Activity; import org.openbpmn.bpmn.elements.BPMNProcess; import org.openbpmn.bpmn.elements.Event; +import org.openbpmn.bpmn.elements.Gateway; import org.openbpmn.bpmn.elements.core.BPMNElementNode; import org.openbpmn.bpmn.exceptions.BPMNModelException; -import org.openbpmn.bpmn.navigation.BPMNFlowIterator; import org.openbpmn.bpmn.navigation.BPMNFlowNavigator; import org.openbpmn.bpmn.util.BPMNModelFactory; import org.openbpmn.metamodel.examples.TestCreateEdges; +/** + * Test class to test simple navigation cases. + * + */ public class TestNavigation { private static Logger logger = Logger.getLogger(TestCreateEdges.class.getName()); /** - * Loads a model and navigates.... + * This test loads model 'refmodel-navigation-01.bpmn' and finds all events + * followed by task-1. * * @throws BPMNModelException * */ @Test - public void testSimpleNavigation() throws BPMNModelException { + public void testFindAllEventsFromTask1() throws BPMNModelException { logger.info("...read model"); - BPMNModel model = BPMNModelFactory.read("/refmodel-15.bpmn"); + BPMNModel model = BPMNModelFactory.read("/refmodel-navigation-01.bpmn"); assertEquals(1, model.getProcesses().size()); BPMNProcess process = model.openDefaultProces(); // get Task1 BPMNElementNode task1 = process.findElementNodeById("task_SBK01w"); - assertNotNull(task1); - BPMNFlowIterator eventNavigator = new BPMNFlowIterator(task1, + BPMNFlowNavigator eventNavigator = new BPMNFlowNavigator(task1, n -> n instanceof Event); - assertNotNull(eventNavigator); + // we expect 3 Event Nodes + + List elementNames = new ArrayList(); while (eventNavigator.hasNext()) { - System.out.println(eventNavigator.next().getId()); + Event event = (Event) eventNavigator.next(); + elementNames.add(event.getName()); } + + assertEquals(2, elementNames.size()); + assertTrue(elementNames.contains("Submit")); + assertTrue(elementNames.contains("Forward and submit")); + } /** - * Loads a model and navigates.... - * - * Event-7 : target should be Task-2 + * This test loads model 'refmodel-navigation-01.bpmn' and finds the target task + * of Event-2 * * @throws BPMNModelException * */ @Test - public void testSimpleEventNavigation() throws BPMNModelException { + public void testFindTargetFromEvent2() throws BPMNModelException { logger.info("...read model"); - BPMNModel model = BPMNModelFactory.read("/refmodel-15.bpmn"); + BPMNModel model = BPMNModelFactory.read("/refmodel-navigation-01.bpmn"); assertEquals(1, model.getProcesses().size()); BPMNProcess process = model.openDefaultProces(); - // get Event5 - BPMNElementNode event5 = process.findElementNodeById("event_cFt0jw"); + // get Event2 + BPMNElementNode event2 = process.findElementNodeById("event_IyD2LA"); + assertNotNull(event2); - assertNotNull(event5); + BPMNFlowNavigator taskNavigator = new BPMNFlowNavigator(event2, + n -> n instanceof Activity); + assertNotNull(taskNavigator); - // find next task or event..... - BPMNFlowNavigator eventNavigator = new BPMNFlowNavigator(event5, - n -> ((n instanceof Event) || (n instanceof Activity))); + // we expect 3 Event Nodes - // We expect the Task 2 as the next target. - assertNotNull(eventNavigator); - BPMNElementNode nextNode = eventNavigator.next(); - assertNotNull(nextNode); - assertTrue(nextNode instanceof Activity); - assertEquals("task_1gbByA", nextNode.getId()); + List elementNames = new ArrayList(); + while (taskNavigator.hasNext()) { + Activity task = (Activity) taskNavigator.next(); + elementNames.add(task.getName()); + } + + assertEquals(1, elementNames.size()); + assertTrue(elementNames.contains("Task-2")); } /** - * Loads a model and navigates.... - * - * Event-7 : target should be Task-2 + * This test loads model 'refmodel-navigation-01.bpmn' and finds the target task + * of Event-1. Here we have a follow up event. So no result is expected here! * * @throws BPMNModelException * */ @Test - public void testTargetNavigation() throws BPMNModelException { + public void testFindTargetFromEvent1() throws BPMNModelException { logger.info("...read model"); - BPMNModel model = BPMNModelFactory.read("/refmodel-15.bpmn"); + BPMNModel model = BPMNModelFactory.read("/refmodel-navigation-01.bpmn"); assertEquals(1, model.getProcesses().size()); BPMNProcess process = model.openDefaultProces(); - // get Event7 - BPMNElementNode event7 = process.findElementNodeById("event_H4GvRQ"); + // get Event2 + BPMNElementNode event1 = process.findElementNodeById("event_TGi3FA"); + assertNotNull(event1); - assertNotNull(event7); + BPMNFlowNavigator taskNavigator = new BPMNFlowNavigator(event1, + n -> n instanceof Activity); + assertNotNull(taskNavigator); - BPMNFlowNavigator eventNavigator = new BPMNFlowNavigator(event7, - n -> n instanceof Event); + // we expect 3 Event Nodes - assertNotNull(eventNavigator); + List elementNames = new ArrayList(); + while (taskNavigator.hasNext()) { + Activity task = (Activity) taskNavigator.next(); + elementNames.add(task.getName()); + } + + assertEquals(0, elementNames.size()); } /** - * This class navigates from a Link Throw Event to a Link Catch event + * This test loads model 'refmodel-navigation-02.bpmn' and finds all events + * followed by task-1. In this case whe have Gateway between the Source task and + * the events. * - * It is a example implementation of a navigator linking two events + * @throws BPMNModelException * */ - class LinkNavigator { + @Test + public void testFindAllEventsFromTask1ByGateway() throws BPMNModelException { + + logger.info("...read model"); + BPMNModel model = BPMNModelFactory.read("/refmodel-navigation-02.bpmn"); + + assertEquals(1, model.getProcesses().size()); + BPMNProcess process = model.openDefaultProces(); + + // get Task1 + BPMNElementNode task1 = process.findElementNodeById("task_SBK01w"); + assertNotNull(task1); - public BPMNElementNode findNext(BPMNElementNode node) { + BPMNFlowNavigator eventNavigator = new BPMNFlowNavigator(task1, + n -> n instanceof Event); + assertNotNull(eventNavigator); - // is it a throw event? - if (BPMNTypes.THROW_EVENT.equals(node.getType())) { + // we expect 3 Event Nodes - String linkName = node.getName(); + List elementNames = new ArrayList(); + while (eventNavigator.hasNext()) { + Event event = (Event) eventNavigator.next(); + elementNames.add(event.getName()); + } - // now find the corresponding first catch event with the same name + assertEquals(3, elementNames.size()); + assertTrue(elementNames.contains("Event-1")); + assertTrue(elementNames.contains("Event-2")); + assertTrue(elementNames.contains("Event-3")); - Set filteredElementList = node.getBpmnProcess() - .findElementNodes( - n -> (BPMNTypes.CATCH_EVENT.equals(n.getType()) // - && ((Event) n).getEventDefinitionsByType(BPMNTypes.EVENT_DEFINITION_LINK) - .size() > 0 // - && linkName.equals(n.getName()))); + } - // return the first one... - if (filteredElementList != null && filteredElementList.size() > 0) { - return filteredElementList.iterator().next(); - } + /** + * This test loads model 'refmodel-navigation-02.bpmn' and finds the gateway + * followed by task-1. + * + * @throws BPMNModelException + * + */ + @Test + public void testFindGatewayFromTask1() throws BPMNModelException { - } + logger.info("...read model"); + BPMNModel model = BPMNModelFactory.read("/refmodel-navigation-02.bpmn"); - // no match - return null; + assertEquals(1, model.getProcesses().size()); + BPMNProcess process = model.openDefaultProces(); + + // get Task1 + BPMNElementNode task1 = process.findElementNodeById("task_SBK01w"); + assertNotNull(task1); + + BPMNFlowNavigator eventNavigator = new BPMNFlowNavigator(task1, + n -> n instanceof Gateway); + assertNotNull(eventNavigator); + + // we expect 3 Event Nodes + + List elementNames = new ArrayList(); + while (eventNavigator.hasNext()) { + Gateway gateway = (Gateway) eventNavigator.next(); + elementNames.add(gateway.getName()); } + assertEquals(1, elementNames.size()); + assertTrue(elementNames.contains("Gateway-1")); + } + } diff --git a/open-bpmn.metamodel/src/test/java/org/openbpmn/metamodel/navigation/TestNavigationCallbacks.java b/open-bpmn.metamodel/src/test/java/org/openbpmn/metamodel/navigation/TestNavigationCallbacks.java new file mode 100644 index 00000000..221b9931 --- /dev/null +++ b/open-bpmn.metamodel/src/test/java/org/openbpmn/metamodel/navigation/TestNavigationCallbacks.java @@ -0,0 +1,136 @@ +package org.openbpmn.metamodel.navigation; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Logger; + +import org.junit.jupiter.api.Test; +import org.openbpmn.bpmn.BPMNModel; +import org.openbpmn.bpmn.elements.BPMNProcess; +import org.openbpmn.bpmn.elements.Event; +import org.openbpmn.bpmn.elements.core.BPMNElementNode; +import org.openbpmn.bpmn.exceptions.BPMNModelException; +import org.openbpmn.bpmn.navigation.BPMNFlowNavigator; +import org.openbpmn.bpmn.util.BPMNModelFactory; +import org.openbpmn.metamodel.examples.TestCreateEdges; + +/** + * Test class to test navigation cases with complex callback methods. + * + */ +public class TestNavigationCallbacks { + private static Logger logger = Logger.getLogger(TestCreateEdges.class.getName()); + + /** + * This test loads model 'refmodel-navigation-01.bpmn' and finds all events with + * the word Submit in its name + * + * + * @throws BPMNModelException + * + */ + @Test + public void testFindAllEventsFromTask1WithComplexRule() throws BPMNModelException { + + logger.info("...read model"); + BPMNModel model = BPMNModelFactory.read("/refmodel-navigation-01.bpmn"); + + assertEquals(1, model.getProcesses().size()); + BPMNProcess process = model.openDefaultProces(); + + // get Task1 + BPMNElementNode task1 = process.findElementNodeById("task_SBK01w"); + assertNotNull(task1); + + BPMNFlowNavigator eventNavigator = new BPMNFlowNavigator(task1, + n -> isSubmitEvent(n)); + assertNotNull(eventNavigator); + + // we expect 3 Event Nodes + + List elementNames = new ArrayList(); + while (eventNavigator.hasNext()) { + Event event = (Event) eventNavigator.next(); + elementNames.add(event.getName()); + } + + assertEquals(2, elementNames.size()); + assertTrue(elementNames.contains("Submit")); + assertTrue(elementNames.contains("Forward and submit")); + + } + + /** + * This callback method returns true if the given element is a an Event and has + * the word 'submit' in its name attribute. + * + * @param element + * @return + */ + private boolean isSubmitEvent(BPMNElementNode element) { + if ((element instanceof Event) + && element.getName().toLowerCase().contains("submit")) { + return true; + } + // not match + return false; + } + + /** + * This test loads model 'refmodel-navigation-03.bpmn' and finds all events by + * evaluating a the conditions by a callback method + * + * + * @throws BPMNModelException + * + */ + @Test + public void testFindAllEventsFromTask1WithCondition() throws BPMNModelException { + + logger.info("...read model"); + BPMNModel model = BPMNModelFactory.read("/refmodel-navigation-03.bpmn"); + + assertEquals(1, model.getProcesses().size()); + BPMNProcess process = model.openDefaultProces(); + + // get Task1 + BPMNElementNode task1 = process.findElementNodeById("task_SBK01w"); + assertNotNull(task1); + + // Build a navigator with a callback method to eval the condition + BPMNFlowNavigator eventNavigator = new BPMNFlowNavigator<>( + task1, + node -> node instanceof Event || node instanceof Event, + condition -> evalCondition(condition)); + + assertNotNull(eventNavigator); + + // we expect only one Event Node! + List elementNames = new ArrayList(); + while (eventNavigator.hasNext()) { + Event event = (Event) eventNavigator.next(); + elementNames.add(event.getName()); + } + + assertEquals(1, elementNames.size()); + assertTrue(elementNames.contains("Event-2")); + + } + + /** + * This callback method evaluates conditions. + * It only returns true if the condition is 'c=d' + * + * @param element + * @return + */ + private boolean evalCondition(String condition) { + // eval dummy condition only + return ("c=d".equals(condition)); + } + +} diff --git a/open-bpmn.metamodel/src/test/resources/refmodel-navigation-01.bpmn b/open-bpmn.metamodel/src/test/resources/refmodel-navigation-01.bpmn new file mode 100644 index 00000000..4e716ef3 --- /dev/null +++ b/open-bpmn.metamodel/src/test/resources/refmodel-navigation-01.bpmn @@ -0,0 +1,153 @@ + + + + true + + + + + + sequenceFlow_GxGAgQ + + + + sequenceFlow_GxGAgQ + sequenceFlow_GMnxSA + sequenceFlow_f4hhBA + + + + sequenceFlow_NVfK3w + sequenceFlow_MNZU9g + sequenceFlow_Y0i62A + sequenceFlow_gZSk0Q + + + + sequenceFlow_GMnxSA + sequenceFlow_gZSk0Q + + + + sequenceFlow_NVfK3w + + + + + + + + + + + + + + + + sequenceFlow_MNZU9g + + + + + + + sequenceFlow_f4hhBA + sequenceFlow_j9TRfA + + + + sequenceFlow_j9TRfA + sequenceFlow_Y0i62A + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/open-bpmn.metamodel/src/test/resources/refmodel-navigation-02.bpmn b/open-bpmn.metamodel/src/test/resources/refmodel-navigation-02.bpmn new file mode 100644 index 00000000..405190f8 --- /dev/null +++ b/open-bpmn.metamodel/src/test/resources/refmodel-navigation-02.bpmn @@ -0,0 +1,186 @@ + + + + true + + + + + + sequenceFlow_GxGAgQ + + + + sequenceFlow_GxGAgQ + sequenceFlow_aamNCw + + + + sequenceFlow_NVfK3w + sequenceFlow_MNZU9g + sequenceFlow_Y0i62A + sequenceFlow_gZSk0Q + + + + sequenceFlow_gZSk0Q + sequenceFlow_ES26Kg + + + + sequenceFlow_NVfK3w + sequenceFlow_NPmh3w + + + + + + + + + + + + + sequenceFlow_MNZU9g + + + + + + + sequenceFlow_f4hhBA + sequenceFlow_NPmh3w + + + + sequenceFlow_Y0i62A + sequenceFlow_TIcibw + + + + + + + + + + sequenceFlow_aamNCw + sequenceFlow_ES26Kg + sequenceFlow_TIcibw + sequenceFlow_f4hhBA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/open-bpmn.metamodel/src/test/resources/refmodel-navigation-03.bpmn b/open-bpmn.metamodel/src/test/resources/refmodel-navigation-03.bpmn new file mode 100644 index 00000000..bf3d256e --- /dev/null +++ b/open-bpmn.metamodel/src/test/resources/refmodel-navigation-03.bpmn @@ -0,0 +1,188 @@ + + + + true + + + + + + sequenceFlow_GxGAgQ + + + + sequenceFlow_GxGAgQ + sequenceFlow_aamNCw + + + + sequenceFlow_NVfK3w + sequenceFlow_MNZU9g + sequenceFlow_Y0i62A + sequenceFlow_gZSk0Q + + + + sequenceFlow_gZSk0Q + sequenceFlow_ES26Kg + + + + sequenceFlow_NVfK3w + sequenceFlow_NPmh3w + + + + + + + + + + + + + sequenceFlow_MNZU9g + + + + + + + sequenceFlow_f4hhBA + sequenceFlow_NPmh3w + + + + sequenceFlow_Y0i62A + sequenceFlow_TIcibw + + + + + + + + + + sequenceFlow_aamNCw + sequenceFlow_ES26Kg + sequenceFlow_TIcibw + sequenceFlow_f4hhBA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +