/* Copyright 2012-2015 SAP SE * * 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 eu.aniketos.securebpmn.visualization; import java.util.List; import org.eclipse.bpmn2.Event; import org.eclipse.bpmn2.Gateway; import org.eclipse.bpmn2.SequenceFlow; import org.eclipse.bpmn2.Task; import org.eclipse.emf.ecore.EObject; import org.eclipse.graphiti.mm.algorithms.Ellipse; import org.eclipse.graphiti.mm.algorithms.GraphicsAlgorithm; import org.eclipse.graphiti.mm.algorithms.Polygon; import org.eclipse.graphiti.mm.algorithms.Rectangle; import org.eclipse.graphiti.mm.algorithms.RoundedRectangle; import org.eclipse.graphiti.mm.pictograms.Anchor; import org.eclipse.graphiti.mm.pictograms.Connection; import org.eclipse.graphiti.mm.pictograms.ContainerShape; import org.eclipse.graphiti.mm.pictograms.Diagram; import org.eclipse.graphiti.mm.pictograms.PictogramElement; import org.eclipse.graphiti.mm.pictograms.Shape; import org.eclipse.graphiti.services.Graphiti; import org.eclipse.graphiti.services.IGaService; import org.eclipse.graphiti.services.ILinkService; import org.eclipse.securebpmn2.BindingOfDuty; import org.eclipse.securebpmn2.SeparationOfDuty; import eu.aniketos.securebpmn.validation.SCVMValidationConstants; /** * A runnable for highlighting the elements in on step of the attack trace. * * */ public class HighlightVisualizationElementsRunnable implements Runnable { private Diagram diagram; private List<VisualizationElement> elements; private boolean revert; private IGaService gaService; /** * Default constructor. * * @param diagram * The diagram in which the visualization takes place. * @param elements * The List of elements that should be highlighted. * @param revert * true if the reverse visualization should be applied, false if * not. */ public HighlightVisualizationElementsRunnable(Diagram diagram, List<VisualizationElement> elements, boolean revert) { this.diagram = diagram; this.elements = elements; this.revert = revert; this.gaService = Graphiti.getGaService(); } /* * (non-Javadoc) * * @see java.lang.Runnable#run() */ @Override public void run() { for (VisualizationElement element : elements) { if (element.getbObject() instanceof Task) { highlightTask(element.getpElement(), element.getAction()); } else if (element.getbObject() instanceof Gateway) { highlightGateway(element.getpElement(), element.getAction()); } else if (element.getbObject() instanceof Event) { highlightEvent(element.getpElement(), element.getAction()); } else if (element.getbObject() instanceof SeparationOfDuty || element.getbObject() instanceof BindingOfDuty) { highlightTaskLikeElement(element.getpElement(), element.getAction(), false); } } } /** * Performs the highlighting for a Task. * * @param pElement * The corresponding PictogramElement. * @param action * The action that defines the highlighting. */ private void highlightTask(PictogramElement pElement, ActionType action) { highlightTaskLikeElement(pElement, action, true); } /** * Performs the highlighting for a Task and the incoming SequenceFlow. * * @param pElement * The corresponding PictogramElement. * @param action * The action that defines the highlighting. * @param withSequenceFlow * true if the incoming SequenceFlow should be highlighted, false * if not. */ private void highlightTaskLikeElement(PictogramElement pElement, ActionType action, boolean withSequenceFlow) { // highlighting for tasks ContainerShape cs = (ContainerShape) pElement; Shape removeShape = null; int overlayWidth = 105; int overlayHeight = 55; if (cs.getGraphicsAlgorithm() instanceof Rectangle) { Rectangle rect = (Rectangle) cs.getGraphicsAlgorithm(); overlayWidth = rect.getWidth(); overlayHeight = rect.getHeight(); } for (Shape shape : cs.getChildren()) { final GraphicsAlgorithm ga = shape.getGraphicsAlgorithm(); if (ga instanceof RoundedRectangle) { // overlay already exists, remove it removeShape = shape; } } if (removeShape != null) // finally remove overlay cs.getChildren().remove(removeShape); if (!revert) { // create overlay final Shape s = Graphiti.getPeCreateService() .createShape(cs, false); final RoundedRectangle rr = gaService.createRoundedRectangle(s, 20, 20); rr.setLineVisible(true); rr.setFilled(true); rr.setLineWidth(2); rr.setTransparency(0.7); if (action == ActionType.VIOLATION) { rr.setForeground(gaService.manageColor(diagram, SCVMValidationConstants.COLOR_HL_VIOL_FG[0], SCVMValidationConstants.COLOR_HL_VIOL_FG[1], SCVMValidationConstants.COLOR_HL_VIOL_FG[2])); rr.setBackground(gaService.manageColor(diagram, SCVMValidationConstants.COLOR_HL_VIOL_BG[0], SCVMValidationConstants.COLOR_HL_VIOL_BG[1], SCVMValidationConstants.COLOR_HL_VIOL_BG[2])); } else if (action == ActionType.EXECUTE) { rr.setForeground(gaService.manageColor(diagram, SCVMValidationConstants.COLOR_HL_EXEC_FG[0], SCVMValidationConstants.COLOR_HL_EXEC_FG[1], SCVMValidationConstants.COLOR_HL_EXEC_FG[2])); rr.setBackground(gaService.manageColor(diagram, SCVMValidationConstants.COLOR_HL_EXEC_BG[0], SCVMValidationConstants.COLOR_HL_EXEC_BG[1], SCVMValidationConstants.COLOR_HL_EXEC_BG[2])); } else if (action == ActionType.CLAIM) { rr.setForeground(gaService.manageColor(diagram, SCVMValidationConstants.COLOR_HL_CLAIM_FG[0], SCVMValidationConstants.COLOR_HL_CLAIM_FG[1], SCVMValidationConstants.COLOR_HL_CLAIM_FG[2])); rr.setBackground(gaService.manageColor(diagram, SCVMValidationConstants.COLOR_HL_CLAIM_BG[0], SCVMValidationConstants.COLOR_HL_CLAIM_BG[1], SCVMValidationConstants.COLOR_HL_CLAIM_BG[2])); } else if (action == ActionType.ASSIGN) { rr.setForeground(gaService.manageColor(diagram, SCVMValidationConstants.COLOR_HL_ASSIGN_FG[0], SCVMValidationConstants.COLOR_HL_ASSIGN_FG[1], SCVMValidationConstants.COLOR_HL_ASSIGN_FG[2])); rr.setBackground(gaService.manageColor(diagram, SCVMValidationConstants.COLOR_HL_ASSIGN_BG[0], SCVMValidationConstants.COLOR_HL_ASSIGN_BG[1], SCVMValidationConstants.COLOR_HL_ASSIGN_BG[2])); } else if (action == ActionType.WORKFLOW) { rr.setForeground(gaService.manageColor(diagram, SCVMValidationConstants.COLOR_HL_WORK_FG[0], SCVMValidationConstants.COLOR_HL_WORK_FG[1], SCVMValidationConstants.COLOR_HL_WORK_FG[2])); rr.setBackground(gaService.manageColor(diagram, SCVMValidationConstants.COLOR_HL_WORK_BG[0], SCVMValidationConstants.COLOR_HL_WORK_BG[1], SCVMValidationConstants.COLOR_HL_WORK_BG[2])); } gaService.setLocationAndSize(rr, 0, 0, overlayWidth, overlayHeight); } if (withSequenceFlow) highlightIncomingSequenceFlow(cs); } /** * Performs the highlighting for a Gateway. * * @param pElement * The corresponding PictogramElement. * @param action * The action that defines the highlighting. */ private void highlightGateway(PictogramElement pElement, ActionType action) { // highlighting for gateways ContainerShape cs = (ContainerShape) pElement; Shape removeShape = null; for (Shape shape : cs.getChildren()) { final GraphicsAlgorithm ga = shape.getGraphicsAlgorithm(); if (ga instanceof Polygon) { // overlay already exists, remove it removeShape = shape; } } if (removeShape != null) // finally remove overlay cs.getChildren().remove(removeShape); if (!revert) { // create overlay final Shape s = Graphiti.getPeCreateService() .createShape(cs, false); int xy[] = new int[] { 0, 20, 20, 0, 40, 20, 20, 40, 0, 20 }; final Polygon p = gaService.createPolygon(s, xy); p.setLineVisible(true); p.setFilled(true); p.setLineWidth(2); p.setTransparency(0.7); if (action == ActionType.VIOLATION) { p.setForeground(gaService.manageColor(diagram, SCVMValidationConstants.COLOR_HL_VIOL_FG[0], SCVMValidationConstants.COLOR_HL_VIOL_FG[1], SCVMValidationConstants.COLOR_HL_VIOL_FG[2])); p.setBackground(gaService.manageColor(diagram, SCVMValidationConstants.COLOR_HL_VIOL_BG[0], SCVMValidationConstants.COLOR_HL_VIOL_BG[1], SCVMValidationConstants.COLOR_HL_VIOL_BG[2])); } else if (action == ActionType.EXECUTE) { p.setForeground(gaService.manageColor(diagram, SCVMValidationConstants.COLOR_HL_EXEC_FG[0], SCVMValidationConstants.COLOR_HL_EXEC_FG[1], SCVMValidationConstants.COLOR_HL_EXEC_FG[2])); p.setBackground(gaService.manageColor(diagram, SCVMValidationConstants.COLOR_HL_EXEC_BG[0], SCVMValidationConstants.COLOR_HL_EXEC_BG[1], SCVMValidationConstants.COLOR_HL_EXEC_BG[2])); } else if (action == ActionType.CLAIM) { p.setForeground(gaService.manageColor(diagram, SCVMValidationConstants.COLOR_HL_CLAIM_FG[0], SCVMValidationConstants.COLOR_HL_CLAIM_FG[1], SCVMValidationConstants.COLOR_HL_CLAIM_FG[2])); p.setBackground(gaService.manageColor(diagram, SCVMValidationConstants.COLOR_HL_CLAIM_BG[0], SCVMValidationConstants.COLOR_HL_CLAIM_BG[1], SCVMValidationConstants.COLOR_HL_CLAIM_BG[2])); } else if (action == ActionType.ASSIGN) { p.setForeground(gaService.manageColor(diagram, SCVMValidationConstants.COLOR_HL_ASSIGN_FG[0], SCVMValidationConstants.COLOR_HL_ASSIGN_FG[1], SCVMValidationConstants.COLOR_HL_ASSIGN_FG[2])); p.setBackground(gaService.manageColor(diagram, SCVMValidationConstants.COLOR_HL_ASSIGN_BG[0], SCVMValidationConstants.COLOR_HL_ASSIGN_BG[1], SCVMValidationConstants.COLOR_HL_ASSIGN_BG[2])); } else if (action == ActionType.WORKFLOW) { p.setForeground(gaService.manageColor(diagram, SCVMValidationConstants.COLOR_HL_WORK_FG[0], SCVMValidationConstants.COLOR_HL_WORK_FG[1], SCVMValidationConstants.COLOR_HL_WORK_FG[2])); p.setBackground(gaService.manageColor(diagram, SCVMValidationConstants.COLOR_HL_WORK_BG[0], SCVMValidationConstants.COLOR_HL_WORK_BG[1], SCVMValidationConstants.COLOR_HL_WORK_BG[2])); } gaService.setLocationAndSize(p, 0, 0, 40, 40); } highlightIncomingSequenceFlow(cs); } /** * Performs the highlighting for an Event. * * @param pElement * The corresponding PictogramElement. * @param action * The action that defines the highlighting. */ private void highlightEvent(PictogramElement pElement, ActionType action) { // highlighting for events ContainerShape cs = (ContainerShape) pElement; Shape removeShape = null; for (Shape shape : cs.getChildren()) { final GraphicsAlgorithm ga = shape.getGraphicsAlgorithm(); if (ga instanceof Ellipse) { // overlay already exists, remove it removeShape = shape; } } if (removeShape != null) // finally remove overlay cs.getChildren().remove(removeShape); if (!revert) { // create overlay final Shape s = Graphiti.getPeCreateService() .createShape(cs, false); final Ellipse e = gaService.createEllipse(s); e.setLineVisible(true); e.setFilled(true); e.setLineWidth(4); e.setTransparency(0.7); if (action == ActionType.VIOLATION) { e.setForeground(gaService.manageColor(diagram, SCVMValidationConstants.COLOR_HL_VIOL_FG[0], SCVMValidationConstants.COLOR_HL_VIOL_FG[1], SCVMValidationConstants.COLOR_HL_VIOL_FG[2])); e.setBackground(gaService.manageColor(diagram, SCVMValidationConstants.COLOR_HL_VIOL_BG[0], SCVMValidationConstants.COLOR_HL_VIOL_BG[1], SCVMValidationConstants.COLOR_HL_VIOL_BG[2])); } else if (action == ActionType.EXECUTE) { e.setForeground(gaService.manageColor(diagram, SCVMValidationConstants.COLOR_HL_EXEC_FG[0], SCVMValidationConstants.COLOR_HL_EXEC_FG[1], SCVMValidationConstants.COLOR_HL_EXEC_FG[2])); e.setBackground(gaService.manageColor(diagram, SCVMValidationConstants.COLOR_HL_EXEC_BG[0], SCVMValidationConstants.COLOR_HL_EXEC_BG[1], SCVMValidationConstants.COLOR_HL_EXEC_BG[2])); } else if (action == ActionType.CLAIM) { e.setForeground(gaService.manageColor(diagram, SCVMValidationConstants.COLOR_HL_CLAIM_FG[0], SCVMValidationConstants.COLOR_HL_CLAIM_FG[1], SCVMValidationConstants.COLOR_HL_CLAIM_FG[2])); e.setBackground(gaService.manageColor(diagram, SCVMValidationConstants.COLOR_HL_CLAIM_BG[0], SCVMValidationConstants.COLOR_HL_CLAIM_BG[1], SCVMValidationConstants.COLOR_HL_CLAIM_BG[2])); } else if (action == ActionType.ASSIGN) { e.setForeground(gaService.manageColor(diagram, SCVMValidationConstants.COLOR_HL_ASSIGN_FG[0], SCVMValidationConstants.COLOR_HL_ASSIGN_FG[1], SCVMValidationConstants.COLOR_HL_ASSIGN_FG[2])); e.setBackground(gaService.manageColor(diagram, SCVMValidationConstants.COLOR_HL_ASSIGN_BG[0], SCVMValidationConstants.COLOR_HL_ASSIGN_BG[1], SCVMValidationConstants.COLOR_HL_ASSIGN_BG[2])); } else if (action == ActionType.WORKFLOW) { e.setForeground(gaService.manageColor(diagram, SCVMValidationConstants.COLOR_HL_WORK_FG[0], SCVMValidationConstants.COLOR_HL_WORK_FG[1], SCVMValidationConstants.COLOR_HL_WORK_FG[2])); e.setBackground(gaService.manageColor(diagram, SCVMValidationConstants.COLOR_HL_WORK_BG[0], SCVMValidationConstants.COLOR_HL_WORK_BG[1], SCVMValidationConstants.COLOR_HL_WORK_BG[2])); } gaService.setLocationAndSize(e, 0, 0, 35, 35); } highlightIncomingSequenceFlow(cs); } /** * Performs the highlighting for a SequenceFlow. * * @param cs * The corresponding ContainerShape. */ private void highlightIncomingSequenceFlow(ContainerShape cs) { // highlighting of incoming sequence flow ILinkService linkService = Graphiti.getLinkService(); // loop over incoming connections for (Anchor anchor : cs.getAnchors()) { for (Connection connection : anchor.getIncomingConnections()) { EObject linkedObject = linkService .getBusinessObjectForLinkedPictogramElement(connection); if (!(linkedObject instanceof SequenceFlow)) { continue; } // determine if connection comes from highlighted element boolean sourceIsHighlighted = false; PictogramElement sourcePictogramElement = connection.getStart() .getParent().getGraphicsAlgorithm() .getPictogramElement(); if (sourcePictogramElement instanceof ContainerShape) { for (Shape shape : ((ContainerShape) sourcePictogramElement) .getChildren()) { final GraphicsAlgorithm ga = shape .getGraphicsAlgorithm(); if (ga instanceof RoundedRectangle || ga instanceof Ellipse || ga instanceof Polygon) { sourceIsHighlighted = true; break; } } } if (sourceIsHighlighted) { GraphicsAlgorithm connectionGA = connection .getGraphicsAlgorithm(); if (revert) { // remove highlighting of sequenceFlow connectionGA.setLineWidth(1); connectionGA.setForeground(gaService.manageColor( diagram, SCVMValidationConstants.COLOR_DEF_SEQFLOW[0], SCVMValidationConstants.COLOR_DEF_SEQFLOW[1], SCVMValidationConstants.COLOR_DEF_SEQFLOW[2])); } else { // highlight sequenceFlow // TODO make highlighting more beautiful (overlay?) connectionGA.setLineWidth(2); connectionGA.setForeground(gaService.manageColor( diagram, SCVMValidationConstants.COLOR_HL_WORK_FG[0], SCVMValidationConstants.COLOR_HL_WORK_FG[1], SCVMValidationConstants.COLOR_HL_WORK_FG[2])); } } } } } }