All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.activiti.image.impl.DefaultProcessDiagramGenerator Maven / Gradle / Ivy

There is a newer version: 7.1.0.M6
Show newest version
/*
 * Copyright 2017 Alfresco, 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.
 * You may obtain a copy of the License at
 *
 *       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.activiti.image.impl;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.activiti.bpmn.model.Activity;
import org.activiti.bpmn.model.Artifact;
import org.activiti.bpmn.model.Association;
import org.activiti.bpmn.model.AssociationDirection;
import org.activiti.bpmn.model.BaseElement;
import org.activiti.bpmn.model.BoundaryEvent;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.BusinessRuleTask;
import org.activiti.bpmn.model.CallActivity;
import org.activiti.bpmn.model.CompensateEventDefinition;
import org.activiti.bpmn.model.EndEvent;
import org.activiti.bpmn.model.ErrorEventDefinition;
import org.activiti.bpmn.model.Event;
import org.activiti.bpmn.model.EventDefinition;
import org.activiti.bpmn.model.EventGateway;
import org.activiti.bpmn.model.EventSubProcess;
import org.activiti.bpmn.model.ExclusiveGateway;
import org.activiti.bpmn.model.FlowElement;
import org.activiti.bpmn.model.FlowElementsContainer;
import org.activiti.bpmn.model.FlowNode;
import org.activiti.bpmn.model.Gateway;
import org.activiti.bpmn.model.GraphicInfo;
import org.activiti.bpmn.model.InclusiveGateway;
import org.activiti.bpmn.model.IntermediateCatchEvent;
import org.activiti.bpmn.model.Lane;
import org.activiti.bpmn.model.ManualTask;
import org.activiti.bpmn.model.MessageEventDefinition;
import org.activiti.bpmn.model.MultiInstanceLoopCharacteristics;
import org.activiti.bpmn.model.ParallelGateway;
import org.activiti.bpmn.model.Pool;
import org.activiti.bpmn.model.Process;
import org.activiti.bpmn.model.ReceiveTask;
import org.activiti.bpmn.model.ScriptTask;
import org.activiti.bpmn.model.SendTask;
import org.activiti.bpmn.model.SequenceFlow;
import org.activiti.bpmn.model.ServiceTask;
import org.activiti.bpmn.model.SignalEventDefinition;
import org.activiti.bpmn.model.StartEvent;
import org.activiti.bpmn.model.SubProcess;
import org.activiti.bpmn.model.Task;
import org.activiti.bpmn.model.TextAnnotation;
import org.activiti.bpmn.model.ThrowEvent;
import org.activiti.bpmn.model.TimerEventDefinition;
import org.activiti.bpmn.model.UserTask;
import org.activiti.image.ProcessDiagramGenerator;
import org.springframework.stereotype.Component;

/**
 * Class to generate an svg based the diagram interchange information in a
 * BPMN 2.0 process.
 */
@Component
public class DefaultProcessDiagramGenerator implements ProcessDiagramGenerator {

    private String activityFontName = "Arial";

    private String labelFontName = "Arial";

    private String annotationFontName = "Arial";

    @Override
    public String getDefaultActivityFontName() {
        return activityFontName;
    }

    @Override
    public String getDefaultLabelFontName() {
        return labelFontName;
    }

    @Override
    public String getDefaultAnnotationFontName() {
        return annotationFontName;
    }

    protected Map, ActivityDrawInstruction> activityDrawInstructions = new HashMap, ActivityDrawInstruction>();
    protected Map, ArtifactDrawInstruction> artifactDrawInstructions = new HashMap, ArtifactDrawInstruction>();

    // The instructions on how to draw a certain construct is
    // created statically and stored in a map for performance.
    public DefaultProcessDiagramGenerator() {
        // start event
        activityDrawInstructions.put(StartEvent.class,
                                     new ActivityDrawInstruction() {

            @Override
            public void draw(DefaultProcessDiagramCanvas processDiagramCanvas,
                             BpmnModel bpmnModel,
                             FlowNode flowNode) {
                GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
                StartEvent startEvent = (StartEvent) flowNode;
                if (startEvent.getEventDefinitions() != null && !startEvent.getEventDefinitions().isEmpty()) {
                    EventDefinition eventDefinition = startEvent.getEventDefinitions().get(0);
                    if (eventDefinition instanceof TimerEventDefinition) {
                        processDiagramCanvas.drawTimerStartEvent(flowNode.getId(),
                                                                 graphicInfo);
                    } else if (eventDefinition instanceof ErrorEventDefinition) {
                        processDiagramCanvas.drawErrorStartEvent(flowNode.getId(),
                                                                 graphicInfo);
                    } else if (eventDefinition instanceof SignalEventDefinition) {
                        processDiagramCanvas.drawSignalStartEvent(flowNode.getId(),
                                                                  graphicInfo);
                    } else if (eventDefinition instanceof MessageEventDefinition) {
                        processDiagramCanvas.drawMessageStartEvent(flowNode.getId(),
                                                                   graphicInfo);
                    } else {
                        processDiagramCanvas.drawNoneStartEvent(flowNode.getId(),
                                                                graphicInfo);
                    }
                } else {
                    processDiagramCanvas.drawNoneStartEvent(flowNode.getId(),
                                                            graphicInfo);
                }
            }
        });

        // signal catch
        activityDrawInstructions.put(IntermediateCatchEvent.class,
                                     new ActivityDrawInstruction() {

            @Override
            public void draw(DefaultProcessDiagramCanvas processDiagramCanvas,
                             BpmnModel bpmnModel,
                             FlowNode flowNode) {
                GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
                IntermediateCatchEvent intermediateCatchEvent = (IntermediateCatchEvent) flowNode;
                if (intermediateCatchEvent.getEventDefinitions() != null && !intermediateCatchEvent.getEventDefinitions()
                        .isEmpty()) {
                    if (intermediateCatchEvent.getEventDefinitions().get(0) instanceof SignalEventDefinition) {
                        processDiagramCanvas.drawCatchingSignalEvent(flowNode.getId(),
                                                                     flowNode.getName(),
                                                                     graphicInfo,
                                                                     true);
                    } else if (intermediateCatchEvent.getEventDefinitions().get(0) instanceof TimerEventDefinition) {
                        processDiagramCanvas.drawCatchingTimerEvent(flowNode.getId(),
                                                                    flowNode.getName(),
                                                                    graphicInfo,
                                                                    true);
                    } else if (intermediateCatchEvent.getEventDefinitions().get(0) instanceof MessageEventDefinition) {
                        processDiagramCanvas.drawCatchingMessageEvent(flowNode.getId(),
                                                                      flowNode.getName(),
                                                                      graphicInfo,
                                                                      true);
                    }
                }
            }
        });

        // signal throw
        activityDrawInstructions.put(ThrowEvent.class,
                                     new ActivityDrawInstruction() {

            @Override
            public void draw(DefaultProcessDiagramCanvas processDiagramCanvas,
                             BpmnModel bpmnModel,
                             FlowNode flowNode) {
                GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
                ThrowEvent throwEvent = (ThrowEvent) flowNode;
                if (throwEvent.getEventDefinitions() != null && !throwEvent.getEventDefinitions().isEmpty()) {
                    if (throwEvent.getEventDefinitions().get(0) instanceof SignalEventDefinition) {
                        processDiagramCanvas.drawThrowingSignalEvent(flowNode.getId(),
                                                                     graphicInfo);
                    } else if (throwEvent.getEventDefinitions().get(0) instanceof CompensateEventDefinition) {
                        processDiagramCanvas.drawThrowingCompensateEvent(flowNode.getId(),
                                                                         graphicInfo);
                    } else {
                        processDiagramCanvas.drawThrowingNoneEvent(flowNode.getId(),
                                                                   graphicInfo);
                    }
                } else {
                    processDiagramCanvas.drawThrowingNoneEvent(flowNode.getId(),
                                                               graphicInfo);
                }
            }
        });

        // end event
        activityDrawInstructions.put(EndEvent.class,
                                     new ActivityDrawInstruction() {

            @Override
            public void draw(DefaultProcessDiagramCanvas processDiagramCanvas,
                             BpmnModel bpmnModel,
                             FlowNode flowNode) {
                GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
                EndEvent endEvent = (EndEvent) flowNode;
                if (endEvent.getEventDefinitions() != null && !endEvent.getEventDefinitions().isEmpty()) {
                    if (endEvent.getEventDefinitions().get(0) instanceof ErrorEventDefinition) {
                        processDiagramCanvas.drawErrorEndEvent(flowNode.getId(),
                                                               flowNode.getName(),
                                                               graphicInfo);
                    } else {
                        processDiagramCanvas.drawNoneEndEvent(flowNode.getId(),
                                                              flowNode.getName(),
                                                              graphicInfo);
                    }
                } else {
                    processDiagramCanvas.drawNoneEndEvent(flowNode.getId(),
                                                          flowNode.getName(),
                                                          graphicInfo);
                }
            }
        });

        // task
        activityDrawInstructions.put(Task.class,
                                     new ActivityDrawInstruction() {

            @Override
            public void draw(DefaultProcessDiagramCanvas processDiagramCanvas,
                             BpmnModel bpmnModel,
                             FlowNode flowNode) {
                GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
                processDiagramCanvas.drawTask(flowNode.getId(),
                                              flowNode.getName(),
                                              graphicInfo);
            }
        });

        // user task
        activityDrawInstructions.put(UserTask.class,
                                     new ActivityDrawInstruction() {

            @Override
            public void draw(DefaultProcessDiagramCanvas processDiagramCanvas,
                             BpmnModel bpmnModel,
                             FlowNode flowNode) {
                GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
                processDiagramCanvas.drawUserTask(flowNode.getId(),
                                                  flowNode.getName(),
                                                  graphicInfo);
            }
        });

        // script task
        activityDrawInstructions.put(ScriptTask.class,
                                     new ActivityDrawInstruction() {

            @Override
            public void draw(DefaultProcessDiagramCanvas processDiagramCanvas,
                             BpmnModel bpmnModel,
                             FlowNode flowNode) {
                GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
                processDiagramCanvas.drawScriptTask(flowNode.getId(),
                                                    flowNode.getName(),
                                                    graphicInfo);
            }
        });

        // service task
        activityDrawInstructions.put(ServiceTask.class,
                                     new ActivityDrawInstruction() {

            @Override
            public void draw(DefaultProcessDiagramCanvas processDiagramCanvas,
                             BpmnModel bpmnModel,
                             FlowNode flowNode) {
                GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
                ServiceTask serviceTask = (ServiceTask) flowNode;
                processDiagramCanvas.drawServiceTask(flowNode.getId(),
                                                     serviceTask.getName(),
                                                     graphicInfo);
            }
        });

        // receive task
        activityDrawInstructions.put(ReceiveTask.class,
                                     new ActivityDrawInstruction() {

            @Override
            public void draw(DefaultProcessDiagramCanvas processDiagramCanvas,
                             BpmnModel bpmnModel,
                             FlowNode flowNode) {
                GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
                processDiagramCanvas.drawReceiveTask(flowNode.getId(),
                                                     flowNode.getName(),
                                                     graphicInfo);
            }
        });

        // send task
        activityDrawInstructions.put(SendTask.class,
                                     new ActivityDrawInstruction() {

            @Override
            public void draw(DefaultProcessDiagramCanvas processDiagramCanvas,
                             BpmnModel bpmnModel,
                             FlowNode flowNode) {
                GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
                processDiagramCanvas.drawSendTask(flowNode.getId(),
                                                  flowNode.getName(),
                                                  graphicInfo);
            }
        });

        // manual task
        activityDrawInstructions.put(ManualTask.class,
                                     new ActivityDrawInstruction() {

            @Override
            public void draw(DefaultProcessDiagramCanvas processDiagramCanvas,
                             BpmnModel bpmnModel,
                             FlowNode flowNode) {
                GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
                processDiagramCanvas.drawManualTask(flowNode.getId(),
                                                    flowNode.getName(),
                                                    graphicInfo);
            }
        });

        // businessRuleTask task
        activityDrawInstructions.put(BusinessRuleTask.class,
                                     new ActivityDrawInstruction() {

            @Override
            public void draw(DefaultProcessDiagramCanvas processDiagramCanvas,
                             BpmnModel bpmnModel,
                             FlowNode flowNode) {
                GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
                processDiagramCanvas.drawBusinessRuleTask(flowNode.getId(),
                                                          flowNode.getName(),
                                                          graphicInfo);
            }
        });

        // exclusive gateway
        activityDrawInstructions.put(ExclusiveGateway.class,
                                     new ActivityDrawInstruction() {

            @Override
            public void draw(DefaultProcessDiagramCanvas processDiagramCanvas,
                             BpmnModel bpmnModel,
                             FlowNode flowNode) {
                GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
                processDiagramCanvas.drawExclusiveGateway(flowNode.getId(),
                                                          graphicInfo);
            }
        });

        // inclusive gateway
        activityDrawInstructions.put(InclusiveGateway.class,
                                     new ActivityDrawInstruction() {

            @Override
            public void draw(DefaultProcessDiagramCanvas processDiagramCanvas,
                             BpmnModel bpmnModel,
                             FlowNode flowNode) {
                GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
                processDiagramCanvas.drawInclusiveGateway(flowNode.getId(),
                                                          graphicInfo);
            }
        });

        // parallel gateway
        activityDrawInstructions.put(ParallelGateway.class,
                                     new ActivityDrawInstruction() {

            @Override
            public void draw(DefaultProcessDiagramCanvas processDiagramCanvas,
                             BpmnModel bpmnModel,
                             FlowNode flowNode) {
                GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
                processDiagramCanvas.drawParallelGateway(flowNode.getId(),
                                                         graphicInfo);
            }
        });

        // event based gateway
        activityDrawInstructions.put(EventGateway.class,
                                     new ActivityDrawInstruction() {

            @Override
            public void draw(DefaultProcessDiagramCanvas processDiagramCanvas,
                             BpmnModel bpmnModel,
                             FlowNode flowNode) {
                GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
                processDiagramCanvas.drawEventBasedGateway(flowNode.getId(),
                                                           graphicInfo);
            }
        });

        // Boundary timer
        activityDrawInstructions.put(BoundaryEvent.class,
                                     new ActivityDrawInstruction() {

            @Override
            public void draw(DefaultProcessDiagramCanvas processDiagramCanvas,
                             BpmnModel bpmnModel,
                             FlowNode flowNode) {
                GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
                BoundaryEvent boundaryEvent = (BoundaryEvent) flowNode;
                if (boundaryEvent.getEventDefinitions() != null && !boundaryEvent.getEventDefinitions().isEmpty()) {
                    if (boundaryEvent.getEventDefinitions().get(0) instanceof TimerEventDefinition) {

                        processDiagramCanvas.drawCatchingTimerEvent(flowNode.getId(),
                                                                    flowNode.getName(),
                                                                    graphicInfo,
                                                                    boundaryEvent.isCancelActivity());
                    } else if (boundaryEvent.getEventDefinitions().get(0) instanceof ErrorEventDefinition) {

                        processDiagramCanvas.drawCatchingErrorEvent(flowNode.getId(),
                                                                    graphicInfo,
                                                                    boundaryEvent.isCancelActivity());
                    } else if (boundaryEvent.getEventDefinitions().get(0) instanceof SignalEventDefinition) {
                        processDiagramCanvas.drawCatchingSignalEvent(flowNode.getId(),
                                                                     flowNode.getName(),
                                                                     graphicInfo,
                                                                     boundaryEvent.isCancelActivity());
                    } else if (boundaryEvent.getEventDefinitions().get(0) instanceof MessageEventDefinition) {
                        processDiagramCanvas.drawCatchingMessageEvent(flowNode.getId(),
                                                                      flowNode.getName(),
                                                                      graphicInfo,
                                                                      boundaryEvent.isCancelActivity());
                    } else if (boundaryEvent.getEventDefinitions().get(0) instanceof CompensateEventDefinition) {
                        processDiagramCanvas.drawCatchingCompensateEvent(flowNode.getId(),
                                                                         graphicInfo,
                                                                         boundaryEvent.isCancelActivity());
                    }
                }
            }
        });

        // subprocess
        activityDrawInstructions.put(SubProcess.class,
                                     new ActivityDrawInstruction() {

            @Override
            public void draw(DefaultProcessDiagramCanvas processDiagramCanvas,
                             BpmnModel bpmnModel,
                             FlowNode flowNode) {
                GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
                if (graphicInfo.getExpanded() != null && !graphicInfo.getExpanded()) {
                    processDiagramCanvas.drawCollapsedSubProcess(flowNode.getId(),
                                                                 flowNode.getName(),
                                                                 graphicInfo,
                                                                 false);
                } else {
                    processDiagramCanvas.drawExpandedSubProcess(flowNode.getId(),
                                                                flowNode.getName(),
                                                                graphicInfo,
                                                                false);
                }
            }
        });

        // Event subprocess
        activityDrawInstructions.put(EventSubProcess.class,
                                     new ActivityDrawInstruction() {

            @Override
            public void draw(DefaultProcessDiagramCanvas processDiagramCanvas,
                             BpmnModel bpmnModel,
                             FlowNode flowNode) {
                GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
                if (graphicInfo.getExpanded() != null && !graphicInfo.getExpanded()) {
                    processDiagramCanvas.drawCollapsedSubProcess(flowNode.getId(),
                                                                 flowNode.getName(),
                                                                 graphicInfo,
                                                                 true);
                } else {
                    processDiagramCanvas.drawExpandedSubProcess(flowNode.getId(),
                                                                flowNode.getName(),
                                                                graphicInfo,
                                                                true);
                }
            }
        });

        // call activity
        activityDrawInstructions.put(CallActivity.class,
                                     new ActivityDrawInstruction() {

            @Override
            public void draw(DefaultProcessDiagramCanvas processDiagramCanvas,
                             BpmnModel bpmnModel,
                             FlowNode flowNode) {
                GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
                processDiagramCanvas.drawCollapsedCallActivity(flowNode.getId(),
                                                               flowNode.getName(),
                                                               graphicInfo);
            }
        });

        // text annotation
        artifactDrawInstructions.put(TextAnnotation.class,
                                     new ArtifactDrawInstruction() {

            @Override
            public void draw(DefaultProcessDiagramCanvas processDiagramCanvas,
                             BpmnModel bpmnModel,
                             Artifact artifact) {
                GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(artifact.getId());
                TextAnnotation textAnnotation = (TextAnnotation) artifact;
                processDiagramCanvas.drawTextAnnotation(textAnnotation.getId(),
                                                        textAnnotation.getText(),
                                                        graphicInfo);
            }
        });

        // association
        artifactDrawInstructions.put(Association.class,
                                     new ArtifactDrawInstruction() {

            @Override
            public void draw(DefaultProcessDiagramCanvas processDiagramCanvas,
                             BpmnModel bpmnModel,
                             Artifact artifact) {
                Association association = (Association) artifact;
                String sourceRef = association.getSourceRef();
                String targetRef = association.getTargetRef();

                // source and target can be instance of FlowElement or Artifact
                BaseElement sourceElement = bpmnModel.getFlowElement(sourceRef);
                BaseElement targetElement = bpmnModel.getFlowElement(targetRef);
                if (sourceElement == null) {
                    sourceElement = bpmnModel.getArtifact(sourceRef);
                }
                if (targetElement == null) {
                    targetElement = bpmnModel.getArtifact(targetRef);
                }
                List graphicInfoList = bpmnModel.getFlowLocationGraphicInfo(artifact.getId());
                graphicInfoList = connectionPerfectionizer(processDiagramCanvas,
                                                           bpmnModel,
                                                           sourceElement,
                                                           targetElement,
                                                           graphicInfoList);
                int xPoints[] = new int[graphicInfoList.size()];
                int yPoints[] = new int[graphicInfoList.size()];
                for (int i = 1; i < graphicInfoList.size(); i++) {
                    GraphicInfo graphicInfo = graphicInfoList.get(i);
                    GraphicInfo previousGraphicInfo = graphicInfoList.get(i - 1);

                    if (i == 1) {
                        xPoints[0] = (int) previousGraphicInfo.getX();
                        yPoints[0] = (int) previousGraphicInfo.getY();
                    }
                    xPoints[i] = (int) graphicInfo.getX();
                    yPoints[i] = (int) graphicInfo.getY();
                }

                AssociationDirection associationDirection = association.getAssociationDirection();
                processDiagramCanvas.drawAssociation(xPoints,
                                                     yPoints,
                                                     associationDirection,
                                                     false);
            }
        });
    }

    @Override
    public InputStream generateDiagram(BpmnModel bpmnModel,
                                       List highLightedActivities,
                                       List highLightedFlows,
                                       String activityFontName,
                                       String labelFontName,
                                       String annotationFontName) {

        return generateProcessDiagram(bpmnModel,
                                      highLightedActivities,
                                      highLightedFlows,
                                      activityFontName,
                                      labelFontName,
                                      annotationFontName).generateImage();
    }

    @Override
    public InputStream generateDiagram(BpmnModel bpmnModel,
                                       List highLightedActivities,
                                       List highLightedFlows) {
        return generateDiagram(bpmnModel,
                               highLightedActivities,
                               highLightedFlows,
                               null,
                               null,
                               null);
    }

    @Override
    public InputStream generateDiagram(BpmnModel bpmnModel,
                                       List highLightedActivities) {
        return generateDiagram(bpmnModel,
                               highLightedActivities,
                               Collections.emptyList());
    }

    @Override
    public InputStream generateDiagram(BpmnModel bpmnModel,
                                       String activityFontName,
                                       String labelFontName,
                                       String annotationFontName) {

        return generateDiagram(bpmnModel,
                               Collections.emptyList(),
                               Collections.emptyList(),
                               activityFontName,
                               labelFontName,
                               annotationFontName);
    }

    protected DefaultProcessDiagramCanvas generateProcessDiagram(BpmnModel bpmnModel,
                                                                 List highLightedActivities,
                                                                 List highLightedFlows,
                                                                 String activityFontName,
                                                                 String labelFontName,
                                                                 String annotationFontName) {

        prepareBpmnModel(bpmnModel);

        DefaultProcessDiagramCanvas processDiagramCanvas = initProcessDiagramCanvas(bpmnModel,
                                                                                    activityFontName,
                                                                                    labelFontName,
                                                                                    annotationFontName);

        // Draw pool shape, if process is participant in collaboration
        for (Pool pool : bpmnModel.getPools()) {
            GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(pool.getId());
            processDiagramCanvas.drawPoolOrLane(pool.getId(),
                                                pool.getName(),
                                                graphicInfo);
        }

        // Draw lanes
        for (Process process : bpmnModel.getProcesses()) {
            for (Lane lane : process.getLanes()) {
                GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(lane.getId());
                processDiagramCanvas.drawPoolOrLane(lane.getId(),
                                                    lane.getName(),
                                                    graphicInfo);
            }
        }

        // Draw activities and their sequence-flows
        for (Process process : bpmnModel.getProcesses()) {
            for (FlowNode flowNode : process.findFlowElementsOfType(FlowNode.class)) {
                drawActivity(processDiagramCanvas,
                             bpmnModel,
                             flowNode,
                             highLightedActivities,
                             highLightedFlows);
            }
        }

        // Draw artifacts
        for (Process process : bpmnModel.getProcesses()) {

            for (Artifact artifact : process.getArtifacts()) {
                drawArtifact(processDiagramCanvas,
                             bpmnModel,
                             artifact);
            }

            List subProcesses = process.findFlowElementsOfType(SubProcess.class,
                                                                           true);
            if (subProcesses != null) {
                for (SubProcess subProcess : subProcesses) {
                    for (Artifact subProcessArtifact : subProcess.getArtifacts()) {
                        drawArtifact(processDiagramCanvas,
                                     bpmnModel,
                                     subProcessArtifact);
                    }
                }
            }
        }

        return processDiagramCanvas;
    }

    protected void prepareBpmnModel(BpmnModel bpmnModel) {

        // Need to make sure all elements have positive x and y.
        // Check all graphicInfo and update the elements accordingly

        List allGraphicInfos = new ArrayList();
        if (bpmnModel.getLocationMap() != null) {
            allGraphicInfos.addAll(bpmnModel.getLocationMap().values());
        }
        if (bpmnModel.getLabelLocationMap() != null) {
            allGraphicInfos.addAll(bpmnModel.getLabelLocationMap().values());
        }
        if (bpmnModel.getFlowLocationMap() != null) {
            for (List flowGraphicInfos : bpmnModel.getFlowLocationMap().values()) {
                allGraphicInfos.addAll(flowGraphicInfos);
            }
        }

        if (allGraphicInfos.size() > 0) {

            boolean needsTranslationX = false;
            boolean needsTranslationY = false;

            double lowestX = 0.0;
            double lowestY = 0.0;

            // Collect lowest x and y
            for (GraphicInfo graphicInfo : allGraphicInfos) {

                double x = graphicInfo.getX();
                double y = graphicInfo.getY();

                if (x < lowestX) {
                    needsTranslationX = true;
                    lowestX = x;
                }
                if (y < lowestY) {
                    needsTranslationY = true;
                    lowestY = y;
                }
            }

            // Update all graphicInfo objects
            if (needsTranslationX || needsTranslationY) {

                double translationX = Math.abs(lowestX);
                double translationY = Math.abs(lowestY);

                for (GraphicInfo graphicInfo : allGraphicInfos) {
                    if (needsTranslationX) {
                        graphicInfo.setX(graphicInfo.getX() + translationX);
                    }
                    if (needsTranslationY) {
                        graphicInfo.setY(graphicInfo.getY() + translationY);
                    }
                }
            }
        }
    }

    protected void drawActivity(DefaultProcessDiagramCanvas processDiagramCanvas,
                                BpmnModel bpmnModel,
                                FlowNode flowNode,
                                List highLightedActivities,
                                List highLightedFlows) {

        ActivityDrawInstruction drawInstruction = activityDrawInstructions.get(flowNode.getClass());
        if (drawInstruction != null) {

            drawInstruction.draw(processDiagramCanvas,
                                 bpmnModel,
                                 flowNode);

            // Gather info on the multi instance marker
            boolean multiInstanceSequential = false;
            boolean multiInstanceParallel = false;
            boolean collapsed = false;
            if (flowNode instanceof Activity) {
                Activity activity = (Activity) flowNode;
                MultiInstanceLoopCharacteristics multiInstanceLoopCharacteristics = activity.getLoopCharacteristics();
                if (multiInstanceLoopCharacteristics != null) {
                    multiInstanceSequential = multiInstanceLoopCharacteristics.isSequential();
                    multiInstanceParallel = !multiInstanceSequential;
                }
            }

            // Gather info on the collapsed marker
            GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(flowNode.getId());
            if (flowNode instanceof SubProcess) {
                collapsed = graphicInfo.getExpanded() != null && !graphicInfo.getExpanded();
            } else if (flowNode instanceof CallActivity) {
                collapsed = true;
            }

            // Actually draw the markers
            processDiagramCanvas.drawActivityMarkers((int) graphicInfo.getX(),
                                                     (int) graphicInfo.getY(),
                                                     (int) graphicInfo.getWidth(),
                                                     (int) graphicInfo.getHeight(),
                                                     multiInstanceSequential,
                                                     multiInstanceParallel,
                                                     collapsed);

            // Draw highlighted activities
            if (highLightedActivities.contains(flowNode.getId())) {
                drawHighLight(processDiagramCanvas,
                              bpmnModel.getGraphicInfo(flowNode.getId()));
            }
        }

        // Outgoing transitions of activity
        for (SequenceFlow sequenceFlow : flowNode.getOutgoingFlows()) {
            boolean highLighted = (highLightedFlows.contains(sequenceFlow.getId()));
            String defaultFlow = null;
            if (flowNode instanceof Activity) {
                defaultFlow = ((Activity) flowNode).getDefaultFlow();
            } else if (flowNode instanceof Gateway) {
                defaultFlow = ((Gateway) flowNode).getDefaultFlow();
            }

            boolean isDefault = false;
            if (defaultFlow != null && defaultFlow.equalsIgnoreCase(sequenceFlow.getId())) {
                isDefault = true;
            }
            boolean drawConditionalIndicator = sequenceFlow.getConditionExpression() != null && !(flowNode instanceof Gateway);

            String sourceRef = sequenceFlow.getSourceRef();
            String targetRef = sequenceFlow.getTargetRef();
            FlowElement sourceElement = bpmnModel.getFlowElement(sourceRef);
            FlowElement targetElement = bpmnModel.getFlowElement(targetRef);
            List graphicInfoList = bpmnModel.getFlowLocationGraphicInfo(sequenceFlow.getId());
            if (graphicInfoList != null && graphicInfoList.size() > 0) {
                graphicInfoList = connectionPerfectionizer(processDiagramCanvas,
                                                           bpmnModel,
                                                           sourceElement,
                                                           targetElement,
                                                           graphicInfoList);
                int xPoints[] = new int[graphicInfoList.size()];
                int yPoints[] = new int[graphicInfoList.size()];

                for (int i = 1; i < graphicInfoList.size(); i++) {
                    GraphicInfo graphicInfo = graphicInfoList.get(i);
                    GraphicInfo previousGraphicInfo = graphicInfoList.get(i - 1);

                    if (i == 1) {
                        xPoints[0] = (int) previousGraphicInfo.getX();
                        yPoints[0] = (int) previousGraphicInfo.getY();
                    }
                    xPoints[i] = (int) graphicInfo.getX();
                    yPoints[i] = (int) graphicInfo.getY();
                }

                processDiagramCanvas.drawSequenceflow(xPoints,
                                                      yPoints,
                                                      drawConditionalIndicator,
                                                      isDefault,
                                                      highLighted);

                // Draw sequenceflow label
                GraphicInfo labelGraphicInfo = bpmnModel.getLabelGraphicInfo(sequenceFlow.getId());
                if (labelGraphicInfo != null) {
                    processDiagramCanvas.drawLabel(sequenceFlow.getName(),
                                                   labelGraphicInfo,
                                                   false);
                }
            }
        }

        // Nested elements
        if (flowNode instanceof FlowElementsContainer) {
            for (FlowElement nestedFlowElement : ((FlowElementsContainer) flowNode).getFlowElements()) {
                if (nestedFlowElement instanceof FlowNode) {
                    drawActivity(processDiagramCanvas,
                                 bpmnModel,
                                 (FlowNode) nestedFlowElement,
                                 highLightedActivities,
                                 highLightedFlows);
                }
            }
        }
    }

    /**
     * This method makes coordinates of connection flow better.
     * @param processDiagramCanvas
     * @param bpmnModel
     * @param sourceElement
     * @param targetElement
     * @param graphicInfoList
     * @return
     */
    protected static List connectionPerfectionizer(DefaultProcessDiagramCanvas processDiagramCanvas,
                                                                BpmnModel bpmnModel,
                                                                BaseElement sourceElement,
                                                                BaseElement targetElement,
                                                                List graphicInfoList) {
        GraphicInfo sourceGraphicInfo = bpmnModel.getGraphicInfo(sourceElement.getId());
        GraphicInfo targetGraphicInfo = bpmnModel.getGraphicInfo(targetElement.getId());

        DefaultProcessDiagramCanvas.SHAPE_TYPE sourceShapeType = getShapeType(sourceElement);
        DefaultProcessDiagramCanvas.SHAPE_TYPE targetShapeType = getShapeType(targetElement);

        return processDiagramCanvas.connectionPerfectionizer(sourceShapeType,
                                                             targetShapeType,
                                                             sourceGraphicInfo,
                                                             targetGraphicInfo,
                                                             graphicInfoList);
    }

    /**
     * This method returns shape type of base element.
* Each element can be presented as rectangle, rhombus, or ellipse. * @param baseElement * @return DefaultProcessDiagramCanvas.SHAPE_TYPE */ protected static DefaultProcessDiagramCanvas.SHAPE_TYPE getShapeType(BaseElement baseElement) { if (baseElement instanceof Task || baseElement instanceof Activity || baseElement instanceof TextAnnotation) { return DefaultProcessDiagramCanvas.SHAPE_TYPE.Rectangle; } else if (baseElement instanceof Gateway) { return DefaultProcessDiagramCanvas.SHAPE_TYPE.Rhombus; } else if (baseElement instanceof Event) { return DefaultProcessDiagramCanvas.SHAPE_TYPE.Ellipse; } // unknown source element, just do not correct coordinates return null; } protected static GraphicInfo getLineCenter(List graphicInfoList) { GraphicInfo gi = new GraphicInfo(); int xPoints[] = new int[graphicInfoList.size()]; int yPoints[] = new int[graphicInfoList.size()]; double length = 0; double[] lengths = new double[graphicInfoList.size()]; lengths[0] = 0; double m; for (int i = 1; i < graphicInfoList.size(); i++) { GraphicInfo graphicInfo = graphicInfoList.get(i); GraphicInfo previousGraphicInfo = graphicInfoList.get(i - 1); if (i == 1) { xPoints[0] = (int) previousGraphicInfo.getX(); yPoints[0] = (int) previousGraphicInfo.getY(); } xPoints[i] = (int) graphicInfo.getX(); yPoints[i] = (int) graphicInfo.getY(); length += Math.sqrt( Math.pow((int) graphicInfo.getX() - (int) previousGraphicInfo.getX(), 2) + Math.pow((int) graphicInfo.getY() - (int) previousGraphicInfo.getY(), 2) ); lengths[i] = length; } m = length / 2; int p1 = 0; int p2 = 1; for (int i = 1; i < lengths.length; i++) { double len = lengths[i]; p1 = i - 1; p2 = i; if (len > m) { break; } } GraphicInfo graphicInfo1 = graphicInfoList.get(p1); GraphicInfo graphicInfo2 = graphicInfoList.get(p2); double AB = (int) graphicInfo2.getX() - (int) graphicInfo1.getX(); double OA = (int) graphicInfo2.getY() - (int) graphicInfo1.getY(); double OB = lengths[p2] - lengths[p1]; double ob = m - lengths[p1]; double ab = AB * ob / OB; double oa = OA * ob / OB; double mx = graphicInfo1.getX() + ab; double my = graphicInfo1.getY() + oa; gi.setX(mx); gi.setY(my); return gi; } protected void drawArtifact(DefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, Artifact artifact) { ArtifactDrawInstruction drawInstruction = artifactDrawInstructions.get(artifact.getClass()); if (drawInstruction != null) { drawInstruction.draw(processDiagramCanvas, bpmnModel, artifact); } } private static void drawHighLight(DefaultProcessDiagramCanvas processDiagramCanvas, GraphicInfo graphicInfo) { processDiagramCanvas.drawHighLight((int) graphicInfo.getX(), (int) graphicInfo.getY(), (int) graphicInfo.getWidth(), (int) graphicInfo.getHeight()); } protected static DefaultProcessDiagramCanvas initProcessDiagramCanvas(BpmnModel bpmnModel, String activityFontName, String labelFontName, String annotationFontName) { // We need to calculate maximum values to know how big the image will be in its entirety double minX = Double.MAX_VALUE; double maxX = 0; double minY = Double.MAX_VALUE; double maxY = 0; for (Pool pool : bpmnModel.getPools()) { GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(pool.getId()); minX = graphicInfo.getX(); maxX = graphicInfo.getX() + graphicInfo.getWidth(); minY = graphicInfo.getY(); maxY = graphicInfo.getY() + graphicInfo.getHeight(); } List flowNodes = gatherAllFlowNodes(bpmnModel); for (FlowNode flowNode : flowNodes) { GraphicInfo flowNodeGraphicInfo = bpmnModel.getGraphicInfo(flowNode.getId()); // width if (flowNodeGraphicInfo.getX() + flowNodeGraphicInfo.getWidth() > maxX) { maxX = flowNodeGraphicInfo.getX() + flowNodeGraphicInfo.getWidth(); } if (flowNodeGraphicInfo.getX() < minX) { minX = flowNodeGraphicInfo.getX(); } // height if (flowNodeGraphicInfo.getY() + flowNodeGraphicInfo.getHeight() > maxY) { maxY = flowNodeGraphicInfo.getY() + flowNodeGraphicInfo.getHeight(); } if (flowNodeGraphicInfo.getY() < minY) { minY = flowNodeGraphicInfo.getY(); } for (SequenceFlow sequenceFlow : flowNode.getOutgoingFlows()) { List graphicInfoList = bpmnModel.getFlowLocationGraphicInfo(sequenceFlow.getId()); if (graphicInfoList != null) { for (GraphicInfo graphicInfo : graphicInfoList) { // width if (graphicInfo.getX() > maxX) { maxX = graphicInfo.getX(); } if (graphicInfo.getX() < minX) { minX = graphicInfo.getX(); } // height if (graphicInfo.getY() > maxY) { maxY = graphicInfo.getY(); } if (graphicInfo.getY() < minY) { minY = graphicInfo.getY(); } } } } } List artifacts = gatherAllArtifacts(bpmnModel); for (Artifact artifact : artifacts) { GraphicInfo artifactGraphicInfo = bpmnModel.getGraphicInfo(artifact.getId()); if (artifactGraphicInfo != null) { // width if (artifactGraphicInfo.getX() + artifactGraphicInfo.getWidth() > maxX) { maxX = artifactGraphicInfo.getX() + artifactGraphicInfo.getWidth(); } if (artifactGraphicInfo.getX() < minX) { minX = artifactGraphicInfo.getX(); } // height if (artifactGraphicInfo.getY() + artifactGraphicInfo.getHeight() > maxY) { maxY = artifactGraphicInfo.getY() + artifactGraphicInfo.getHeight(); } if (artifactGraphicInfo.getY() < minY) { minY = artifactGraphicInfo.getY(); } } List graphicInfoList = bpmnModel.getFlowLocationGraphicInfo(artifact.getId()); if (graphicInfoList != null) { for (GraphicInfo graphicInfo : graphicInfoList) { // width if (graphicInfo.getX() > maxX) { maxX = graphicInfo.getX(); } if (graphicInfo.getX() < minX) { minX = graphicInfo.getX(); } // height if (graphicInfo.getY() > maxY) { maxY = graphicInfo.getY(); } if (graphicInfo.getY() < minY) { minY = graphicInfo.getY(); } } } } int nrOfLanes = 0; for (Process process : bpmnModel.getProcesses()) { for (Lane l : process.getLanes()) { nrOfLanes++; GraphicInfo graphicInfo = bpmnModel.getGraphicInfo(l.getId()); // // width if (graphicInfo.getX() + graphicInfo.getWidth() > maxX) { maxX = graphicInfo.getX() + graphicInfo.getWidth(); } if (graphicInfo.getX() < minX) { minX = graphicInfo.getX(); } // height if (graphicInfo.getY() + graphicInfo.getHeight() > maxY) { maxY = graphicInfo.getY() + graphicInfo.getHeight(); } if (graphicInfo.getY() < minY) { minY = graphicInfo.getY(); } } } // Special case, see https://activiti.atlassian.net/browse/ACT-1431 if (flowNodes.isEmpty() && bpmnModel.getPools().isEmpty() && nrOfLanes == 0) { // Nothing to show minX = 0; minY = 0; } return new DefaultProcessDiagramCanvas((int) maxX + 10, (int) maxY + 10, (int) minX, (int) minY, activityFontName, labelFontName, annotationFontName); } protected static List gatherAllArtifacts(BpmnModel bpmnModel) { List artifacts = new ArrayList(); for (Process process : bpmnModel.getProcesses()) { artifacts.addAll(process.getArtifacts()); } return artifacts; } protected static List gatherAllFlowNodes(BpmnModel bpmnModel) { List flowNodes = new ArrayList(); for (Process process : bpmnModel.getProcesses()) { flowNodes.addAll(gatherAllFlowNodes(process)); } return flowNodes; } protected static List gatherAllFlowNodes(FlowElementsContainer flowElementsContainer) { List flowNodes = new ArrayList(); for (FlowElement flowElement : flowElementsContainer.getFlowElements()) { if (flowElement instanceof FlowNode) { flowNodes.add((FlowNode) flowElement); } if (flowElement instanceof FlowElementsContainer) { flowNodes.addAll(gatherAllFlowNodes((FlowElementsContainer) flowElement)); } } return flowNodes; } public Map, ActivityDrawInstruction> getActivityDrawInstructions() { return activityDrawInstructions; } public void setActivityDrawInstructions( Map, ActivityDrawInstruction> activityDrawInstructions) { this.activityDrawInstructions = activityDrawInstructions; } public Map, ArtifactDrawInstruction> getArtifactDrawInstructions() { return artifactDrawInstructions; } public void setArtifactDrawInstructions( Map, ArtifactDrawInstruction> artifactDrawInstructions) { this.artifactDrawInstructions = artifactDrawInstructions; } protected interface ActivityDrawInstruction { void draw(DefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, FlowNode flowNode); } protected interface ArtifactDrawInstruction { void draw(DefaultProcessDiagramCanvas processDiagramCanvas, BpmnModel bpmnModel, Artifact artifact); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy