From 88f715e2631219448c0066c85871d32081e42fd2 Mon Sep 17 00:00:00 2001 From: Thomas Bouffard <27200110+tbouffard@users.noreply.github.com> Date: Tue, 8 Jun 2021 10:57:11 +0200 Subject: [PATCH] refactor(waypoints): split code and remove duplications Extract code from WayPointsComputer: remove duplications and clarify responsibilities. This class now only does the orchestration. The waypoints description and conversion to display model are done in dedicated classes. Move display model domain classes to a dedicated package (clarify and remove cyclic dependencies). Rename some methods and classes to better express their purpose. --- .../AlgoToDisplayModelConverter.java | 173 ++---- .../generator/converter/Configuration.java | 12 + .../waypoint/EdgeTerminalPoints.java | 4 +- .../converter/waypoint/GridSearcher.java | 7 +- ...Direction.java => WayPointDescriptor.java} | 4 +- .../converter/waypoint/WayPointsComputer.java | 273 +-------- .../waypoint/WayPointsConverter.java | 154 +++++ .../waypoint/WayPointsPositioner.java | 137 +++++ .../bpmn/generator/export/BPMNExporter.java | 2 +- .../bpmn/generator/export/SVGExporter.java | 6 +- .../internal/BPMNDiagramRichBuilder.java | 12 +- .../model/display/DisplayDimension.java | 24 + .../generator/model/display/DisplayEdge.java | 28 + .../model/display/DisplayFlowNode.java | 31 + .../generator/model/display/DisplayLabel.java | 23 + .../generator/model/display/DisplayModel.java | 32 + .../generator/model/display/DisplayPoint.java | 24 + .../waypoint/WayPointsComputerTest.java | 556 ------------------ .../waypoint/WayPointsPositionerTest.java | 556 ++++++++++++++++++ 19 files changed, 1109 insertions(+), 949 deletions(-) rename java/src/main/java/io/process/analytics/tools/bpmn/generator/converter/waypoint/{EdgeDirection.java => WayPointDescriptor.java} (92%) create mode 100644 java/src/main/java/io/process/analytics/tools/bpmn/generator/converter/waypoint/WayPointsConverter.java create mode 100644 java/src/main/java/io/process/analytics/tools/bpmn/generator/converter/waypoint/WayPointsPositioner.java create mode 100644 java/src/main/java/io/process/analytics/tools/bpmn/generator/model/display/DisplayDimension.java create mode 100644 java/src/main/java/io/process/analytics/tools/bpmn/generator/model/display/DisplayEdge.java create mode 100644 java/src/main/java/io/process/analytics/tools/bpmn/generator/model/display/DisplayFlowNode.java create mode 100644 java/src/main/java/io/process/analytics/tools/bpmn/generator/model/display/DisplayLabel.java create mode 100644 java/src/main/java/io/process/analytics/tools/bpmn/generator/model/display/DisplayModel.java create mode 100644 java/src/main/java/io/process/analytics/tools/bpmn/generator/model/display/DisplayPoint.java delete mode 100644 java/src/test/java/io/process/analytics/tools/bpmn/generator/converter/waypoint/WayPointsComputerTest.java create mode 100644 java/src/test/java/io/process/analytics/tools/bpmn/generator/converter/waypoint/WayPointsPositionerTest.java diff --git a/java/src/main/java/io/process/analytics/tools/bpmn/generator/converter/AlgoToDisplayModelConverter.java b/java/src/main/java/io/process/analytics/tools/bpmn/generator/converter/AlgoToDisplayModelConverter.java index 21668493..0a982087 100644 --- a/java/src/main/java/io/process/analytics/tools/bpmn/generator/converter/AlgoToDisplayModelConverter.java +++ b/java/src/main/java/io/process/analytics/tools/bpmn/generator/converter/AlgoToDisplayModelConverter.java @@ -18,14 +18,12 @@ import static io.process.analytics.tools.bpmn.generator.converter.Configuration.CELL_HEIGHT; import static io.process.analytics.tools.bpmn.generator.converter.Configuration.CELL_WIDTH; -import java.util.List; +import java.util.Collection; +import java.util.stream.Collectors; import io.process.analytics.tools.bpmn.generator.converter.waypoint.WayPointsComputer; import io.process.analytics.tools.bpmn.generator.model.*; -import lombok.Builder; -import lombok.RequiredArgsConstructor; -import lombok.Singular; -import lombok.ToString; +import io.process.analytics.tools.bpmn.generator.model.display.*; public class AlgoToDisplayModelConverter { @@ -37,131 +35,76 @@ public DisplayModel convert(Grid grid, Diagram diagram) { // increase to display edges with extra paths to avoid shape overlapping model.width(grid.width() * CELL_WIDTH).height((grid.height() + 1) * CELL_HEIGHT); - for (Position position : grid.getPositions()) { - int xOffset = position.getX() * CELL_WIDTH; - int yOffset = position.getY() * CELL_HEIGHT; - int nodeWidth = x(60); - int nodeHeight = y(60); - - // TODO manage when not found (should not occur) - Shape shape = diagram.getShapes().stream() - .filter(s -> s.getId().equals(position.getShape())) - .findFirst().get(); - String name = shape.getName(); - - // ensure to have a square shape (i.e. same width and height) for non activity elements - ShapeType shapeType = shape.getType(); - if (shapeType == ShapeType.EVENT || shapeType == ShapeType.GATEWAY) { - int nodeDimension = Math.min(nodeWidth, nodeHeight); - if (shapeType == ShapeType.EVENT) { - nodeDimension /= 2; - } - nodeWidth = nodeDimension; - nodeHeight = nodeDimension; - } - - int x = xOffset + (CELL_WIDTH - nodeWidth) / 2; - int y = yOffset + (CELL_HEIGHT - nodeHeight) / 2; - DisplayDimension flowNodeDimension = new DisplayDimension(x, y, nodeWidth, nodeHeight); - - // Labels positions better work with the SVG export - // BPMN label positions are adjusted in BPMNDiagramRichBuilder - int labelX = xOffset + x(50); - int labelY = yOffset + y(50); - if (shapeType == ShapeType.EVENT) { // put the label under the shape - labelY = (int) (y + nodeHeight * 1.5); - } else if (shapeType == ShapeType.GATEWAY) { // put the label on the top left of the shape - labelX = (int) (x - nodeWidth * 0.5); - labelY = (int) (y - nodeHeight * 0.5); - } + Collection flowNodes = grid.getPositions().stream() + .map(position -> toDisplayFlowNode(position, diagram)) + .collect(Collectors.toList()); + model.flowNodes(flowNodes); - DisplayDimension labelDimension = new DisplayDimension(labelX, labelY, nodeWidth, nodeHeight); - DisplayLabel label = new DisplayLabel(name, y(16), labelDimension); - - model.flowNode(DisplayFlowNode.builder().bpmnElementId(shape.getId()) - .dimension(flowNodeDimension) - .label(label) - .type(shapeType) - .rx(y(10)).strokeWidth(y(5)).build()); - } - - WayPointsComputer wayPointsComputer = new WayPointsComputer(grid, model.flowNodes); + WayPointsComputer wayPointsComputer = new WayPointsComputer(grid, flowNodes); diagram.getEdges() .stream() - .map(edge -> new DisplayEdge(edge.getId(), wayPointsComputer.inferWayPoints(edge))) + .map(edge -> new DisplayEdge(edge.getId(), wayPointsComputer.compute(edge))) .forEach(model::edge); return model.build(); } - private static int x(int percentage) { - return CELL_WIDTH * percentage / 100; - } - - private static int y(int percentage) { - return CELL_HEIGHT * percentage / 100; - } - - - @RequiredArgsConstructor - @Builder - public static class DisplayModel { - public final int width; - public final int height; - - @Singular - public final List flowNodes; - @Singular - public final List edges; - - } - - @RequiredArgsConstructor - @Builder - public static class DisplayFlowNode { - - public final String bpmnElementId; - public final DisplayDimension dimension; - public final DisplayLabel label; - // for non BPMN exporters only - public final ShapeType type; - public final int rx; - public final int strokeWidth; - - } - - @RequiredArgsConstructor - @Builder - public static class DisplayEdge { - - public final String bpmnElementId; - public final List wayPoints; + private DisplayFlowNode toDisplayFlowNode(Position position, Diagram diagram) { + int xOffset = position.getX() * CELL_WIDTH; + int yOffset = position.getY() * CELL_HEIGHT; + int nodeWidth = x(60); + int nodeHeight = y(60); + + // TODO manage when not found (should not occur) + Shape shape = diagram.getShapes().stream() + .filter(s -> s.getId().equals(position.getShape())) + .findFirst().get(); + String name = shape.getName(); + + // ensure to have a square shape (i.e. same width and height) for non activity elements + ShapeType shapeType = shape.getType(); + if (shapeType == ShapeType.EVENT || shapeType == ShapeType.GATEWAY) { + int nodeDimension = Math.min(nodeWidth, nodeHeight); + if (shapeType == ShapeType.EVENT) { + nodeDimension /= 2; + } + nodeWidth = nodeDimension; + nodeHeight = nodeDimension; + } - } + int x = xOffset + (CELL_WIDTH - nodeWidth) / 2; + int y = yOffset + (CELL_HEIGHT - nodeHeight) / 2; + DisplayDimension flowNodeDimension = new DisplayDimension(x, y, nodeWidth, nodeHeight); + + // Labels positions better work with the SVG export + // BPMN label positions are adjusted in BPMNDiagramRichBuilder + int labelX = xOffset + x(50); + int labelY = yOffset + y(50); + if (shapeType == ShapeType.EVENT) { // put the label under the shape + labelY = (int) (y + nodeHeight * 1.5); + } else if (shapeType == ShapeType.GATEWAY) { // put the label on the top left of the shape + labelX = (int) (x - nodeWidth * 0.5); + labelY = (int) (y - nodeHeight * 0.5); + } - @RequiredArgsConstructor - public static class DisplayDimension { + DisplayDimension labelDimension = new DisplayDimension(labelX, labelY, nodeWidth, nodeHeight); + DisplayLabel label = new DisplayLabel(name, y(16), labelDimension); - public final int x; - public final int y; - public final int width; - public final int height; + return DisplayFlowNode.builder().bpmnElementId(shape.getId()) + .dimension(flowNodeDimension) + .label(label) + .type(shapeType) + .rx(y(10)) + .strokeWidth(y(5)) + .build(); } - @RequiredArgsConstructor - public static class DisplayLabel { - - public final String text; // for non BPMN exporters only - public final int fontSize; - public final DisplayDimension dimension; + private static int x(int percentage) { + return CELL_WIDTH * percentage / 100; } - @RequiredArgsConstructor - @ToString - public static class DisplayPoint { - - public final int x; - public final int y; + private static int y(int percentage) { + return CELL_HEIGHT * percentage / 100; } } diff --git a/java/src/main/java/io/process/analytics/tools/bpmn/generator/converter/Configuration.java b/java/src/main/java/io/process/analytics/tools/bpmn/generator/converter/Configuration.java index d6877ff8..e5268bb3 100644 --- a/java/src/main/java/io/process/analytics/tools/bpmn/generator/converter/Configuration.java +++ b/java/src/main/java/io/process/analytics/tools/bpmn/generator/converter/Configuration.java @@ -1,3 +1,15 @@ +/* + * Copyright 2021 Bonitasoft S.A. + * 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 io.process.analytics.tools.bpmn.generator.converter; public class Configuration { diff --git a/java/src/main/java/io/process/analytics/tools/bpmn/generator/converter/waypoint/EdgeTerminalPoints.java b/java/src/main/java/io/process/analytics/tools/bpmn/generator/converter/waypoint/EdgeTerminalPoints.java index a350018a..7847e2f8 100644 --- a/java/src/main/java/io/process/analytics/tools/bpmn/generator/converter/waypoint/EdgeTerminalPoints.java +++ b/java/src/main/java/io/process/analytics/tools/bpmn/generator/converter/waypoint/EdgeTerminalPoints.java @@ -12,8 +12,8 @@ */ package io.process.analytics.tools.bpmn.generator.converter.waypoint; -import io.process.analytics.tools.bpmn.generator.converter.AlgoToDisplayModelConverter.DisplayDimension; -import io.process.analytics.tools.bpmn.generator.converter.AlgoToDisplayModelConverter.DisplayPoint; +import io.process.analytics.tools.bpmn.generator.model.display.DisplayDimension; +import io.process.analytics.tools.bpmn.generator.model.display.DisplayPoint; /** * Compute coordinates of the terminal points (source or target) of an Edge. diff --git a/java/src/main/java/io/process/analytics/tools/bpmn/generator/converter/waypoint/GridSearcher.java b/java/src/main/java/io/process/analytics/tools/bpmn/generator/converter/waypoint/GridSearcher.java index 2b07a5f8..83d91dd1 100644 --- a/java/src/main/java/io/process/analytics/tools/bpmn/generator/converter/waypoint/GridSearcher.java +++ b/java/src/main/java/io/process/analytics/tools/bpmn/generator/converter/waypoint/GridSearcher.java @@ -12,9 +12,6 @@ */ package io.process.analytics.tools.bpmn.generator.converter.waypoint; -import java.util.List; -import java.util.stream.Collectors; - import io.process.analytics.tools.bpmn.generator.model.Edge; import io.process.analytics.tools.bpmn.generator.model.Grid; import io.process.analytics.tools.bpmn.generator.model.Position; @@ -69,8 +66,8 @@ public boolean isShapeExistAbove(final Position positionFrom) { .anyMatch(p -> p.getY() == positionFrom.getY() - 1); } - - public BendConfiguration searchEmptyRow(Position positionFrom, Position positionTo, BendDirection searchDirection) { + public BendConfiguration computeConfigurationToPassByEmptyRow(Position positionFrom, Position positionTo, + BendDirection searchDirection) { int positionFromY = positionFrom.getY(); int offset = -1; boolean isElementBetween = true; diff --git a/java/src/main/java/io/process/analytics/tools/bpmn/generator/converter/waypoint/EdgeDirection.java b/java/src/main/java/io/process/analytics/tools/bpmn/generator/converter/waypoint/WayPointDescriptor.java similarity index 92% rename from java/src/main/java/io/process/analytics/tools/bpmn/generator/converter/waypoint/EdgeDirection.java rename to java/src/main/java/io/process/analytics/tools/bpmn/generator/converter/waypoint/WayPointDescriptor.java index 4f2d2988..8e375e82 100644 --- a/java/src/main/java/io/process/analytics/tools/bpmn/generator/converter/waypoint/EdgeDirection.java +++ b/java/src/main/java/io/process/analytics/tools/bpmn/generator/converter/waypoint/WayPointDescriptor.java @@ -13,9 +13,11 @@ package io.process.analytics.tools.bpmn.generator.converter.waypoint; import lombok.Builder; +import lombok.ToString; @Builder -public class EdgeDirection { +@ToString +public class WayPointDescriptor { public final Direction direction; public final Orientation orientation; diff --git a/java/src/main/java/io/process/analytics/tools/bpmn/generator/converter/waypoint/WayPointsComputer.java b/java/src/main/java/io/process/analytics/tools/bpmn/generator/converter/waypoint/WayPointsComputer.java index d2345d76..ff0b356b 100644 --- a/java/src/main/java/io/process/analytics/tools/bpmn/generator/converter/waypoint/WayPointsComputer.java +++ b/java/src/main/java/io/process/analytics/tools/bpmn/generator/converter/waypoint/WayPointsComputer.java @@ -12,292 +12,47 @@ */ package io.process.analytics.tools.bpmn.generator.converter.waypoint; -import static io.process.analytics.tools.bpmn.generator.converter.Configuration.CELL_HEIGHT; -import static io.process.analytics.tools.bpmn.generator.converter.waypoint.Direction.*; -import static io.process.analytics.tools.bpmn.generator.converter.waypoint.Orientation.*; - -import java.util.ArrayList; +import java.util.Collection; import java.util.List; -import io.process.analytics.tools.bpmn.generator.converter.AlgoToDisplayModelConverter.DisplayDimension; -import io.process.analytics.tools.bpmn.generator.converter.AlgoToDisplayModelConverter.DisplayFlowNode; -import io.process.analytics.tools.bpmn.generator.converter.AlgoToDisplayModelConverter.DisplayPoint; import io.process.analytics.tools.bpmn.generator.model.Edge; import io.process.analytics.tools.bpmn.generator.model.Grid; import io.process.analytics.tools.bpmn.generator.model.Position; -import io.process.analytics.tools.bpmn.generator.model.ShapeType; +import io.process.analytics.tools.bpmn.generator.model.display.DisplayFlowNode; +import io.process.analytics.tools.bpmn.generator.model.display.DisplayPoint; import lombok.extern.log4j.Log4j2; @Log4j2 public class WayPointsComputer { - private final List flowNodes; + private final Collection flowNodes; private final GridSearcher gridSearcher; + private final WayPointsConverter wayPointsConverter = new WayPointsConverter(); + private final WayPointsPositioner wayPointsPositioner; - public WayPointsComputer(final Grid grid, final List flowNodes) { + public WayPointsComputer(final Grid grid, final Collection flowNodes) { this.flowNodes = flowNodes; gridSearcher = new GridSearcher(grid); + wayPointsPositioner = new WayPointsPositioner(gridSearcher); } - public List inferWayPoints(Edge edge) { + public List compute(Edge edge) { log.debug("Inferring waypoints of edge {}", edge); Position positionFrom = gridSearcher.getPositionFrom(edge); Position positionTo = gridSearcher.getPositionTo(edge); - EdgeDirection edgeDirection = computeEdgeDirection(positionFrom, positionTo); - DisplayFlowNode flowNodeFrom = getFlowNode(flowNodes, positionFrom.getShape()); - DisplayFlowNode flowNodeTo = getFlowNode(flowNodes, positionTo.getShape()); - - return computeWayPoints(edgeDirection, flowNodeFrom, flowNodeTo); - } - - private final static EdgeTerminalPoints edgeTerminalPoints = new EdgeTerminalPoints(); - - private static List computeWayPoints(EdgeDirection edgeDirection, DisplayFlowNode flowNodeFrom, - DisplayFlowNode flowNodeTo) { - DisplayDimension dimensionFrom = flowNodeFrom.dimension; - DisplayDimension dimensionTo = flowNodeTo.dimension; - - List wayPoints = new ArrayList<>(); - - Orientation orientation = edgeDirection.orientation; - switch (edgeDirection.direction) { - case LeftToRight: - if (orientation == Horizontal) { - wayPoints.add(edgeTerminalPoints.rightMiddle(dimensionFrom)); - wayPoints.add(edgeTerminalPoints.leftMiddle(dimensionTo)); - } - // Special case add bend points to avoid edge overlapping on shape - else if (orientation == VerticalHorizontalVertical) { - log.debug("Special case LeftToRight VerticalHorizontalVertical"); - BendConfiguration bendConfiguration = edgeDirection.bendConfiguration; - log.debug("Bend configuration: {}", bendConfiguration); - - DisplayPoint from = bendConfiguration.direction == BendDirection.BOTTOM ? edgeTerminalPoints.centerBottom(dimensionFrom): edgeTerminalPoints.centerTop(dimensionFrom); - DisplayPoint to = bendConfiguration.direction == BendDirection.BOTTOM ? edgeTerminalPoints.centerBottom(dimensionTo): edgeTerminalPoints.centerTop(dimensionTo); - int bendPointY = from.y + bendConfiguration.direction.numericFactor() * bendConfiguration.offset * CELL_HEIGHT; - - wayPoints.add(from); - wayPoints.add(new DisplayPoint(from.x, bendPointY)); - wayPoints.add(new DisplayPoint(to.x, bendPointY)); - wayPoints.add(to); - } - break; - case RightToLeft: - if (orientation == Horizontal) { - wayPoints.add(edgeTerminalPoints.leftMiddle(dimensionFrom)); - wayPoints.add(edgeTerminalPoints.rightMiddle(dimensionTo)); - } - // Special case add bend points to avoid edge overlapping on shape - else if (orientation == VerticalHorizontalVertical) { // TODO duplication with LeftToRight - log.debug("Special case RightToLeft VerticalHorizontalVertical"); - BendConfiguration bendConfiguration = edgeDirection.bendConfiguration; - log.debug("Bend configuration: {}", bendConfiguration); - - DisplayPoint from = bendConfiguration.direction == BendDirection.BOTTOM ? edgeTerminalPoints.centerBottom(dimensionFrom): edgeTerminalPoints.centerTop(dimensionFrom); - DisplayPoint to = bendConfiguration.direction == BendDirection.BOTTOM ? edgeTerminalPoints.centerBottom(dimensionTo): edgeTerminalPoints.centerTop(dimensionTo); - int bendPointY = from.y + bendConfiguration.direction.numericFactor() * bendConfiguration.offset * CELL_HEIGHT; + WayPointDescriptor wayPointDescriptor = wayPointsPositioner.computeWaypointDescriptor(positionFrom, positionTo); + DisplayFlowNode flowNodeFrom = getFlowNode(positionFrom.getShape()); + DisplayFlowNode flowNodeTo = getFlowNode(positionTo.getShape()); - wayPoints.add(from); - wayPoints.add(new DisplayPoint(from.x, bendPointY)); - wayPoints.add(new DisplayPoint(to.x, bendPointY)); - wayPoints.add(to); - } - break; - case BottomLeftToTopRight: - if (orientation == HorizontalVertical) { - DisplayPoint from = edgeTerminalPoints.rightMiddle(dimensionFrom); - DisplayPoint to = edgeTerminalPoints.centerBottom(dimensionTo); - wayPoints.add(from); - wayPoints.add(new DisplayPoint(to.x, from.y)); - wayPoints.add(to); - } else if (orientation == VerticalHorizontal) { - DisplayPoint from = edgeTerminalPoints.centerTop(dimensionFrom); - DisplayPoint to = edgeTerminalPoints.leftMiddle(dimensionTo); - wayPoints.add(from); - wayPoints.add(new DisplayPoint(from.x, to.y)); - wayPoints.add(to); - } - break; - case BottomRightToTopLeft: - if (orientation == HorizontalVertical) { - DisplayPoint from = edgeTerminalPoints.leftMiddle(dimensionFrom); - DisplayPoint to = edgeTerminalPoints.centerBottom(dimensionTo); - wayPoints.add(from); - wayPoints.add(new DisplayPoint(to.x, from.y)); - wayPoints.add(to); - } else if (orientation == VerticalHorizontal) { - DisplayPoint from = edgeTerminalPoints.centerTop(dimensionFrom); - DisplayPoint to = edgeTerminalPoints.rightMiddle(dimensionTo); - wayPoints.add(from); - wayPoints.add(new DisplayPoint(from.x, to.y)); - wayPoints.add(to); - } - break; - case TopLeftToBottomRight: - if (orientation == HorizontalVertical) { - DisplayPoint from = edgeTerminalPoints.rightMiddle(dimensionFrom); - DisplayPoint to = edgeTerminalPoints.centerTop(dimensionTo); - wayPoints.add(from); - wayPoints.add(new DisplayPoint(to.x, from.y)); - wayPoints.add(to); - } else if (orientation == VerticalHorizontal) { - DisplayPoint from = edgeTerminalPoints.centerBottom(dimensionFrom); - DisplayPoint to = edgeTerminalPoints.leftMiddle(dimensionTo); - wayPoints.add(from); - wayPoints.add(new DisplayPoint(from.x, to.y)); - wayPoints.add(to); - } - break; - case TopRightToBottomLeft: - if (orientation == HorizontalVertical) { - DisplayPoint from = edgeTerminalPoints.leftMiddle(dimensionFrom); - DisplayPoint to = edgeTerminalPoints.centerTop(dimensionTo); - wayPoints.add(from); - wayPoints.add(new DisplayPoint(to.x, from.y)); - wayPoints.add(to); - } else if (orientation == VerticalHorizontal) { - DisplayPoint from = edgeTerminalPoints.centerBottom(dimensionFrom); - DisplayPoint to = edgeTerminalPoints.rightMiddle(dimensionTo); - wayPoints.add(from); - wayPoints.add(new DisplayPoint(from.x, to.y)); - wayPoints.add(to); - } - break; - case BottomToTop: - if (orientation == Vertical) { - wayPoints.add(edgeTerminalPoints.centerTop(dimensionFrom)); - wayPoints.add(edgeTerminalPoints.centerBottom(dimensionTo)); - } - break; - case TopToBottom: - if (orientation == Vertical) { - wayPoints.add(edgeTerminalPoints.centerBottom(dimensionFrom)); - wayPoints.add(edgeTerminalPoints.centerTop(dimensionTo)); - } - break; - default: - // do nothing - } - return wayPoints; + return wayPointsConverter.toDisplayPoints(wayPointDescriptor, flowNodeFrom.dimension, flowNodeTo.dimension); } - private static DisplayFlowNode getFlowNode(List flowNodes, String flowNodeId) { + private DisplayFlowNode getFlowNode(String flowNodeId) { return flowNodes.stream() .filter(f -> flowNodeId.equals(f.bpmnElementId)) .findFirst() .get(); // always exist, otherwise error occur on flow node generation } - // visible for testing - EdgeDirection computeEdgeDirection(Position positionFrom, Position positionTo) { - Direction direction; - Orientation orientation; - BendConfiguration bendConfiguration = null; - - if (positionFrom.getX() == positionTo.getX()) { - orientation = Orientation.Vertical; - if (positionFrom.getY() < positionTo.getY()) { - direction = TopToBottom; - } else { - direction = BottomToTop; - } - } else if (positionFrom.getY() == positionTo.getY()) { - orientation = Horizontal; - int positionFromX = positionFrom.getX(); - int positionToX = positionTo.getX(); - - if (positionFromX < positionToX) { - direction = LeftToRight; - if (positionFromX + 1 != positionToX) { - log.debug("Direction {}. Detected potential overlapping of horizontal edge on shapes. Shape: {}", - direction, positionFrom.getShape()); - BendConfiguration bendConfigurationBottom = gridSearcher.searchEmptyRow(positionFrom, positionTo, BendDirection.BOTTOM); - if (bendConfigurationBottom.offset != 0) { - log.debug("Not possible to keep horizontal orientation"); - orientation = VerticalHorizontalVertical; - bendConfiguration = bendConfigurationBottom; - if (bendConfigurationBottom.offset != 1) { - BendConfiguration bendConfigurationTop = gridSearcher.searchEmptyRow(positionFrom, positionTo, BendDirection.TOP); - if (bendConfigurationTop.offset < bendConfigurationBottom.offset) { - bendConfiguration = bendConfigurationTop; - } - } - } else { - log.debug("Keep the horizontal orientation"); - } - } - } else { - direction = RightToLeft; - if (positionFromX - 1 != positionToX) { - // TODO duplication with LeftToRight - log.debug("Direction {}. Detected potential overlapping of horizontal edge on shapes. Shape: {}", - direction, positionFrom.getShape()); - BendConfiguration bendConfigurationBottom = gridSearcher.searchEmptyRow(positionFrom, positionTo, BendDirection.BOTTOM); - if (bendConfigurationBottom.offset != 0) { - log.debug("Not possible to keep horizontal orientation"); - orientation = VerticalHorizontalVertical; - bendConfiguration = bendConfigurationBottom; - if (bendConfigurationBottom.offset != 1) { - BendConfiguration bendConfigurationTop = gridSearcher.searchEmptyRow(positionFrom, positionTo, BendDirection.TOP); - if (bendConfigurationTop.offset < bendConfigurationBottom.offset) { - bendConfiguration = bendConfigurationTop; - } - } - } - } - } - } else if (positionFrom.getX() < positionTo.getX()) { - if (positionFrom.getY() < positionTo.getY()) { - direction = TopLeftToBottomRight; - boolean shapeExistAtRightPositionFrom = gridSearcher.isShapeExistAtRight(positionFrom); - orientation = shapeExistAtRightPositionFrom - || (isGatewayAt(positionFrom) && isGatewaySplitAt(positionFrom) && (!isGatewayAt(positionTo) || isGatewaySplitAt(positionTo))) - ? Orientation.VerticalHorizontal - : Orientation.HorizontalVertical; - } else { - direction = BottomLeftToTopRight; - if (isGatewayAt(positionFrom)) { - orientation = !isGatewaySplitAt(positionFrom) - || isGatewayAt(positionTo) && !isGatewaySplitAt(positionTo) - ? Orientation.HorizontalVertical - : Orientation.VerticalHorizontal; - } else { - boolean shapeExistAbovePositionFrom = gridSearcher.isShapeExistAbove(positionFrom); - orientation = shapeExistAbovePositionFrom || isGatewayAt(positionTo) - ? Orientation.HorizontalVertical - : Orientation.VerticalHorizontal; - } - } - } else { - if (positionFrom.getY() < positionTo.getY()) { - direction = TopRightToBottomLeft; - boolean shapeExistAtLeftPositionFrom = gridSearcher.isShapeExistAtLeft(positionFrom); - orientation = shapeExistAtLeftPositionFrom || isGatewaySplitAt(positionFrom) - ? Orientation.VerticalHorizontal - : Orientation.HorizontalVertical; - } else { - direction = BottomRightToTopLeft; - boolean shapeExistAbovePositionFrom = gridSearcher.isShapeExistAbove(positionFrom); - orientation = shapeExistAbovePositionFrom || isGatewayAt(positionTo) - ? Orientation.HorizontalVertical - : Orientation.VerticalHorizontal; - } - } - - log.debug("Computed Edge orientation. Direction: {}, Orientation: {}, {}", direction, orientation, - bendConfiguration); - return EdgeDirection.builder().direction(direction).orientation(orientation) - .bendConfiguration(bendConfiguration) - .build(); - } - - private static boolean isGatewayAt(Position position) { - return ShapeType.GATEWAY.equals(position.getShapeType()); - } - - private static boolean isGatewaySplitAt(Position position) { - return isGatewayAt(position) && position.isSplitGateway(); - } - } diff --git a/java/src/main/java/io/process/analytics/tools/bpmn/generator/converter/waypoint/WayPointsConverter.java b/java/src/main/java/io/process/analytics/tools/bpmn/generator/converter/waypoint/WayPointsConverter.java new file mode 100644 index 00000000..1005f2f1 --- /dev/null +++ b/java/src/main/java/io/process/analytics/tools/bpmn/generator/converter/waypoint/WayPointsConverter.java @@ -0,0 +1,154 @@ +/* + * Copyright 2021 Bonitasoft S.A. + * + * 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 io.process.analytics.tools.bpmn.generator.converter.waypoint; + +import static io.process.analytics.tools.bpmn.generator.converter.Configuration.CELL_HEIGHT; +import static io.process.analytics.tools.bpmn.generator.converter.waypoint.Orientation.*; + +import java.util.ArrayList; +import java.util.List; + +import io.process.analytics.tools.bpmn.generator.model.display.DisplayDimension; +import io.process.analytics.tools.bpmn.generator.model.display.DisplayPoint; +import lombok.extern.log4j.Log4j2; + +@Log4j2 +public class WayPointsConverter { + + private final EdgeTerminalPoints edgeTerminalPoints = new EdgeTerminalPoints(); + + public List toDisplayPoints(WayPointDescriptor wayPointDescriptor, DisplayDimension dimensionFrom, + DisplayDimension dimensionTo) { + List wayPoints = new ArrayList<>(); + + Orientation orientation = wayPointDescriptor.orientation; + switch (wayPointDescriptor.direction) { + case LeftToRight: + if (orientation == Horizontal) { + wayPoints.add(edgeTerminalPoints.rightMiddle(dimensionFrom)); + wayPoints.add(edgeTerminalPoints.leftMiddle(dimensionTo)); + } + else if (orientation == VerticalHorizontalVertical) { + log.debug("Special case LeftToRight VerticalHorizontalVertical"); + wayPoints = computeWaypointsWithBendPoint(wayPointDescriptor.bendConfiguration, dimensionFrom, dimensionTo); + } + break; + case RightToLeft: + if (orientation == Horizontal) { + wayPoints.add(edgeTerminalPoints.leftMiddle(dimensionFrom)); + wayPoints.add(edgeTerminalPoints.rightMiddle(dimensionTo)); + } + else if (orientation == VerticalHorizontalVertical) { + log.debug("Special case RightToLeft VerticalHorizontalVertical"); + wayPoints = computeWaypointsWithBendPoint(wayPointDescriptor.bendConfiguration, dimensionFrom, dimensionTo); + } + break; + case BottomLeftToTopRight: + if (orientation == HorizontalVertical) { + DisplayPoint from = edgeTerminalPoints.rightMiddle(dimensionFrom); + DisplayPoint to = edgeTerminalPoints.centerBottom(dimensionTo); + wayPoints.add(from); + wayPoints.add(new DisplayPoint(to.x, from.y)); + wayPoints.add(to); + } else if (orientation == VerticalHorizontal) { + DisplayPoint from = edgeTerminalPoints.centerTop(dimensionFrom); + DisplayPoint to = edgeTerminalPoints.leftMiddle(dimensionTo); + wayPoints.add(from); + wayPoints.add(new DisplayPoint(from.x, to.y)); + wayPoints.add(to); + } + break; + case BottomRightToTopLeft: + if (orientation == HorizontalVertical) { + DisplayPoint from = edgeTerminalPoints.leftMiddle(dimensionFrom); + DisplayPoint to = edgeTerminalPoints.centerBottom(dimensionTo); + wayPoints.add(from); + wayPoints.add(new DisplayPoint(to.x, from.y)); + wayPoints.add(to); + } else if (orientation == VerticalHorizontal) { + DisplayPoint from = edgeTerminalPoints.centerTop(dimensionFrom); + DisplayPoint to = edgeTerminalPoints.rightMiddle(dimensionTo); + wayPoints.add(from); + wayPoints.add(new DisplayPoint(from.x, to.y)); + wayPoints.add(to); + } + break; + case TopLeftToBottomRight: + if (orientation == HorizontalVertical) { + DisplayPoint from = edgeTerminalPoints.rightMiddle(dimensionFrom); + DisplayPoint to = edgeTerminalPoints.centerTop(dimensionTo); + wayPoints.add(from); + wayPoints.add(new DisplayPoint(to.x, from.y)); + wayPoints.add(to); + } else if (orientation == VerticalHorizontal) { + DisplayPoint from = edgeTerminalPoints.centerBottom(dimensionFrom); + DisplayPoint to = edgeTerminalPoints.leftMiddle(dimensionTo); + wayPoints.add(from); + wayPoints.add(new DisplayPoint(from.x, to.y)); + wayPoints.add(to); + } + break; + case TopRightToBottomLeft: + if (orientation == HorizontalVertical) { + DisplayPoint from = edgeTerminalPoints.leftMiddle(dimensionFrom); + DisplayPoint to = edgeTerminalPoints.centerTop(dimensionTo); + wayPoints.add(from); + wayPoints.add(new DisplayPoint(to.x, from.y)); + wayPoints.add(to); + } else if (orientation == VerticalHorizontal) { + DisplayPoint from = edgeTerminalPoints.centerBottom(dimensionFrom); + DisplayPoint to = edgeTerminalPoints.rightMiddle(dimensionTo); + wayPoints.add(from); + wayPoints.add(new DisplayPoint(from.x, to.y)); + wayPoints.add(to); + } + break; + case BottomToTop: + if (orientation == Vertical) { + wayPoints.add(edgeTerminalPoints.centerTop(dimensionFrom)); + wayPoints.add(edgeTerminalPoints.centerBottom(dimensionTo)); + } + break; + case TopToBottom: + if (orientation == Vertical) { + wayPoints.add(edgeTerminalPoints.centerBottom(dimensionFrom)); + wayPoints.add(edgeTerminalPoints.centerTop(dimensionTo)); + } + break; + default: + // do nothing + } + return wayPoints; + } + + // Special case add bend points to avoid edge overlapping on shape + private List computeWaypointsWithBendPoint(BendConfiguration bendConfiguration, + DisplayDimension dimensionFrom, DisplayDimension dimensionTo) { + log.debug("Bend configuration: {}", bendConfiguration); + + DisplayPoint from = bendConfiguration.direction == BendDirection.BOTTOM ? edgeTerminalPoints.centerBottom(dimensionFrom): edgeTerminalPoints.centerTop(dimensionFrom); + DisplayPoint to = bendConfiguration.direction == BendDirection.BOTTOM ? edgeTerminalPoints.centerBottom(dimensionTo): edgeTerminalPoints.centerTop(dimensionTo); + int bendPointY = from.y + bendConfiguration.direction.numericFactor() * bendConfiguration.offset * CELL_HEIGHT; + + List wayPoints = new ArrayList<>(); + wayPoints.add(from); + wayPoints.add(new DisplayPoint(from.x, bendPointY)); + wayPoints.add(new DisplayPoint(to.x, bendPointY)); + wayPoints.add(to); + return wayPoints; + } + +} diff --git a/java/src/main/java/io/process/analytics/tools/bpmn/generator/converter/waypoint/WayPointsPositioner.java b/java/src/main/java/io/process/analytics/tools/bpmn/generator/converter/waypoint/WayPointsPositioner.java new file mode 100644 index 00000000..ba737ae8 --- /dev/null +++ b/java/src/main/java/io/process/analytics/tools/bpmn/generator/converter/waypoint/WayPointsPositioner.java @@ -0,0 +1,137 @@ +/* + * Copyright 2021 Bonitasoft S.A. + * 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 io.process.analytics.tools.bpmn.generator.converter.waypoint; + +import static io.process.analytics.tools.bpmn.generator.converter.waypoint.Direction.*; +import static io.process.analytics.tools.bpmn.generator.converter.waypoint.Orientation.*; + +import io.process.analytics.tools.bpmn.generator.converter.waypoint.WayPointDescriptor.WayPointDescriptorBuilder; +import io.process.analytics.tools.bpmn.generator.model.Position; +import io.process.analytics.tools.bpmn.generator.model.ShapeType; +import lombok.RequiredArgsConstructor; +import lombok.extern.log4j.Log4j2; + +@RequiredArgsConstructor +@Log4j2 +public class WayPointsPositioner { + + private final GridSearcher gridSearcher; + + public WayPointDescriptor computeWaypointDescriptor(Position positionFrom, Position positionTo) { + WayPointDescriptorBuilder builder = WayPointDescriptor.builder(); + + if (positionFrom.getX() == positionTo.getX()) { + builder.orientation(Vertical); + if (positionFrom.getY() < positionTo.getY()) { + builder.direction(TopToBottom); + } else { + builder.direction(BottomToTop); + } + } else if (positionFrom.getY() == positionTo.getY()) { + builder.orientation(Horizontal); + int positionFromX = positionFrom.getX(); + int positionToX = positionTo.getX(); + + if (positionFromX < positionToX) { + builder.direction(LeftToRight); + if (positionFromX + 1 != positionToX) { + updateWhenExtraBendPointsRequired(builder, positionFrom, positionTo); + } + } else { + builder.direction(RightToLeft); + if (positionFromX - 1 != positionToX) { + updateWhenExtraBendPointsRequired(builder, positionFrom, positionTo); + } + } + } else if (positionFrom.getX() < positionTo.getX()) { + if (positionFrom.getY() < positionTo.getY()) { + builder.direction(TopLeftToBottomRight); + boolean shapeExistAtRightPositionFrom = gridSearcher.isShapeExistAtRight(positionFrom); + Orientation orientation = shapeExistAtRightPositionFrom + || (isGatewayAt(positionFrom) && isGatewaySplitAt(positionFrom) && (!isGatewayAt(positionTo) || isGatewaySplitAt(positionTo))) + ? VerticalHorizontal + : HorizontalVertical; + builder.orientation(orientation); + } else { + builder.direction(BottomLeftToTopRight); + if (isGatewayAt(positionFrom)) { + Orientation orientation = !isGatewaySplitAt(positionFrom) + || isGatewayAt(positionTo) && !isGatewaySplitAt(positionTo) + ? HorizontalVertical + : VerticalHorizontal; + builder.orientation(orientation); + } else { + boolean shapeExistAbovePositionFrom = gridSearcher.isShapeExistAbove(positionFrom); + Orientation orientation = shapeExistAbovePositionFrom || isGatewayAt(positionTo) + ? HorizontalVertical + : VerticalHorizontal; + builder.orientation(orientation); + } + } + } else { + if (positionFrom.getY() < positionTo.getY()) { + builder.direction(TopRightToBottomLeft); + boolean shapeExistAtLeftPositionFrom = gridSearcher.isShapeExistAtLeft(positionFrom); + Orientation orientation = shapeExistAtLeftPositionFrom || isGatewaySplitAt(positionFrom) + ? VerticalHorizontal + : HorizontalVertical; + builder.orientation(orientation); + } else { + builder.direction(BottomRightToTopLeft); + boolean shapeExistAbovePositionFrom = gridSearcher.isShapeExistAbove(positionFrom); + Orientation orientation = shapeExistAbovePositionFrom || isGatewayAt(positionTo) + ? HorizontalVertical + : VerticalHorizontal; + builder.orientation(orientation); + } + } + + WayPointDescriptor wayPointDescriptor = builder.build(); + log.debug("Computed {}", wayPointDescriptor); + return wayPointDescriptor; + } + + private void updateWhenExtraBendPointsRequired(WayPointDescriptorBuilder builder, Position positionFrom, + Position positionTo) { + log.debug("Detected potential overlapping of horizontal edge on shapes. Shape: {}", positionFrom.getShape()); + + BendConfiguration bendConfigurationBottom = gridSearcher.computeConfigurationToPassByEmptyRow(positionFrom, positionTo, + BendDirection.BOTTOM); + if (bendConfigurationBottom.offset == 0) { + log.debug("Keep the horizontal orientation"); + return; + } + log.debug("Not possible to keep horizontal orientation"); + builder.orientation(VerticalHorizontalVertical); + builder.bendConfiguration(bendConfigurationBottom); + + if (bendConfigurationBottom.offset == 1) { + return; + } + + BendConfiguration bendConfigurationTop = gridSearcher.computeConfigurationToPassByEmptyRow(positionFrom, positionTo, + BendDirection.TOP); + if (bendConfigurationTop.offset < bendConfigurationBottom.offset) { + builder.bendConfiguration(bendConfigurationTop); + } + } + + private static boolean isGatewayAt(Position position) { + return ShapeType.GATEWAY.equals(position.getShapeType()); + } + + private static boolean isGatewaySplitAt(Position position) { + return isGatewayAt(position) && position.isSplitGateway(); + } + +} diff --git a/java/src/main/java/io/process/analytics/tools/bpmn/generator/export/BPMNExporter.java b/java/src/main/java/io/process/analytics/tools/bpmn/generator/export/BPMNExporter.java index 56e6f436..27bee473 100644 --- a/java/src/main/java/io/process/analytics/tools/bpmn/generator/export/BPMNExporter.java +++ b/java/src/main/java/io/process/analytics/tools/bpmn/generator/export/BPMNExporter.java @@ -16,7 +16,7 @@ package io.process.analytics.tools.bpmn.generator.export; import io.process.analytics.tools.bpmn.generator.converter.AlgoToDisplayModelConverter; -import io.process.analytics.tools.bpmn.generator.converter.AlgoToDisplayModelConverter.DisplayModel; +import io.process.analytics.tools.bpmn.generator.model.display.DisplayModel; import io.process.analytics.tools.bpmn.generator.internal.BPMNDiagramRichBuilder; import io.process.analytics.tools.bpmn.generator.internal.generated.model.TDefinitions; import io.process.analytics.tools.bpmn.generator.model.Diagram; diff --git a/java/src/main/java/io/process/analytics/tools/bpmn/generator/export/SVGExporter.java b/java/src/main/java/io/process/analytics/tools/bpmn/generator/export/SVGExporter.java index cf9c4f52..b66440be 100644 --- a/java/src/main/java/io/process/analytics/tools/bpmn/generator/export/SVGExporter.java +++ b/java/src/main/java/io/process/analytics/tools/bpmn/generator/export/SVGExporter.java @@ -17,15 +17,15 @@ import static io.process.analytics.tools.bpmn.generator.internal.StringUtils.defaultIfNull; +import java.util.stream.Collectors; + import io.process.analytics.tools.bpmn.generator.converter.AlgoToDisplayModelConverter; -import io.process.analytics.tools.bpmn.generator.converter.AlgoToDisplayModelConverter.*; import io.process.analytics.tools.bpmn.generator.model.Diagram; import io.process.analytics.tools.bpmn.generator.model.Grid; import io.process.analytics.tools.bpmn.generator.model.ShapeType; +import io.process.analytics.tools.bpmn.generator.model.display.*; import lombok.extern.log4j.Log4j2; -import java.util.stream.Collectors; - @Log4j2 public class SVGExporter { diff --git a/java/src/main/java/io/process/analytics/tools/bpmn/generator/internal/BPMNDiagramRichBuilder.java b/java/src/main/java/io/process/analytics/tools/bpmn/generator/internal/BPMNDiagramRichBuilder.java index 83b71103..d1de69e9 100644 --- a/java/src/main/java/io/process/analytics/tools/bpmn/generator/internal/BPMNDiagramRichBuilder.java +++ b/java/src/main/java/io/process/analytics/tools/bpmn/generator/internal/BPMNDiagramRichBuilder.java @@ -15,8 +15,6 @@ */ package io.process.analytics.tools.bpmn.generator.internal; -import static io.process.analytics.tools.bpmn.generator.internal.IdUtils.generateRandomId; - import java.util.ArrayList; import java.util.List; import java.util.Optional; @@ -25,10 +23,10 @@ import javax.xml.bind.JAXBElement; import javax.xml.namespace.QName; -import io.process.analytics.tools.bpmn.generator.converter.AlgoToDisplayModelConverter.DisplayDimension; -import io.process.analytics.tools.bpmn.generator.converter.AlgoToDisplayModelConverter.DisplayEdge; -import io.process.analytics.tools.bpmn.generator.converter.AlgoToDisplayModelConverter.DisplayFlowNode; -import io.process.analytics.tools.bpmn.generator.converter.AlgoToDisplayModelConverter.DisplayPoint; +import io.process.analytics.tools.bpmn.generator.model.display.DisplayDimension; +import io.process.analytics.tools.bpmn.generator.model.display.DisplayEdge; +import io.process.analytics.tools.bpmn.generator.model.display.DisplayFlowNode; +import io.process.analytics.tools.bpmn.generator.model.display.DisplayPoint; import io.process.analytics.tools.bpmn.generator.internal.generated.model.*; import io.process.analytics.tools.bpmn.generator.model.ShapeType; import lombok.NonNull; @@ -134,7 +132,7 @@ public TDefinitions build() { diagrams.clear(); BPMNDiagram bpmnDiagram = initializeBPMNDiagram(); diagrams.add(bpmnDiagram); - + BPMNPlane bpmnPlane = bpmnDiagram.getBPMNPlane(); List> diagramElements = bpmnPlane.getDiagramElement(); diff --git a/java/src/main/java/io/process/analytics/tools/bpmn/generator/model/display/DisplayDimension.java b/java/src/main/java/io/process/analytics/tools/bpmn/generator/model/display/DisplayDimension.java new file mode 100644 index 00000000..e207ba0e --- /dev/null +++ b/java/src/main/java/io/process/analytics/tools/bpmn/generator/model/display/DisplayDimension.java @@ -0,0 +1,24 @@ +/* + * Copyright 2021 Bonitasoft S.A. + * 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 io.process.analytics.tools.bpmn.generator.model.display; + +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public class DisplayDimension { + + public final int x; + public final int y; + public final int width; + public final int height; +} diff --git a/java/src/main/java/io/process/analytics/tools/bpmn/generator/model/display/DisplayEdge.java b/java/src/main/java/io/process/analytics/tools/bpmn/generator/model/display/DisplayEdge.java new file mode 100644 index 00000000..7240a3b4 --- /dev/null +++ b/java/src/main/java/io/process/analytics/tools/bpmn/generator/model/display/DisplayEdge.java @@ -0,0 +1,28 @@ +/* + * Copyright 2021 Bonitasoft S.A. + * 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 io.process.analytics.tools.bpmn.generator.model.display; + +import io.process.analytics.tools.bpmn.generator.model.display.DisplayPoint; +import lombok.Builder; +import lombok.RequiredArgsConstructor; + +import java.util.List; + +@RequiredArgsConstructor +@Builder +public class DisplayEdge { + + public final String bpmnElementId; + public final List wayPoints; + +} diff --git a/java/src/main/java/io/process/analytics/tools/bpmn/generator/model/display/DisplayFlowNode.java b/java/src/main/java/io/process/analytics/tools/bpmn/generator/model/display/DisplayFlowNode.java new file mode 100644 index 00000000..d103af29 --- /dev/null +++ b/java/src/main/java/io/process/analytics/tools/bpmn/generator/model/display/DisplayFlowNode.java @@ -0,0 +1,31 @@ +/* + * Copyright 2021 Bonitasoft S.A. + * 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 io.process.analytics.tools.bpmn.generator.model.display; + +import io.process.analytics.tools.bpmn.generator.model.ShapeType; +import lombok.Builder; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@Builder +public class DisplayFlowNode { + + public final String bpmnElementId; + public final DisplayDimension dimension; + public final DisplayLabel label; + // for non BPMN exporters only + public final ShapeType type; + public final int rx; + public final int strokeWidth; + +} diff --git a/java/src/main/java/io/process/analytics/tools/bpmn/generator/model/display/DisplayLabel.java b/java/src/main/java/io/process/analytics/tools/bpmn/generator/model/display/DisplayLabel.java new file mode 100644 index 00000000..268298d4 --- /dev/null +++ b/java/src/main/java/io/process/analytics/tools/bpmn/generator/model/display/DisplayLabel.java @@ -0,0 +1,23 @@ +/* + * Copyright 2021 Bonitasoft S.A. + * 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 io.process.analytics.tools.bpmn.generator.model.display; + +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public class DisplayLabel { + + public final String text; // for non BPMN exporters only + public final int fontSize; + public final DisplayDimension dimension; +} diff --git a/java/src/main/java/io/process/analytics/tools/bpmn/generator/model/display/DisplayModel.java b/java/src/main/java/io/process/analytics/tools/bpmn/generator/model/display/DisplayModel.java new file mode 100644 index 00000000..ee0a3093 --- /dev/null +++ b/java/src/main/java/io/process/analytics/tools/bpmn/generator/model/display/DisplayModel.java @@ -0,0 +1,32 @@ +/* + * Copyright 2021 Bonitasoft S.A. + * 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 io.process.analytics.tools.bpmn.generator.model.display; + +import lombok.Builder; +import lombok.RequiredArgsConstructor; +import lombok.Singular; + +import java.util.List; + +@RequiredArgsConstructor +@Builder +public class DisplayModel { + public final int width; + public final int height; + + @Singular + public final List flowNodes; + @Singular + public final List edges; + +} diff --git a/java/src/main/java/io/process/analytics/tools/bpmn/generator/model/display/DisplayPoint.java b/java/src/main/java/io/process/analytics/tools/bpmn/generator/model/display/DisplayPoint.java new file mode 100644 index 00000000..9494885d --- /dev/null +++ b/java/src/main/java/io/process/analytics/tools/bpmn/generator/model/display/DisplayPoint.java @@ -0,0 +1,24 @@ +/* + * Copyright 2021 Bonitasoft S.A. + * 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 io.process.analytics.tools.bpmn.generator.model.display; + +import lombok.RequiredArgsConstructor; +import lombok.ToString; + +@RequiredArgsConstructor +@ToString +public class DisplayPoint { + + public final int x; + public final int y; +} diff --git a/java/src/test/java/io/process/analytics/tools/bpmn/generator/converter/waypoint/WayPointsComputerTest.java b/java/src/test/java/io/process/analytics/tools/bpmn/generator/converter/waypoint/WayPointsComputerTest.java deleted file mode 100644 index 5f2e994a..00000000 --- a/java/src/test/java/io/process/analytics/tools/bpmn/generator/converter/waypoint/WayPointsComputerTest.java +++ /dev/null @@ -1,556 +0,0 @@ -/* - * Copyright 2020 Bonitasoft S.A. - * 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 io.process.analytics.tools.bpmn.generator.converter.waypoint; - -import static io.process.analytics.tools.bpmn.generator.converter.waypoint.Direction.*; -import static io.process.analytics.tools.bpmn.generator.converter.waypoint.Orientation.*; -import static org.assertj.core.api.Assertions.assertThat; - -import org.junit.jupiter.api.Test; - -import io.process.analytics.tools.bpmn.generator.model.Grid; -import io.process.analytics.tools.bpmn.generator.model.Position; -import io.process.analytics.tools.bpmn.generator.model.Shape; -import io.process.analytics.tools.bpmn.generator.model.ShapeType; - -class WayPointsComputerTest { - - // ================================================================================================================= - // from and to in the same row - left to right - // ================================================================================================================= - - @Test - public void computeEdgeDirection_same_row_from_on_left() { - EdgeDirection edgeDirection = computeEdgeDirection(positionSameRow(10), positionSameRow(100)); - assertThat(edgeDirection.direction).isEqualTo(LeftToRight); - assertThat(edgeDirection.orientation).isEqualTo(Horizontal); - } - - @Test - public void computeEdgeDirection_same_row_left_to_right_with_elements_between_none_on_bottom() { - // +--------------------+ - // | from elt to | - // | | - // +--------------------+ - EdgeDirection edgeDirection = computeEdgeDirection(position(1,1), position(4,1), Grid.of(position(3, 1))); - assertThat(edgeDirection.direction).isEqualTo(LeftToRight); - assertThat(edgeDirection.orientation).isEqualTo(VerticalHorizontalVertical); - assertBendConfigurationOnBottom(edgeDirection.bendConfiguration, 1); - } - - @Test - public void computeEdgeDirection_same_row_left_to_right_with_elements_between_no_elements_on_top() { - // +--------------------+ - // | | - // | from elt to | - // | elt | - // +--------------------+ - EdgeDirection edgeDirection = computeEdgeDirection(position(1,2), position(4,2), Grid.of(position(3, 2), position(3, 3))); - assertThat(edgeDirection.direction).isEqualTo(LeftToRight); - assertThat(edgeDirection.orientation).isEqualTo(VerticalHorizontalVertical); - assertBendConfigurationOnTop(edgeDirection.bendConfiguration, 1); - } - - @Test - public void computeEdgeDirection_same_row_left_to_right_with_elements_between_more_occupied_rows_on_top() { - // +--------------------+ - // | elt | - // | elt | - // | from elt to | - // | elt | - // +--------------------+ - EdgeDirection edgeDirection = computeEdgeDirection(position(1,3), position(4,3), - Grid.of(position(3, 1), position(3, 2), position(3, 3), position(3, 4))); - assertThat(edgeDirection.direction).isEqualTo(LeftToRight); - assertThat(edgeDirection.orientation).isEqualTo(VerticalHorizontalVertical); - assertBendConfigurationOnBottom(edgeDirection.bendConfiguration, 2); - } - - @Test - public void computeEdgeDirection_same_row_left_to_right_with_elements_between_more_occupied_rows_on_bottom() { - // +--------------------+ - // | elt | - // | from elt to | - // | elt | - // | elt | - // +--------------------+ - EdgeDirection edgeDirection = computeEdgeDirection(position(1,2), position(4,2), - Grid.of(position(3, 1), position(3, 2), position(3, 3), position(3, 4))); - assertThat(edgeDirection.direction).isEqualTo(LeftToRight); - assertThat(edgeDirection.orientation).isEqualTo(VerticalHorizontalVertical); - assertBendConfigurationOnTop(edgeDirection.bendConfiguration, 2); - } - - @Test - public void computeEdgeDirection_same_row_left_to_right_with_elements_between_as_much_on_bottom_as_on_top() { - // +--------------------+ - // | elt | - // | elt | - // | from elt to | - // | elt | - // | elt | - // +--------------------+ - EdgeDirection edgeDirection = computeEdgeDirection(position(1,3), position(4,3), - Grid.of(position(3, 1), position(2, 2), position(3, 3), position(3, 4), position(2, 5))); - assertThat(edgeDirection.direction).isEqualTo(LeftToRight); - assertThat(edgeDirection.orientation).isEqualTo(VerticalHorizontalVertical); - assertBendConfigurationOnBottom(edgeDirection.bendConfiguration, 3); - } - - // ================================================================================================================= - // from and to in the same row - right to left - // ================================================================================================================= - - @Test - public void computeEdgeDirection_same_row_from_on_right() { - EdgeDirection edgeDirection = computeEdgeDirection(positionSameRow(100), positionSameRow(20)); - assertThat(edgeDirection.direction).isEqualTo(RightToLeft); - assertThat(edgeDirection.orientation).isEqualTo(Horizontal); - } - - @Test - public void computeEdgeDirection_same_row_right_to_left_with_elements_between_none_on_bottom() { - // +--------------------+ - // | to elt from | - // | | - // +--------------------+ - EdgeDirection edgeDirection = computeEdgeDirection(position(4,1), position(1,1), Grid.of(position(3, 1))); - assertThat(edgeDirection.direction).isEqualTo(RightToLeft); - assertThat(edgeDirection.orientation).isEqualTo(VerticalHorizontalVertical); - assertBendConfigurationOnBottom(edgeDirection.bendConfiguration, 1); - } - - @Test - public void computeEdgeDirection_same_row_right_to_left_with_elements_between_no_elements_on_top() { - // +--------------------+ - // | | - // | to elt from | - // | elt | - // +--------------------+ - EdgeDirection edgeDirection = computeEdgeDirection(position(4,2), position(1,2), Grid.of(position(3, 2), position(3, 3))); - assertThat(edgeDirection.direction).isEqualTo(RightToLeft); - assertThat(edgeDirection.orientation).isEqualTo(VerticalHorizontalVertical); - assertBendConfigurationOnTop(edgeDirection.bendConfiguration, 1); - } - - @Test - public void computeEdgeDirection_same_row_right_to_left_with_elements_between_more_occupied_rows_on_top() { - // +--------------------+ - // | elt | - // | elt | - // | to elt from | - // | elt | - // +--------------------+ - EdgeDirection edgeDirection = computeEdgeDirection(position(4,3), position(1,3), - Grid.of(position(3, 1), position(3, 2), position(3, 3), position(3, 4))); - assertThat(edgeDirection.direction).isEqualTo(RightToLeft); - assertThat(edgeDirection.orientation).isEqualTo(VerticalHorizontalVertical); - assertBendConfigurationOnBottom(edgeDirection.bendConfiguration, 2); - } - - @Test - public void computeEdgeDirection_same_row_right_to_left_with_elements_between_more_occupied_rows_on_bottom() { - // +--------------------+ - // | elt | - // | to elt from | - // | elt | - // | elt | - // +--------------------+ - EdgeDirection edgeDirection = computeEdgeDirection(position(4,2), position(1,2), - Grid.of(position(3, 1), position(3, 2), position(3, 3), position(3, 4))); - assertThat(edgeDirection.direction).isEqualTo(RightToLeft); - assertThat(edgeDirection.orientation).isEqualTo(VerticalHorizontalVertical); - assertBendConfigurationOnTop(edgeDirection.bendConfiguration, 2); - } - - @Test - public void computeEdgeDirection_same_row_right_to_left_with_elements_between_as_much_on_bottom_as_on_top() { - // +--------------------+ - // | elt | - // | elt | - // | to elt from | - // | elt | - // | elt | - // +--------------------+ - EdgeDirection edgeDirection = computeEdgeDirection(position(4,3), position(1,3), - Grid.of(position(3, 1), position(2, 2), position(3, 3), position(3, 4), position(2, 5))); - assertThat(edgeDirection.direction).isEqualTo(RightToLeft); - assertThat(edgeDirection.orientation).isEqualTo(VerticalHorizontalVertical); - assertBendConfigurationOnBottom(edgeDirection.bendConfiguration, 3); - } - - // ================================================================================================================= - // from and to in the same column - // ================================================================================================================= - - @Test - public void computeEdgeDirection_same_column_from_on_top() { - EdgeDirection edgeDirection = computeEdgeDirection(positionSameColumn(10), positionSameColumn(100)); - assertThat(edgeDirection.direction).isEqualTo(TopToBottom); - assertThat(edgeDirection.orientation).isEqualTo(Vertical); - } - - @Test - public void computeEdgeDirection_same_column_from_on_bottom() { - EdgeDirection edgeDirection = computeEdgeDirection(positionSameColumn(100), positionSameColumn(20)); - assertThat(edgeDirection.direction).isEqualTo(BottomToTop); - assertThat(edgeDirection.orientation).isEqualTo(Vertical); - } - - // ================================================================================================================= - // Add waypoints when no elements between from and to - // ================================================================================================================= - - @Test - public void computeEdgeDirection_no_elements_between_from_on_top_left_to_on_bottom_right() { - // +-----------------+ - // | from | - // | to | - // +-----------------+ - EdgeDirection edgeDirection = computeEdgeDirection(position(10, 10), position(50, 50)); - assertThat(edgeDirection.direction).isEqualTo(TopLeftToBottomRight); - assertThat(edgeDirection.orientation).isEqualTo(HorizontalVertical); - } - - @Test - public void computeEdgeDirection_no_elements_between_from_on_top_right_to_on_bottom_right() { - // +-----------------+ - // | from | - // | to | - // +-----------------+ - EdgeDirection edgeDirection = computeEdgeDirection(position(50, 10), position(10, 50)); - assertThat(edgeDirection.direction).isEqualTo(TopRightToBottomLeft); - assertThat(edgeDirection.orientation).isEqualTo(HorizontalVertical); - } - - @Test - public void computeEdgeDirection_no_elements_between_from_on_bottom_left_to_on_top_right() { - // +-----------------+ - // | to | - // | from | - // +-----------------+ - EdgeDirection edgeDirection = computeEdgeDirection(position(10, 100), position(50, 50)); - assertThat(edgeDirection.direction).isEqualTo(BottomLeftToTopRight); - assertThat(edgeDirection.orientation).isEqualTo(VerticalHorizontal); - } - - @Test - public void computeEdgeDirection_no_elements_between_from_on_bottom_right_to_on_top_left() { - // +-----------------+ - // | to | - // | from | - // +-----------------+ - EdgeDirection edgeDirection = computeEdgeDirection(position(50, 50), position(10, 10)); - assertThat(edgeDirection.direction).isEqualTo(BottomRightToTopLeft); - assertThat(edgeDirection.orientation).isEqualTo(VerticalHorizontal); - } - - // ================================================================================================================= - // Add waypoints when from is a gateway - // ================================================================================================================= - - @Test - public void computeEdgeDirection_from_join_gateway_on_bottom_left_to_on_top_right() { - // +---------------------+ - // | to | - // | from-gw-join | - // +---------------------+ - EdgeDirection edgeDirection = computeEdgeDirection(positionGatewayJoin(10, 100), position(50, 50)); - assertThat(edgeDirection.direction).isEqualTo(BottomLeftToTopRight); - assertThat(edgeDirection.orientation).isEqualTo(HorizontalVertical); - } - - @Test - public void computeEdgeDirection_from_join_gateway_on_top_left_to_on_bottom_right() { - // +---------------------+ - // | from-gw-join | - // | to | - // +---------------------+ - EdgeDirection edgeDirection = computeEdgeDirection(positionGatewayJoin(1, 1), position(5, 5)); - assertThat(edgeDirection.direction).isEqualTo(TopLeftToBottomRight); - assertThat(edgeDirection.orientation).isEqualTo(HorizontalVertical); - } - - @Test - public void computeEdgeDirection_from_split_gateway_on_bottom_left_to_on_top_right() { - // +---------------------+ - // | to | - // | from-gw-split | - // +---------------------+ - EdgeDirection edgeDirection = computeEdgeDirection(positionGatewaySplit(10, 100), position(50, 50)); - assertThat(edgeDirection.direction).isEqualTo(BottomLeftToTopRight); - assertThat(edgeDirection.orientation).isEqualTo(VerticalHorizontal); - } - - @Test - public void computeEdgeDirection_from_gateway_split_on_bottom_left_to_gateway_join_on_top_right() { - // +-----------------------------+ - // | to-gw-join | - // | from-gw-split | - // +-----------------------------+ - EdgeDirection edgeDirection = computeEdgeDirection(positionGatewaySplit(10, 100), positionGatewayJoin(50, 50)); - assertThat(edgeDirection.direction).isEqualTo(BottomLeftToTopRight); - assertThat(edgeDirection.orientation).isEqualTo(HorizontalVertical); - } - - @Test - public void computeEdgeDirection_from_gateway_split_on_bottom_left_to_gateway_split_on_top_right() { - // +-----------------------------+ - // | to-gw-split | - // | from-gw-split | - // +-----------------------------+ - EdgeDirection edgeDirection = computeEdgeDirection(positionGatewaySplit(10, 100), positionGatewaySplit(50, 50)); - assertThat(edgeDirection.direction).isEqualTo(BottomLeftToTopRight); - assertThat(edgeDirection.orientation).isEqualTo(VerticalHorizontal); - } - - @Test - public void computeEdgeDirection_from_gateway_split_on_top_left_to_on_bottom_right() { - // +-----------------------+ - // | from-gw-split | - // | to | - // +-----------------------+ - EdgeDirection edgeDirection = computeEdgeDirection(positionGatewaySplit(10, 10), position(50, 50)); - assertThat(edgeDirection.direction).isEqualTo(TopLeftToBottomRight); - assertThat(edgeDirection.orientation).isEqualTo(VerticalHorizontal); - } - - @Test - public void computeEdgeDirection_from_gateway_split_on_top_left_to_gateway_join_on_bottom_right() { - // +------------------------------+ - // | from-gw-split | - // | to-gw-join | - // +------------------------------+ - EdgeDirection edgeDirection = computeEdgeDirection(positionGatewaySplit(10, 10), positionGatewayJoin(50, 50)); - assertThat(edgeDirection.direction).isEqualTo(TopLeftToBottomRight); - assertThat(edgeDirection.orientation).isEqualTo(HorizontalVertical); - } - - @Test - public void computeEdgeDirection_from_gateway_split_on_top_left_to_gateway_split_on_bottom_right() { - // +-----------------------------+ - // | from-gw-split | - // | to-gw-split | - // +-----------------------------+ - EdgeDirection edgeDirection = computeEdgeDirection(positionGatewaySplit(10, 10), positionGatewaySplit(50, 50)); - assertThat(edgeDirection.direction).isEqualTo(TopLeftToBottomRight); - assertThat(edgeDirection.orientation).isEqualTo(VerticalHorizontal); - } - - @Test - public void computeEdgeDirection_from_gateway_split_on_top_left_to_gateway_join_on_bottom_right_with_element_on_top_left() { - // +------------------------------+ - // | from-gw-split elt | - // | to-gw-join | - // +------------------------------+ - EdgeDirection edgeDirection = computeEdgeDirection(positionGatewaySplit(1, 1), positionGatewayJoin(2, 2), - Grid.of(position(2, 1))); - assertThat(edgeDirection.direction).isEqualTo(TopLeftToBottomRight); - assertThat(edgeDirection.orientation).isEqualTo(VerticalHorizontal); - } - - // ================================================================================================================= - // Add waypoints when 'to' is a gateway and not already covered by other tests - // ================================================================================================================= - - @Test - public void computeEdgeDirection_from_on_top_left_to_gateway_join_on_bottom_right() { - // +--------------------+ - // | from | - // | to-gw-join | - // +--------------------+ - EdgeDirection edgeDirection = computeEdgeDirection(position(10, 10), positionGatewayJoin(50, 50)); - assertThat(edgeDirection.direction).isEqualTo(TopLeftToBottomRight); - assertThat(edgeDirection.orientation).isEqualTo(HorizontalVertical); - } - - @Test - public void computeEdgeDirection_from_on_bottom_left_to_gateway_join_on_top_right() { - // +-----------------------+ - // | to-gw-join | - // | from | - // +-----------------------+ - EdgeDirection edgeDirection = computeEdgeDirection(position(10, 100), positionGatewayJoin(50, 50)); - assertThat(edgeDirection.direction).isEqualTo(BottomLeftToTopRight); - assertThat(edgeDirection.orientation).isEqualTo(HorizontalVertical); - } - - @Test - public void computeEdgeDirection_from_on_top_right_to_gateway_join_on_bottom_left() { - // +-----------------------+ - // | from | - // | to-gw-join | - // +-----------------------+ - EdgeDirection edgeDirection = computeEdgeDirection(position(50, 50), positionGatewayJoin(10, 100)); - assertThat(edgeDirection.direction).isEqualTo(TopRightToBottomLeft); - assertThat(edgeDirection.orientation).isEqualTo(HorizontalVertical); - } - - @Test - public void computeEdgeDirection_from_gateway_split_on_top_right_to_bottom_left() { - // +-----------------------+ - // | from-gw-split | - // | elt | - // +-----------------------+ - EdgeDirection edgeDirection = computeEdgeDirection(positionGatewaySplit(2, 1), position(1, 2), - Grid.of(position(2, 2))); - assertThat(edgeDirection.direction).isEqualTo(TopRightToBottomLeft); - assertThat(edgeDirection.orientation).isEqualTo(VerticalHorizontal); - } - - @Test - public void computeEdgeDirection_from_on_bottom_right_to_gateway_on_top_left() { - // +--------------------+ - // | to-gw-join | - // | from | - // +--------------------+ - EdgeDirection edgeDirection = computeEdgeDirection(position(50, 50), positionGatewayJoin(10, 10)); - assertThat(edgeDirection.direction).isEqualTo(BottomRightToTopLeft); - assertThat(edgeDirection.orientation).isEqualTo(HorizontalVertical); - } - - // ================================================================================================================= - // Add waypoints when there are elements between from and to - // ================================================================================================================= - - @Test - public void computeEdgeDirection_has_elements_between_from_and_top_with_from_on_top_left() { - // +-----------------+ - // | from | - // | element to | - // +-----------------+ - EdgeDirection edgeDirection = computeEdgeDirection(position(1, 1), position(2, 2), Grid.of(position(1, 2))); - assertThat(edgeDirection.direction).isEqualTo(TopLeftToBottomRight); - assertThat(edgeDirection.orientation).isEqualTo(HorizontalVertical); - } - - @Test - public void computeEdgeDirection_has_elements_between_from_and_top_with_from_on_top_left_case_2() { - // +-----------------+ - // | from element | - // | to | - // +-----------------+ - EdgeDirection edgeDirection = computeEdgeDirection(position(1, 1), position(2, 2), Grid.of(position(2, 1))); - assertThat(edgeDirection.direction).isEqualTo(TopLeftToBottomRight); - assertThat(edgeDirection.orientation).isEqualTo(VerticalHorizontal); - } - - @Test - public void computeEdgeDirection_has_elements_between_from_and_top_with_from_on_bottom_left() { - // +-----------------+ - // | element to | - // | from | - // +-----------------+ - EdgeDirection edgeDirection = computeEdgeDirection(position(1, 2), position(2, 1), Grid.of(position(1, 1))); - assertThat(edgeDirection.direction).isEqualTo(BottomLeftToTopRight); - assertThat(edgeDirection.orientation).isEqualTo(HorizontalVertical); - } - - @Test - public void computeEdgeDirection_has_elements_between_from_and_top_with_from_on_bottom_left_case2() { - // +-----------------+ - // | to | - // | from element | - // +-----------------+ - EdgeDirection edgeDirection = computeEdgeDirection(position(1, 2), position(2, 1), Grid.of(position(2, 2))); - assertThat(edgeDirection.direction).isEqualTo(BottomLeftToTopRight); - assertThat(edgeDirection.orientation).isEqualTo(VerticalHorizontal); - } - - @Test - public void computeEdgeDirection_has_elements_between_from_and_top_with_from_on_top_right() { - // +-----------------+ - // | element from | - // | to | - // +-----------------+ - EdgeDirection edgeDirection = computeEdgeDirection(position(2, 1), position(1, 2), Grid.of(position(1, 1))); - assertThat(edgeDirection.direction).isEqualTo(TopRightToBottomLeft); - assertThat(edgeDirection.orientation).isEqualTo(VerticalHorizontal); - } - - @Test - public void computeEdgeDirection_has_elements_between_from_and_top_with_from_on_top_right_case2() { - // +-----------------+ - // | from | - // | to element | - // +-----------------+ - EdgeDirection edgeDirection = computeEdgeDirection(position(2, 1), position(1, 2), Grid.of(position(2, 2))); - assertThat(edgeDirection.direction).isEqualTo(TopRightToBottomLeft); - assertThat(edgeDirection.orientation).isEqualTo(HorizontalVertical); - } - - @Test - public void computeEdgeDirection_has_elements_between_from_and_top_with_from_on_bottom_right() { - // +-----------------+ - // | to | - // | element from | - // +-----------------+ - EdgeDirection edgeDirection = computeEdgeDirection(position(2, 2), position(1, 1), Grid.of(position(1, 2))); - assertThat(edgeDirection.direction).isEqualTo(BottomRightToTopLeft); - assertThat(edgeDirection.orientation).isEqualTo(VerticalHorizontal); - } - - @Test - public void computeEdgeDirection_has_elements_between_from_and_top_with_from_on_bottom_right_case2() { - // +-----------------+ - // | to element | - // | from | - // +-----------------+ - EdgeDirection edgeDirection = computeEdgeDirection(position(2, 2), position(1, 1), Grid.of(position(2, 1))); - assertThat(edgeDirection.direction).isEqualTo(BottomRightToTopLeft); - assertThat(edgeDirection.orientation).isEqualTo(HorizontalVertical); - } - - // ================================================================================================================= - // UTILS - // ================================================================================================================= - - private static EdgeDirection computeEdgeDirection(Position positionFrom, Position positionTo) { - return computeEdgeDirection(positionFrom, positionTo, new Grid()); - } - - private static EdgeDirection computeEdgeDirection(Position positionFrom, Position positionTo, Grid grid) { - return new WayPointsComputer(grid, null).computeEdgeDirection(positionFrom, positionTo); - } - - private static Position positionSameRow(int x) { - return position(x,12); // arbitrary row - } - - private static Position positionSameColumn(int y) { - return position(50,y); // arbitrary column - } - - private static Position position(int x, int y) { - return Position.builder().x(x).y(y).build(); - } - - private static Position positionGatewaySplit(int x, int y) { - return Position.position(new Shape(null, null, ShapeType.GATEWAY, true), x, y); - } - - private static Position positionGatewayJoin(int x, int y) { - return Position.position(new Shape(null, null, ShapeType.GATEWAY, false), x, y); - } - - private static void assertBendConfigurationOnBottom(BendConfiguration bendConfiguration, int offset) { - assertThat(bendConfiguration.direction).isEqualTo(BendDirection.BOTTOM); - assertThat(bendConfiguration.offset).isEqualTo(offset); - } - - private static void assertBendConfigurationOnTop(BendConfiguration bendConfiguration, int offset) { - assertThat(bendConfiguration.direction).isEqualTo(BendDirection.TOP); - assertThat(bendConfiguration.offset).isEqualTo(offset); - } - -} diff --git a/java/src/test/java/io/process/analytics/tools/bpmn/generator/converter/waypoint/WayPointsPositionerTest.java b/java/src/test/java/io/process/analytics/tools/bpmn/generator/converter/waypoint/WayPointsPositionerTest.java new file mode 100644 index 00000000..af08cece --- /dev/null +++ b/java/src/test/java/io/process/analytics/tools/bpmn/generator/converter/waypoint/WayPointsPositionerTest.java @@ -0,0 +1,556 @@ +/* + * Copyright 2020 Bonitasoft S.A. + * 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 io.process.analytics.tools.bpmn.generator.converter.waypoint; + +import static io.process.analytics.tools.bpmn.generator.converter.waypoint.Direction.*; +import static io.process.analytics.tools.bpmn.generator.converter.waypoint.Orientation.*; +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; + +import io.process.analytics.tools.bpmn.generator.model.Grid; +import io.process.analytics.tools.bpmn.generator.model.Position; +import io.process.analytics.tools.bpmn.generator.model.Shape; +import io.process.analytics.tools.bpmn.generator.model.ShapeType; + +class WayPointsPositionerTest { + + // ================================================================================================================= + // from and to in the same row - left to right + // ================================================================================================================= + + @Test + public void computeWaypointDescriptor_same_row_from_on_left() { + WayPointDescriptor wayPointDescriptor = computeWaypointDescriptor(positionSameRow(10), positionSameRow(100)); + assertThat(wayPointDescriptor.direction).isEqualTo(LeftToRight); + assertThat(wayPointDescriptor.orientation).isEqualTo(Horizontal); + } + + @Test + public void computeWaypointDescriptor_same_row_left_to_right_with_elements_between_none_on_bottom() { + // +--------------------+ + // | from elt to | + // | | + // +--------------------+ + WayPointDescriptor wayPointDescriptor = computeWaypointDescriptor(position(1,1), position(4,1), Grid.of(position(3, 1))); + assertThat(wayPointDescriptor.direction).isEqualTo(LeftToRight); + assertThat(wayPointDescriptor.orientation).isEqualTo(VerticalHorizontalVertical); + assertBendConfigurationOnBottom(wayPointDescriptor.bendConfiguration, 1); + } + + @Test + public void computeWaypointDescriptor_same_row_left_to_right_with_elements_between_no_elements_on_top() { + // +--------------------+ + // | | + // | from elt to | + // | elt | + // +--------------------+ + WayPointDescriptor wayPointDescriptor = computeWaypointDescriptor(position(1,2), position(4,2), Grid.of(position(3, 2), position(3, 3))); + assertThat(wayPointDescriptor.direction).isEqualTo(LeftToRight); + assertThat(wayPointDescriptor.orientation).isEqualTo(VerticalHorizontalVertical); + assertBendConfigurationOnTop(wayPointDescriptor.bendConfiguration, 1); + } + + @Test + public void computeWaypointDescriptor_same_row_left_to_right_with_elements_between_more_occupied_rows_on_top() { + // +--------------------+ + // | elt | + // | elt | + // | from elt to | + // | elt | + // +--------------------+ + WayPointDescriptor wayPointDescriptor = computeWaypointDescriptor(position(1,3), position(4,3), + Grid.of(position(3, 1), position(3, 2), position(3, 3), position(3, 4))); + assertThat(wayPointDescriptor.direction).isEqualTo(LeftToRight); + assertThat(wayPointDescriptor.orientation).isEqualTo(VerticalHorizontalVertical); + assertBendConfigurationOnBottom(wayPointDescriptor.bendConfiguration, 2); + } + + @Test + public void computeWaypointDescriptor_same_row_left_to_right_with_elements_between_more_occupied_rows_on_bottom() { + // +--------------------+ + // | elt | + // | from elt to | + // | elt | + // | elt | + // +--------------------+ + WayPointDescriptor wayPointDescriptor = computeWaypointDescriptor(position(1,2), position(4,2), + Grid.of(position(3, 1), position(3, 2), position(3, 3), position(3, 4))); + assertThat(wayPointDescriptor.direction).isEqualTo(LeftToRight); + assertThat(wayPointDescriptor.orientation).isEqualTo(VerticalHorizontalVertical); + assertBendConfigurationOnTop(wayPointDescriptor.bendConfiguration, 2); + } + + @Test + public void computeWaypointDescriptor_same_row_left_to_right_with_elements_between_as_much_on_bottom_as_on_top() { + // +--------------------+ + // | elt | + // | elt | + // | from elt to | + // | elt | + // | elt | + // +--------------------+ + WayPointDescriptor wayPointDescriptor = computeWaypointDescriptor(position(1,3), position(4,3), + Grid.of(position(3, 1), position(2, 2), position(3, 3), position(3, 4), position(2, 5))); + assertThat(wayPointDescriptor.direction).isEqualTo(LeftToRight); + assertThat(wayPointDescriptor.orientation).isEqualTo(VerticalHorizontalVertical); + assertBendConfigurationOnBottom(wayPointDescriptor.bendConfiguration, 3); + } + + // ================================================================================================================= + // from and to in the same row - right to left + // ================================================================================================================= + + @Test + public void computeWaypointDescriptor_same_row_from_on_right() { + WayPointDescriptor wayPointDescriptor = computeWaypointDescriptor(positionSameRow(100), positionSameRow(20)); + assertThat(wayPointDescriptor.direction).isEqualTo(RightToLeft); + assertThat(wayPointDescriptor.orientation).isEqualTo(Horizontal); + } + + @Test + public void computeWaypointDescriptor_same_row_right_to_left_with_elements_between_none_on_bottom() { + // +--------------------+ + // | to elt from | + // | | + // +--------------------+ + WayPointDescriptor wayPointDescriptor = computeWaypointDescriptor(position(4,1), position(1,1), Grid.of(position(3, 1))); + assertThat(wayPointDescriptor.direction).isEqualTo(RightToLeft); + assertThat(wayPointDescriptor.orientation).isEqualTo(VerticalHorizontalVertical); + assertBendConfigurationOnBottom(wayPointDescriptor.bendConfiguration, 1); + } + + @Test + public void computeWaypointDescriptor_same_row_right_to_left_with_elements_between_no_elements_on_top() { + // +--------------------+ + // | | + // | to elt from | + // | elt | + // +--------------------+ + WayPointDescriptor wayPointDescriptor = computeWaypointDescriptor(position(4,2), position(1,2), Grid.of(position(3, 2), position(3, 3))); + assertThat(wayPointDescriptor.direction).isEqualTo(RightToLeft); + assertThat(wayPointDescriptor.orientation).isEqualTo(VerticalHorizontalVertical); + assertBendConfigurationOnTop(wayPointDescriptor.bendConfiguration, 1); + } + + @Test + public void computeWaypointDescriptor_same_row_right_to_left_with_elements_between_more_occupied_rows_on_top() { + // +--------------------+ + // | elt | + // | elt | + // | to elt from | + // | elt | + // +--------------------+ + WayPointDescriptor wayPointDescriptor = computeWaypointDescriptor(position(4,3), position(1,3), + Grid.of(position(3, 1), position(3, 2), position(3, 3), position(3, 4))); + assertThat(wayPointDescriptor.direction).isEqualTo(RightToLeft); + assertThat(wayPointDescriptor.orientation).isEqualTo(VerticalHorizontalVertical); + assertBendConfigurationOnBottom(wayPointDescriptor.bendConfiguration, 2); + } + + @Test + public void computeWaypointDescriptor_same_row_right_to_left_with_elements_between_more_occupied_rows_on_bottom() { + // +--------------------+ + // | elt | + // | to elt from | + // | elt | + // | elt | + // +--------------------+ + WayPointDescriptor wayPointDescriptor = computeWaypointDescriptor(position(4,2), position(1,2), + Grid.of(position(3, 1), position(3, 2), position(3, 3), position(3, 4))); + assertThat(wayPointDescriptor.direction).isEqualTo(RightToLeft); + assertThat(wayPointDescriptor.orientation).isEqualTo(VerticalHorizontalVertical); + assertBendConfigurationOnTop(wayPointDescriptor.bendConfiguration, 2); + } + + @Test + public void computeWaypointDescriptor_same_row_right_to_left_with_elements_between_as_much_on_bottom_as_on_top() { + // +--------------------+ + // | elt | + // | elt | + // | to elt from | + // | elt | + // | elt | + // +--------------------+ + WayPointDescriptor wayPointDescriptor = computeWaypointDescriptor(position(4,3), position(1,3), + Grid.of(position(3, 1), position(2, 2), position(3, 3), position(3, 4), position(2, 5))); + assertThat(wayPointDescriptor.direction).isEqualTo(RightToLeft); + assertThat(wayPointDescriptor.orientation).isEqualTo(VerticalHorizontalVertical); + assertBendConfigurationOnBottom(wayPointDescriptor.bendConfiguration, 3); + } + + // ================================================================================================================= + // from and to in the same column + // ================================================================================================================= + + @Test + public void computeWaypointDescriptor_same_column_from_on_top() { + WayPointDescriptor wayPointDescriptor = computeWaypointDescriptor(positionSameColumn(10), positionSameColumn(100)); + assertThat(wayPointDescriptor.direction).isEqualTo(TopToBottom); + assertThat(wayPointDescriptor.orientation).isEqualTo(Vertical); + } + + @Test + public void computeWaypointDescriptor_same_column_from_on_bottom() { + WayPointDescriptor wayPointDescriptor = computeWaypointDescriptor(positionSameColumn(100), positionSameColumn(20)); + assertThat(wayPointDescriptor.direction).isEqualTo(BottomToTop); + assertThat(wayPointDescriptor.orientation).isEqualTo(Vertical); + } + + // ================================================================================================================= + // Add waypoints when no elements between from and to + // ================================================================================================================= + + @Test + public void computeWaypointDescriptor_no_elements_between_from_on_top_left_to_on_bottom_right() { + // +-----------------+ + // | from | + // | to | + // +-----------------+ + WayPointDescriptor wayPointDescriptor = computeWaypointDescriptor(position(10, 10), position(50, 50)); + assertThat(wayPointDescriptor.direction).isEqualTo(TopLeftToBottomRight); + assertThat(wayPointDescriptor.orientation).isEqualTo(HorizontalVertical); + } + + @Test + public void computeWaypointDescriptor_no_elements_between_from_on_top_right_to_on_bottom_right() { + // +-----------------+ + // | from | + // | to | + // +-----------------+ + WayPointDescriptor wayPointDescriptor = computeWaypointDescriptor(position(50, 10), position(10, 50)); + assertThat(wayPointDescriptor.direction).isEqualTo(TopRightToBottomLeft); + assertThat(wayPointDescriptor.orientation).isEqualTo(HorizontalVertical); + } + + @Test + public void computeWaypointDescriptor_no_elements_between_from_on_bottom_left_to_on_top_right() { + // +-----------------+ + // | to | + // | from | + // +-----------------+ + WayPointDescriptor wayPointDescriptor = computeWaypointDescriptor(position(10, 100), position(50, 50)); + assertThat(wayPointDescriptor.direction).isEqualTo(BottomLeftToTopRight); + assertThat(wayPointDescriptor.orientation).isEqualTo(VerticalHorizontal); + } + + @Test + public void computeWaypointDescriptor_no_elements_between_from_on_bottom_right_to_on_top_left() { + // +-----------------+ + // | to | + // | from | + // +-----------------+ + WayPointDescriptor wayPointDescriptor = computeWaypointDescriptor(position(50, 50), position(10, 10)); + assertThat(wayPointDescriptor.direction).isEqualTo(BottomRightToTopLeft); + assertThat(wayPointDescriptor.orientation).isEqualTo(VerticalHorizontal); + } + + // ================================================================================================================= + // Add waypoints when from is a gateway + // ================================================================================================================= + + @Test + public void computeWaypointDescriptor_from_join_gateway_on_bottom_left_to_on_top_right() { + // +---------------------+ + // | to | + // | from-gw-join | + // +---------------------+ + WayPointDescriptor wayPointDescriptor = computeWaypointDescriptor(positionGatewayJoin(10, 100), position(50, 50)); + assertThat(wayPointDescriptor.direction).isEqualTo(BottomLeftToTopRight); + assertThat(wayPointDescriptor.orientation).isEqualTo(HorizontalVertical); + } + + @Test + public void computeWaypointDescriptor_from_join_gateway_on_top_left_to_on_bottom_right() { + // +---------------------+ + // | from-gw-join | + // | to | + // +---------------------+ + WayPointDescriptor wayPointDescriptor = computeWaypointDescriptor(positionGatewayJoin(1, 1), position(5, 5)); + assertThat(wayPointDescriptor.direction).isEqualTo(TopLeftToBottomRight); + assertThat(wayPointDescriptor.orientation).isEqualTo(HorizontalVertical); + } + + @Test + public void computeWaypointDescriptor_from_split_gateway_on_bottom_left_to_on_top_right() { + // +---------------------+ + // | to | + // | from-gw-split | + // +---------------------+ + WayPointDescriptor wayPointDescriptor = computeWaypointDescriptor(positionGatewaySplit(10, 100), position(50, 50)); + assertThat(wayPointDescriptor.direction).isEqualTo(BottomLeftToTopRight); + assertThat(wayPointDescriptor.orientation).isEqualTo(VerticalHorizontal); + } + + @Test + public void computeWaypointDescriptor_from_gateway_split_on_bottom_left_to_gateway_join_on_top_right() { + // +-----------------------------+ + // | to-gw-join | + // | from-gw-split | + // +-----------------------------+ + WayPointDescriptor wayPointDescriptor = computeWaypointDescriptor(positionGatewaySplit(10, 100), positionGatewayJoin(50, 50)); + assertThat(wayPointDescriptor.direction).isEqualTo(BottomLeftToTopRight); + assertThat(wayPointDescriptor.orientation).isEqualTo(HorizontalVertical); + } + + @Test + public void computeWaypointDescriptor_from_gateway_split_on_bottom_left_to_gateway_split_on_top_right() { + // +-----------------------------+ + // | to-gw-split | + // | from-gw-split | + // +-----------------------------+ + WayPointDescriptor wayPointDescriptor = computeWaypointDescriptor(positionGatewaySplit(10, 100), positionGatewaySplit(50, 50)); + assertThat(wayPointDescriptor.direction).isEqualTo(BottomLeftToTopRight); + assertThat(wayPointDescriptor.orientation).isEqualTo(VerticalHorizontal); + } + + @Test + public void computeWaypointDescriptor_from_gateway_split_on_top_left_to_on_bottom_right() { + // +-----------------------+ + // | from-gw-split | + // | to | + // +-----------------------+ + WayPointDescriptor wayPointDescriptor = computeWaypointDescriptor(positionGatewaySplit(10, 10), position(50, 50)); + assertThat(wayPointDescriptor.direction).isEqualTo(TopLeftToBottomRight); + assertThat(wayPointDescriptor.orientation).isEqualTo(VerticalHorizontal); + } + + @Test + public void computeWaypointDescriptor_from_gateway_split_on_top_left_to_gateway_join_on_bottom_right() { + // +------------------------------+ + // | from-gw-split | + // | to-gw-join | + // +------------------------------+ + WayPointDescriptor wayPointDescriptor = computeWaypointDescriptor(positionGatewaySplit(10, 10), positionGatewayJoin(50, 50)); + assertThat(wayPointDescriptor.direction).isEqualTo(TopLeftToBottomRight); + assertThat(wayPointDescriptor.orientation).isEqualTo(HorizontalVertical); + } + + @Test + public void computeWaypointDescriptor_from_gateway_split_on_top_left_to_gateway_split_on_bottom_right() { + // +-----------------------------+ + // | from-gw-split | + // | to-gw-split | + // +-----------------------------+ + WayPointDescriptor wayPointDescriptor = computeWaypointDescriptor(positionGatewaySplit(10, 10), positionGatewaySplit(50, 50)); + assertThat(wayPointDescriptor.direction).isEqualTo(TopLeftToBottomRight); + assertThat(wayPointDescriptor.orientation).isEqualTo(VerticalHorizontal); + } + + @Test + public void computeWaypointDescriptor_from_gateway_split_on_top_left_to_gateway_join_on_bottom_right_with_element_on_top_left() { + // +------------------------------+ + // | from-gw-split elt | + // | to-gw-join | + // +------------------------------+ + WayPointDescriptor wayPointDescriptor = computeWaypointDescriptor(positionGatewaySplit(1, 1), positionGatewayJoin(2, 2), + Grid.of(position(2, 1))); + assertThat(wayPointDescriptor.direction).isEqualTo(TopLeftToBottomRight); + assertThat(wayPointDescriptor.orientation).isEqualTo(VerticalHorizontal); + } + + // ================================================================================================================= + // Add waypoints when 'to' is a gateway and not already covered by other tests + // ================================================================================================================= + + @Test + public void computeWaypointDescriptor_from_on_top_left_to_gateway_join_on_bottom_right() { + // +--------------------+ + // | from | + // | to-gw-join | + // +--------------------+ + WayPointDescriptor wayPointDescriptor = computeWaypointDescriptor(position(10, 10), positionGatewayJoin(50, 50)); + assertThat(wayPointDescriptor.direction).isEqualTo(TopLeftToBottomRight); + assertThat(wayPointDescriptor.orientation).isEqualTo(HorizontalVertical); + } + + @Test + public void computeWaypointDescriptor_from_on_bottom_left_to_gateway_join_on_top_right() { + // +-----------------------+ + // | to-gw-join | + // | from | + // +-----------------------+ + WayPointDescriptor wayPointDescriptor = computeWaypointDescriptor(position(10, 100), positionGatewayJoin(50, 50)); + assertThat(wayPointDescriptor.direction).isEqualTo(BottomLeftToTopRight); + assertThat(wayPointDescriptor.orientation).isEqualTo(HorizontalVertical); + } + + @Test + public void computeWaypointDescriptor_from_on_top_right_to_gateway_join_on_bottom_left() { + // +-----------------------+ + // | from | + // | to-gw-join | + // +-----------------------+ + WayPointDescriptor wayPointDescriptor = computeWaypointDescriptor(position(50, 50), positionGatewayJoin(10, 100)); + assertThat(wayPointDescriptor.direction).isEqualTo(TopRightToBottomLeft); + assertThat(wayPointDescriptor.orientation).isEqualTo(HorizontalVertical); + } + + @Test + public void computeWaypointDescriptor_from_gateway_split_on_top_right_to_bottom_left() { + // +-----------------------+ + // | from-gw-split | + // | elt | + // +-----------------------+ + WayPointDescriptor wayPointDescriptor = computeWaypointDescriptor(positionGatewaySplit(2, 1), position(1, 2), + Grid.of(position(2, 2))); + assertThat(wayPointDescriptor.direction).isEqualTo(TopRightToBottomLeft); + assertThat(wayPointDescriptor.orientation).isEqualTo(VerticalHorizontal); + } + + @Test + public void computeWaypointDescriptor_from_on_bottom_right_to_gateway_on_top_left() { + // +--------------------+ + // | to-gw-join | + // | from | + // +--------------------+ + WayPointDescriptor wayPointDescriptor = computeWaypointDescriptor(position(50, 50), positionGatewayJoin(10, 10)); + assertThat(wayPointDescriptor.direction).isEqualTo(BottomRightToTopLeft); + assertThat(wayPointDescriptor.orientation).isEqualTo(HorizontalVertical); + } + + // ================================================================================================================= + // Add waypoints when there are elements between from and to + // ================================================================================================================= + + @Test + public void computeWaypointDescriptor_has_elements_between_from_and_top_with_from_on_top_left() { + // +-----------------+ + // | from | + // | element to | + // +-----------------+ + WayPointDescriptor wayPointDescriptor = computeWaypointDescriptor(position(1, 1), position(2, 2), Grid.of(position(1, 2))); + assertThat(wayPointDescriptor.direction).isEqualTo(TopLeftToBottomRight); + assertThat(wayPointDescriptor.orientation).isEqualTo(HorizontalVertical); + } + + @Test + public void computeWaypointDescriptor_has_elements_between_from_and_top_with_from_on_top_left_case_2() { + // +-----------------+ + // | from element | + // | to | + // +-----------------+ + WayPointDescriptor wayPointDescriptor = computeWaypointDescriptor(position(1, 1), position(2, 2), Grid.of(position(2, 1))); + assertThat(wayPointDescriptor.direction).isEqualTo(TopLeftToBottomRight); + assertThat(wayPointDescriptor.orientation).isEqualTo(VerticalHorizontal); + } + + @Test + public void computeWaypointDescriptor_has_elements_between_from_and_top_with_from_on_bottom_left() { + // +-----------------+ + // | element to | + // | from | + // +-----------------+ + WayPointDescriptor wayPointDescriptor = computeWaypointDescriptor(position(1, 2), position(2, 1), Grid.of(position(1, 1))); + assertThat(wayPointDescriptor.direction).isEqualTo(BottomLeftToTopRight); + assertThat(wayPointDescriptor.orientation).isEqualTo(HorizontalVertical); + } + + @Test + public void computeWaypointDescriptor_has_elements_between_from_and_top_with_from_on_bottom_left_case2() { + // +-----------------+ + // | to | + // | from element | + // +-----------------+ + WayPointDescriptor wayPointDescriptor = computeWaypointDescriptor(position(1, 2), position(2, 1), Grid.of(position(2, 2))); + assertThat(wayPointDescriptor.direction).isEqualTo(BottomLeftToTopRight); + assertThat(wayPointDescriptor.orientation).isEqualTo(VerticalHorizontal); + } + + @Test + public void computeWaypointDescriptor_has_elements_between_from_and_top_with_from_on_top_right() { + // +-----------------+ + // | element from | + // | to | + // +-----------------+ + WayPointDescriptor wayPointDescriptor = computeWaypointDescriptor(position(2, 1), position(1, 2), Grid.of(position(1, 1))); + assertThat(wayPointDescriptor.direction).isEqualTo(TopRightToBottomLeft); + assertThat(wayPointDescriptor.orientation).isEqualTo(VerticalHorizontal); + } + + @Test + public void computeWaypointDescriptor_has_elements_between_from_and_top_with_from_on_top_right_case2() { + // +-----------------+ + // | from | + // | to element | + // +-----------------+ + WayPointDescriptor wayPointDescriptor = computeWaypointDescriptor(position(2, 1), position(1, 2), Grid.of(position(2, 2))); + assertThat(wayPointDescriptor.direction).isEqualTo(TopRightToBottomLeft); + assertThat(wayPointDescriptor.orientation).isEqualTo(HorizontalVertical); + } + + @Test + public void computeWaypointDescriptor_has_elements_between_from_and_top_with_from_on_bottom_right() { + // +-----------------+ + // | to | + // | element from | + // +-----------------+ + WayPointDescriptor wayPointDescriptor = computeWaypointDescriptor(position(2, 2), position(1, 1), Grid.of(position(1, 2))); + assertThat(wayPointDescriptor.direction).isEqualTo(BottomRightToTopLeft); + assertThat(wayPointDescriptor.orientation).isEqualTo(VerticalHorizontal); + } + + @Test + public void computeWaypointDescriptor_has_elements_between_from_and_top_with_from_on_bottom_right_case2() { + // +-----------------+ + // | to element | + // | from | + // +-----------------+ + WayPointDescriptor wayPointDescriptor = computeWaypointDescriptor(position(2, 2), position(1, 1), Grid.of(position(2, 1))); + assertThat(wayPointDescriptor.direction).isEqualTo(BottomRightToTopLeft); + assertThat(wayPointDescriptor.orientation).isEqualTo(HorizontalVertical); + } + + // ================================================================================================================= + // UTILS + // ================================================================================================================= + + private static WayPointDescriptor computeWaypointDescriptor(Position positionFrom, Position positionTo) { + return computeWaypointDescriptor(positionFrom, positionTo, new Grid()); + } + + private static WayPointDescriptor computeWaypointDescriptor(Position positionFrom, Position positionTo, Grid grid) { + return new WayPointsPositioner(new GridSearcher(grid)).computeWaypointDescriptor(positionFrom, positionTo); + } + + private static Position positionSameRow(int x) { + return position(x,12); // arbitrary row + } + + private static Position positionSameColumn(int y) { + return position(50,y); // arbitrary column + } + + private static Position position(int x, int y) { + return Position.builder().x(x).y(y).build(); + } + + private static Position positionGatewaySplit(int x, int y) { + return Position.position(new Shape(null, null, ShapeType.GATEWAY, true), x, y); + } + + private static Position positionGatewayJoin(int x, int y) { + return Position.position(new Shape(null, null, ShapeType.GATEWAY, false), x, y); + } + + private static void assertBendConfigurationOnBottom(BendConfiguration bendConfiguration, int offset) { + assertThat(bendConfiguration.direction).isEqualTo(BendDirection.BOTTOM); + assertThat(bendConfiguration.offset).isEqualTo(offset); + } + + private static void assertBendConfigurationOnTop(BendConfiguration bendConfiguration, int offset) { + assertThat(bendConfiguration.direction).isEqualTo(BendDirection.TOP); + assertThat(bendConfiguration.offset).isEqualTo(offset); + } + +}