/* * Copyright 2015 Red Hat, Inc. and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jbpm.simulation.impl; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.eclipse.bpmn2.Activity; import org.eclipse.bpmn2.BoundaryEvent; import org.eclipse.bpmn2.CompensateEventDefinition; import org.eclipse.bpmn2.Definitions; import org.eclipse.bpmn2.ErrorEventDefinition; import org.eclipse.bpmn2.EventDefinition; import org.eclipse.bpmn2.EventSubprocess; import org.eclipse.bpmn2.FlowElement; import org.eclipse.bpmn2.FlowElementsContainer; import org.eclipse.bpmn2.IntermediateCatchEvent; import org.eclipse.bpmn2.LinkEventDefinition; import org.eclipse.bpmn2.MessageEventDefinition; import org.eclipse.bpmn2.Process; import org.eclipse.bpmn2.RootElement; import org.eclipse.bpmn2.SignalEventDefinition; import org.eclipse.bpmn2.StartEvent; import org.eclipse.bpmn2.SubProcess; import org.jbpm.simulation.PathContext; import org.jbpm.simulation.PathContextManager; import org.jbpm.simulation.PathFinder; import org.jbpm.simulation.PathFormatConverter; import org.jbpm.simulation.handler.ElementHandler; import org.jbpm.simulation.handler.HandlerRegistry; import org.jbpm.simulation.util.BPMN2Utils; public class BPMN2PathFinderImpl implements PathFinder { private PathContextManager manager; private Definitions definitions; private FlowElementsContainer container; private List<FlowElement> triggerElements = new ArrayList<FlowElement>(); public BPMN2PathFinderImpl(String bpmn2xml) { this.manager = new PathContextManager(); try { InputStream is = new ByteArrayInputStream(bpmn2xml.getBytes("UTF-8")); this.definitions = BPMN2Utils.getDefinitions(is); } catch (UnsupportedEncodingException e) { throw new IllegalStateException(e.getMessage()); } } public BPMN2PathFinderImpl(File bpmn2File) { this.manager = new PathContextManager(); try { InputStream is = new FileInputStream(bpmn2File); this.definitions = BPMN2Utils.getDefinitions(is); } catch (Exception e) { throw new IllegalStateException(e.getMessage()); } } public BPMN2PathFinderImpl(InputStream bpmn2Stream) { this.manager = new PathContextManager(); this.definitions = BPMN2Utils.getDefinitions(bpmn2Stream); } public BPMN2PathFinderImpl(Definitions bpmn2Defs) { this.manager = new PathContextManager(); this.definitions = bpmn2Defs; } public BPMN2PathFinderImpl(FlowElementsContainer bpmn2Container) { this.manager = new PathContextManager(); this.container = bpmn2Container; } public List<PathContext> findPaths() { Map<String, FlowElement> catchingEvents = new HashMap<String, FlowElement>(); if (this.definitions != null) { List<RootElement> rootElements = definitions.getRootElements(); for (RootElement root : rootElements) { if (root instanceof Process) { Process process = (Process) root; readFlowElements(process, catchingEvents); } } } else { readFlowElements(container, catchingEvents); } manager.setCatchingEvents(catchingEvents); ElementHandler handler = HandlerRegistry.getMainHandler(); // show what was found for (FlowElement fe : triggerElements) { if (fe instanceof StartEvent || fe instanceof Activity || fe instanceof IntermediateCatchEvent) { handler.handle(fe, manager); } } manager.complete(); return manager.getCompletePaths(); } protected static String streamToString(InputStream is) { try { BufferedReader reader = new BufferedReader(new InputStreamReader( is, "UTF-8")); StringBuilder sb = new StringBuilder(); String line = null; while ((line = reader.readLine()) != null) { sb.append(line + "\n"); } is.close(); return sb.toString(); } catch (Exception e) { return ""; } } public <E> E findPaths(PathFormatConverter<E> converter) { findPaths(); return converter.convert(manager.getCompletePaths()); } protected void readFlowElements(FlowElementsContainer container, Map<String, FlowElement> catchingEvents) { // find flow elements and traverse it find path List<FlowElement> flowElements = container.getFlowElements(); for (FlowElement fElement : flowElements) { if (fElement instanceof StartEvent) { triggerElements.add(0, fElement); List<EventDefinition> eventDefinitions = ((StartEvent) fElement).getEventDefinitions(); processEventDefinitions(fElement, eventDefinitions, catchingEvents); } else if((fElement instanceof Activity) && BPMN2Utils.isContainerAdHoc(container)) { Activity act = (Activity) fElement; if(act.getIncoming() == null || act.getIncoming().isEmpty()) { triggerElements.add(0, fElement); } } else if (fElement instanceof IntermediateCatchEvent) { IntermediateCatchEvent act = (IntermediateCatchEvent) fElement; if(act.getIncoming() == null || act.getIncoming().isEmpty()) { triggerElements.add(0, fElement); } List<EventDefinition> eventDefinitions = ((IntermediateCatchEvent) fElement) .getEventDefinitions(); processEventDefinitions(fElement, eventDefinitions, catchingEvents); } else if (fElement instanceof BoundaryEvent) { List<EventDefinition> eventDefinitions = ((BoundaryEvent) fElement).getEventDefinitions(); processEventDefinitions(fElement, eventDefinitions, catchingEvents); } else if (fElement instanceof EventSubprocess || ((fElement instanceof SubProcess) && ((SubProcess) fElement).isTriggeredByEvent())) { readFlowElements((FlowElementsContainer)fElement, catchingEvents); } } } protected void processEventDefinitions(FlowElement fElement, List<EventDefinition> eventDefinitions, Map<String, FlowElement> catchingEvents) { String key = null; if (eventDefinitions != null) { for (EventDefinition edef : eventDefinitions) { if (edef instanceof SignalEventDefinition) { key = ((SignalEventDefinition) edef) .getSignalRef(); } else if (edef instanceof MessageEventDefinition) { key = ((MessageEventDefinition) edef) .getMessageRef().getId(); } else if (edef instanceof LinkEventDefinition) { key = ((LinkEventDefinition) edef).getName(); } else if (edef instanceof CompensateEventDefinition) { key = ((CompensateEventDefinition) edef) .getActivityRef().getId(); } else if (edef instanceof ErrorEventDefinition) { key = ((ErrorEventDefinition) edef) .getErrorRef().getId(); } if (key != null) { catchingEvents.put(key, fElement); } } } } }