ModelWalker { public void walk(final ModelElementVisitor visitor) { final Definitions rootElement = modelInstance.getDefinitions(); elementsToVisit.add(rootElement); BpmnModelElementInstance currentElement; while ((currentElement = elementsToVisit.poll()) != null) { visitor.visit(currentElement); final Collection<BpmnModelElementInstance> children = getChildElements(currentElement); children.forEach(c -> elementsToVisit.addFirst(c)); } } ModelWalker(final BpmnModelInstance modelInstance); void walk(final ModelElementVisitor visitor);  }
@Test public void shouldVisitModelTopDownDepthFirst() { final BpmnModelInstance modelInstance = Bpmn.createExecutableProcess("process") .startEvent("start-1-1") .subProcess("sub-1-2") .embeddedSubProcess() .startEvent("start-2-1") .subProcessDone() .subProcess("sub-1-3") .embeddedSubProcess() .startEvent("start-3-1") .subProcessDone() .endEvent("end-1-4") .done(); final List<BpmnModelElementInstance> visitedElements = new ArrayList<>(); final ModelWalker walker = new ModelWalker(modelInstance); walker.walk(visitedElements::add); final List<BaseElement> visitedBaseElements = visitedElements.stream() .filter(e -> e instanceof BaseElement) .map(e -> (BaseElement) e) .collect(Collectors.toList()); final List<String> subprocessVisitingOrder = visitedBaseElements.stream() .filter(e -> e instanceof SubProcess) .map(e -> e.getId()) .collect(Collectors.toList()); assertThat(subprocessVisitingOrder).hasSize(2); final String firstSubprocess = subprocessVisitingOrder.get(0); final String secondSubprocess = subprocessVisitingOrder.get(1); final String firstSubprocessStart = "sub-1-2".equals(firstSubprocess) ? "start-2-1" : "start-3-1"; final String secondSubprocessStart = "sub-1-2".equals(secondSubprocess) ? "start-2-1" : "start-3-1"; assertThat(visitedBaseElements) .extracting(e -> e.getId()) .containsSubsequence("process", "start-1-1") .containsSubsequence("process", "sub-1-2") .containsSubsequence("process", "sub-1-3") .containsSubsequence("process", "end-1-4") .containsSubsequence(firstSubprocess, secondSubprocess) .containsSubsequence(firstSubprocess, firstSubprocessStart) .containsSubsequence(secondSubprocess, secondSubprocessStart) .containsSubsequence(firstSubprocessStart, secondSubprocessStart); }
@Test public void shouldInvokeTypedVisitors() { final BpmnModelInstance modelInstance = Bpmn.createExecutableProcess("process") .startEvent("start-1") .userTask("user-1") .endEvent("end-1") .done(); final List<FlowNode> flowNodes = new ArrayList<>(); final List<UserTask> userTasks = new ArrayList<>(); final TypeHierarchyVisitor compositeVisitor = new TypeHierarchyVisitor() { @Override protected void visit( final ModelElementType implementedType, final BpmnModelElementInstance instance) { if (implementedType.getInstanceType() == UserTask.class) { userTasks.add((UserTask) instance); } if (implementedType.getInstanceType() == FlowNode.class) { flowNodes.add((FlowNode) instance); } } }; final ModelWalker walker = new ModelWalker(modelInstance); walker.walk(compositeVisitor); assertThat(flowNodes).extracting(f -> f.getId()).containsOnly("start-1", "user-1", "end-1"); assertThat(userTasks).extracting(f -> f.getId()).containsOnly("user-1"); }
@Test public void shouldVisitTypeHiearchyInOrder() { final BpmnModelInstance modelInstance = Bpmn.createExecutableProcess("process") .startEvent("start-1") .userTask("user-1") .endEvent("end-1") .done(); final ModelWalker walker = new ModelWalker(modelInstance); final List<Class<?>> visitedUserTaskTypes = new ArrayList<>(); final TypeHierarchyVisitor visitor = new TypeHierarchyVisitor() { @Override protected void visit( final ModelElementType implementedType, final BpmnModelElementInstance instance) { if (instance instanceof UserTask) { visitedUserTaskTypes.add(implementedType.getInstanceType()); } } }; walker.walk(visitor); assertThat(visitedUserTaskTypes) .containsExactly( BaseElement.class, FlowElement.class, FlowNode.class, Activity.class, Task.class, UserTask.class); }