Skip to content

Commit

Permalink
Merge pull request #335 from iriusrisk/feature/OPT-1032
Browse files Browse the repository at this point in the history
[feature/OPT-1032] to dev
  • Loading branch information
dantolin-iriusrisk authored Oct 25, 2023
2 parents df48991 + 672c120 commit 2f2a0a5
Show file tree
Hide file tree
Showing 8 changed files with 165 additions and 42 deletions.
21 changes: 19 additions & 2 deletions slp_drawio/slp_drawio/load/diagram_dataflow_loader.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,27 @@
from typing import List

from slp_drawio.slp_drawio.load.drawio_dict_utils import get_mx_cell_dataflows, get_dataflow_tags
from slp_drawio.slp_drawio.objects.diagram_objects import DiagramDataflow


class DiagramDataflowLoader:

def __init__(self, source: dict):
self.source: dict = source
self._source: dict = source

def load(self) -> [DiagramDataflow]:
return []

result: List[DiagramDataflow] = []

mx_cell_dataflows = get_mx_cell_dataflows(self._source)
for mx_cell in mx_cell_dataflows:
if all(key in mx_cell for key in ['source', 'target']):
result.append(DiagramDataflow(
dataflow_id=mx_cell.get('id'),
name=f'{mx_cell.get("id")}-dataflow',
source_node=mx_cell.get('source'),
destination_node=mx_cell.get('target'),
tags=get_dataflow_tags(mx_cell.get('id'), self._source)
))

return result
21 changes: 16 additions & 5 deletions slp_drawio/slp_drawio/load/drawio_dict_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,32 @@ def __is_mx_cell_dataflow(mx_cell):


def __is_mx_cell_component(mx_cell: Dict):
if 'mxGeometry' not in mx_cell:
mx_geometry = mx_cell.get('mxGeometry', {})
if not all(key in mx_geometry for key in ['height', 'width']):
return False
return not __is_mx_cell_dataflow(mx_cell)


def __get_mx_cell_from_source(source):
def __get_mx_cells(source) -> List[Dict]:
return source.get("mxfile", {}).get("diagram", {}).get("mxGraphModel", {}).get("root", {}).get("mxCell", [])


def get_mx_cell_components(source) -> List[Dict]:
return list(filter(lambda c: __is_mx_cell_component(c), __get_mx_cell_from_source(source)))
return list(filter(lambda c: __is_mx_cell_component(c), __get_mx_cells(source)))


def get_mx_cell_dataflows(source) -> List[Dict]:
return list(filter(lambda c: __is_mx_cell_dataflow(c), __get_mx_cells(source)))


def get_dataflow_tags(dataflow_id: str, source) -> List[str]:
tags: List[str] = []

for mx_cell in __get_mx_cells(source):
if dataflow_id == mx_cell.get('parent') and 'value' in mx_cell:
tags.append(mx_cell['value'])

def get_mxcell_dataflows(source) -> List[Dict]:
return list(filter(lambda c: __is_mx_cell_dataflow(c), __get_mx_cell_from_source(source)))
return tags


def is_multiple_pages(source):
Expand Down
16 changes: 14 additions & 2 deletions slp_drawio/slp_drawio/objects/diagram_objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,20 @@ def __str__(self) -> str:

@auto_repr
class DiagramDataflow:
def __init__(self, id: str):
self.otm = Dataflow(dataflow_id=id, name='', source_node=None, destination_node=None)
def __init__(self,
dataflow_id: str,
name: str = '',
source_node: str = None,
destination_node: str = None,
tags: List[str] = None
):
self.otm = Dataflow(
dataflow_id=dataflow_id,
name=name,
source_node=source_node,
destination_node=destination_node,
tags=tags
)


@auto_repr
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@
},
"id":"pt2kyrPXSm7H56EBWWGj-2",
"style":"edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;",
"edge":"1",
"parent":"1",
"source":"pt2kyrPXSm7H56EBWWGj-1"
"source":"pt2kyrPXSm7H56EBWWGj-1",
"edge":"1"
},
{
"mxGeometry":{
Expand All @@ -46,8 +46,8 @@
},
"id":"pt2kyrPXSm7H56EBWWGj-4",
"style":"edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;",
"edge":"1",
"parent":"1"
"parent":"1",
"edge":"1"
},
{
"mxGeometry":{
Expand All @@ -60,8 +60,8 @@
"id":"pt2kyrPXSm7H56EBWWGj-1",
"value":"",
"style":"outlineConnect=0;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;shape=mxgraph.aws3.ec2;fillColor=#F58534;gradientColor=none;",
"vertex":"1",
"parent":"1"
"parent":"1",
"vertex":"1"
},
{
"mxGeometry":{
Expand All @@ -88,9 +88,9 @@
},
"id":"pt2kyrPXSm7H56EBWWGj-5",
"style":"edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;",
"edge":"1",
"parent":"1",
"target":"pt2kyrPXSm7H56EBWWGj-1"
"target":"pt2kyrPXSm7H56EBWWGj-1",
"edge":"1"
},
{
"mxGeometry":{
Expand All @@ -99,10 +99,28 @@
},
"id":"pt2kyrPXSm7H56EBWWGj-6",
"style":"edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;",
"edge":"1",
"parent":"1",
"source":"pt2kyrPXSm7H56EBWWGj-1",
"target":"pt2kyrPXSm7H56EBWWGj-7"
"target":"pt2kyrPXSm7H56EBWWGj-7",
"edge":"1"
},
{
"mxGeometry":{
"mxPoint":{
"y":"1",
"as":"offset"
},
"x":"-0.0044",
"y":"1",
"relative":"1",
"as":"geometry"
},
"id":"m2HWG3bc47D113dpYQm--1",
"value":"Dataflow Info",
"style":"edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];",
"vertex":"1",
"connectable":"0",
"parent":"pt2kyrPXSm7H56EBWWGj-6"
},
{
"mxGeometry":{
Expand All @@ -115,8 +133,8 @@
"id":"pt2kyrPXSm7H56EBWWGj-7",
"value":"",
"style":"outlineConnect=0;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;shape=mxgraph.aws3.ec2;fillColor=#F58534;gradientColor=none;",
"vertex":"1",
"parent":"1"
"parent":"1",
"vertex":"1"
},
{
"mxGeometry":{
Expand All @@ -125,15 +143,15 @@
},
"id":"pt2kyrPXSm7H56EBWWGj-8",
"style":"edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;",
"edge":"1",
"parent":"1",
"source":"pt2kyrPXSm7H56EBWWGj-7",
"target":"pt2kyrPXSm7H56EBWWGj-7"
"target":"pt2kyrPXSm7H56EBWWGj-7",
"edge":"1"
}
]
},
"dx":"1364",
"dy":"771",
"dy":"759",
"grid":"1",
"gridSize":"10",
"guides":"1",
Expand All @@ -152,9 +170,10 @@
"id":"KqMttW68mEOmiwTKMwjx"
},
"host":"app.diagrams.net",
"modified":"2023-10-19T16:09:41.010Z",
"agent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36",
"etag":"53oyWIo9RTndIs_Ustab",
"version":"22.0.5"
"modified":"2023-10-25T06:52:34.609Z",
"agent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36",
"etag":"gHENJeu3QhVxARD-wiXo",
"version":"22.0.7",
"type":"device"
}
}
Original file line number Diff line number Diff line change
@@ -1,25 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<mxfile host="app.diagrams.net" modified="2023-10-19T16:09:41.010Z" agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36" etag="53oyWIo9RTndIs_Ustab" version="22.0.5">
<mxfile host="app.diagrams.net" modified="2023-10-25T06:52:34.609Z" agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36" etag="gHENJeu3QhVxARD-wiXo" version="22.0.7" type="device">
<diagram name="Page-1" id="KqMttW68mEOmiwTKMwjx">
<mxGraphModel dx="1364" dy="771" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<mxGraphModel dx="1364" dy="759" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="pt2kyrPXSm7H56EBWWGj-2" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="pt2kyrPXSm7H56EBWWGj-1">
<mxCell id="pt2kyrPXSm7H56EBWWGj-2" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="pt2kyrPXSm7H56EBWWGj-1" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="308.25" y="230" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="pt2kyrPXSm7H56EBWWGj-4" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1">
<mxCell id="pt2kyrPXSm7H56EBWWGj-4" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="210" y="240" as="targetPoint" />
<mxPoint x="210" y="340" as="sourcePoint" />
</mxGeometry>
</mxCell>
<mxCell id="pt2kyrPXSm7H56EBWWGj-1" value="" style="outlineConnect=0;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;shape=mxgraph.aws3.ec2;fillColor=#F58534;gradientColor=none;" vertex="1" parent="1">
<mxCell id="pt2kyrPXSm7H56EBWWGj-1" value="" style="outlineConnect=0;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;shape=mxgraph.aws3.ec2;fillColor=#F58534;gradientColor=none;" parent="1" vertex="1">
<mxGeometry x="270" y="340" width="76.5" height="73" as="geometry" />
</mxCell>
<mxCell id="pt2kyrPXSm7H56EBWWGj-5" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" target="pt2kyrPXSm7H56EBWWGj-1">
<mxCell id="pt2kyrPXSm7H56EBWWGj-5" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" target="pt2kyrPXSm7H56EBWWGj-1" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="308" y="490" as="sourcePoint" />
<Array as="points">
Expand All @@ -28,13 +27,18 @@
</Array>
</mxGeometry>
</mxCell>
<mxCell id="pt2kyrPXSm7H56EBWWGj-6" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="1" source="pt2kyrPXSm7H56EBWWGj-1" target="pt2kyrPXSm7H56EBWWGj-7">
<mxCell id="pt2kyrPXSm7H56EBWWGj-6" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;" parent="1" source="pt2kyrPXSm7H56EBWWGj-1" target="pt2kyrPXSm7H56EBWWGj-7" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="pt2kyrPXSm7H56EBWWGj-7" value="" style="outlineConnect=0;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;shape=mxgraph.aws3.ec2;fillColor=#F58534;gradientColor=none;" vertex="1" parent="1">
<mxCell id="m2HWG3bc47D113dpYQm--1" value="Dataflow Info" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="pt2kyrPXSm7H56EBWWGj-6">
<mxGeometry x="-0.0044" y="1" relative="1" as="geometry">
<mxPoint y="1" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="pt2kyrPXSm7H56EBWWGj-7" value="" style="outlineConnect=0;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;shape=mxgraph.aws3.ec2;fillColor=#F58534;gradientColor=none;" parent="1" vertex="1">
<mxGeometry x="460" y="330" width="76.5" height="93" as="geometry" />
</mxCell>
<mxCell id="pt2kyrPXSm7H56EBWWGj-8" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="pt2kyrPXSm7H56EBWWGj-7" target="pt2kyrPXSm7H56EBWWGj-7">
<mxCell id="pt2kyrPXSm7H56EBWWGj-8" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="pt2kyrPXSm7H56EBWWGj-7" target="pt2kyrPXSm7H56EBWWGj-7" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
</root>
Expand Down
2 changes: 1 addition & 1 deletion slp_drawio/tests/resources/test_resource_paths.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
aws_minimal_drawio_as_json = f'{drawio}/aws_minimal_source.json'
aws_multiple_pages_drawio = f'{drawio}/aws_multiple_pages.drawio'
aws_multiple_pages_drawio_as_json = f'{drawio}/aws_multiple_pages.json'
aws_two_component_multiple_dataflows = f'{drawio}/aws_two_component_multiple_dataflows.json'
aws_two_component_multiple_dataflows_as_json = f'{drawio}/aws_two_component_multiple_dataflows.json'
wrong_mxcell_drawio = f'{drawio}/wrong_mxcell.drawio'
wrong_mxfile_drawio = f'{drawio}/wrong_mxfile.drawio'
wrong_mxgraphmodel_drawio = f'{drawio}/wrong_mxgraphmodel.drawio'
Expand Down
38 changes: 38 additions & 0 deletions slp_drawio/tests/unit/load/test_diagram_dataflow_loader.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import json
from unittest.mock import patch

from sl_util.sl_util.file_utils import get_byte_data
from slp_drawio.slp_drawio.load.diagram_dataflow_loader import DiagramDataflowLoader
from slp_drawio.slp_drawio.load.drawio_dict_utils import get_dataflow_tags
from slp_drawio.tests.resources import test_resource_paths


class TestDiagramDataflowLoader:

@patch('slp_drawio.slp_drawio.load.diagram_dataflow_loader.get_dataflow_tags', wraps=get_dataflow_tags)
def test_load(self, get_dataflow_tags_wrapper):
# GIVEN a DrawIO
source = json.loads(get_byte_data(test_resource_paths.aws_two_component_multiple_dataflows_as_json))

# WHEN DiagramDataflowLoader::load
diagram_dataflows = DiagramDataflowLoader(source).load()

# THEN diagram dataflows has length of 2
assert len(diagram_dataflows) == 2
# AND elements has the following information
assert diagram_dataflows[0].otm.id == 'pt2kyrPXSm7H56EBWWGj-6'
assert diagram_dataflows[0].otm.name == 'pt2kyrPXSm7H56EBWWGj-6-dataflow'
assert diagram_dataflows[0].otm.source_node == 'pt2kyrPXSm7H56EBWWGj-1'
assert diagram_dataflows[0].otm.destination_node == 'pt2kyrPXSm7H56EBWWGj-7'
assert len(diagram_dataflows[0].otm.tags) == 1
assert diagram_dataflows[0].otm.tags[0] == 'Dataflow Info'

# AND self reference dataflow is also mapped
assert diagram_dataflows[1].otm.id == 'pt2kyrPXSm7H56EBWWGj-8'
assert diagram_dataflows[1].otm.name == 'pt2kyrPXSm7H56EBWWGj-8-dataflow'
assert diagram_dataflows[1].otm.source_node == 'pt2kyrPXSm7H56EBWWGj-7'
assert diagram_dataflows[1].otm.destination_node == 'pt2kyrPXSm7H56EBWWGj-7'
assert len(diagram_dataflows[1].otm.tags) == 0

# AND the method get_dataflow_tags has been called once for each dataflow
assert get_dataflow_tags_wrapper.call_count == len(diagram_dataflows)
28 changes: 25 additions & 3 deletions slp_drawio/tests/unit/load/test_drawio_dict_utils.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@

# class TestDrawioDictUtils:
import json
from unittest.mock import patch

import pytest

Expand Down Expand Up @@ -48,7 +49,7 @@ def test_is_multiple_pages(source, expected):

def test_get_mx_cell_components():
# GIVEN a DrawIO with one component and Dataflow with multiple configurations
source = json.loads(get_byte_data(test_resource_paths.aws_two_component_multiple_dataflows))
source = json.loads(get_byte_data(test_resource_paths.aws_two_component_multiple_dataflows_as_json))

# WHEN drawio_dict_utils::get_components_from_source
components = drawio_dict_utils.get_mx_cell_components(source)
Expand All @@ -59,15 +60,36 @@ def test_get_mx_cell_components():

def test_get_mx_cell_dataflows():
# GIVEN a DrawIO with one component and Dataflow with multiple configurations
source = json.loads(get_byte_data(test_resource_paths.aws_two_component_multiple_dataflows))
source = json.loads(get_byte_data(test_resource_paths.aws_two_component_multiple_dataflows_as_json))

# WHEN drawio_dict_utils::get_components_from_source
dataflows = drawio_dict_utils.get_mxcell_dataflows(source)
dataflows = drawio_dict_utils.get_mx_cell_dataflows(source)

# THEN it returns 5 dataflows
assert len(dataflows) == 5


@patch('slp_drawio.slp_drawio.load.drawio_dict_utils.__get_mx_cells')
@pytest.mark.parametrize('dataflow_id, source, expected', [
pytest.param('1', [], [], id="tags are empty"),
pytest.param('1', [{'parent': '2'}, {'parent': '1', 'value': 'tag'}], ['tag'], id="tags has one value"),
pytest.param('1', [{'parent': '1', 'value': 'tag'}, {'parent': '1', 'value': 'tag2'}], ['tag', 'tag2'],
id="tags has two values"),
pytest.param('1', [{'parent': '2', 'value': 'tag'}], [], id="tags is empty as not child exists"),
pytest.param('1', [{'parent': '1'}], [], id="tags is empty as not value exists"),
])
def test_get_dataflow_tags(__get_mx_cells_mock, dataflow_id: str, source, expected):
# GIVEN the dataflow_id
# AND the get_mx_cells returning the given source
__get_mx_cells_mock.return_value = source

# WHEN drawio_dict_utils::get_dataflow_tags
tags = drawio_dict_utils.get_dataflow_tags(dataflow_id, {})

# THEN the tags are as expected
assert tags == expected


@pytest.mark.parametrize('mx_geometry, expected', [
pytest.param({}, {'x': 0, 'y': 0}, id="without position"),
pytest.param({'x': '10'}, {'x': 10, 'y': 0}, id="only with x value"),
Expand Down

0 comments on commit 2f2a0a5

Please sign in to comment.