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..cc47ea47 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 @@ -18,10 +18,11 @@ import static io.process.analytics.tools.bpmn.generator.internal.StringUtils.defaultIfNull; 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.display.DisplayEdge; 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; 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); + } + +}