-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #334 from iriusrisk/feature/OPT-1022
[feature/OPT-1022] to dev
- Loading branch information
Showing
13 changed files
with
865 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,97 @@ | ||
import re | ||
from typing import List, Dict | ||
|
||
from otm.otm.entity.representation import RepresentationElement | ||
from slp_base import LoadingDiagramFileError | ||
from slp_drawio.slp_drawio.load.drawio_dict_utils import is_multiple_pages, \ | ||
get_attributes, get_position, get_size, get_mx_cell_components | ||
from slp_drawio.slp_drawio.objects.diagram_objects import DiagramComponent | ||
|
||
__CALCULATE_SHAPE_TYPE_EQUIVALENCES = resource_types_equivalences = { | ||
'aws.group': 'grIcon', | ||
'aws.groupCenter': 'grIcon', | ||
'aws.resourceIcon': 'resIcon', | ||
'aws.productIcon': 'prIcon' | ||
} | ||
|
||
|
||
def __remove_mxgraph_aws(text): | ||
return re.sub(r"aws\d.", "aws.", text) | ||
|
||
|
||
def __remove_mxgraph(text): | ||
return re.sub(r"mxgraph.", "", text) | ||
|
||
|
||
def __normalize_shape_type(text): | ||
for normalize_function in [__remove_mxgraph, __remove_mxgraph_aws]: | ||
text = normalize_function(text) | ||
|
||
return text | ||
|
||
|
||
def _calculate_shape_type(mx_cell: Dict, attr: str = 'shape'): | ||
shape = get_attributes(mx_cell).get(attr) | ||
if not shape: | ||
return | ||
shape_type = __normalize_shape_type(shape) | ||
if shape_type in __CALCULATE_SHAPE_TYPE_EQUIVALENCES: | ||
shape_type = _calculate_shape_type(mx_cell, __CALCULATE_SHAPE_TYPE_EQUIVALENCES.get(shape_type)) | ||
|
||
return shape_type | ||
|
||
|
||
def _get_shape_parent_id(mx_cell: Dict, mx_cell_components: List[Dict]): | ||
return mx_cell.get('parent') \ | ||
if any(item.get('id') == mx_cell.get('parent') for item in mx_cell_components) else None | ||
|
||
|
||
def _get_shape_name(mx_cell: Dict): | ||
name = mx_cell.get('value') | ||
if not name: | ||
name = _calculate_shape_type(mx_cell) or '' | ||
if '.' in name: | ||
name = name.split('.')[-1] | ||
name = name.replace('_', ' ') | ||
if not name: | ||
name = 'N/A' | ||
if len(name) == 1: | ||
name = f'_{name}' | ||
return name | ||
|
||
|
||
class DiagramComponentLoader: | ||
|
||
def __init__(self, source: dict): | ||
self.source: dict = source | ||
def __init__(self, project_id: str, source: dict): | ||
self._project_id = project_id | ||
self._source: dict = source | ||
|
||
def load(self) -> [DiagramComponent]: | ||
return [] | ||
if is_multiple_pages(self._source): | ||
raise LoadingDiagramFileError( | ||
'Diagram file is not valid', 'Diagram File is not compatible', | ||
'DrawIO processor does not accept diagrams with multiple pages') | ||
|
||
result: List[DiagramComponent] = [] | ||
|
||
mx_cell_components = get_mx_cell_components(self._source) | ||
for mx_cell in mx_cell_components: | ||
result.append(DiagramComponent( | ||
id=mx_cell.get('id'), | ||
name=_get_shape_name(mx_cell), | ||
shape_type=_calculate_shape_type(mx_cell), | ||
shape_parent_id=_get_shape_parent_id(mx_cell, mx_cell_components), | ||
representations=[self._get_representation_element(mx_cell)] | ||
)) | ||
|
||
return result | ||
|
||
def _get_representation_element(self, mx_cell: Dict) -> RepresentationElement: | ||
return RepresentationElement( | ||
id_=f"{mx_cell.get('id')}-diagram", | ||
name=f"{mx_cell.get('id')} Representation", | ||
representation=f"{self._project_id}-diagram", | ||
position=get_position(mx_cell), | ||
size=get_size(mx_cell), | ||
attributes={'style': mx_cell.get('style')} | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
from typing import Dict, List, Any | ||
|
||
|
||
def __get_as_mx_point_in_mx_geometry(attr: str, mx_geometry: Dict): | ||
if 'mxPoint' not in mx_geometry: | ||
return | ||
mx_points = [mx_geometry['mxPoint']] if isinstance(mx_geometry['mxPoint'], dict) else mx_geometry['mxPoint'] | ||
|
||
for mx_point in mx_points: | ||
if mx_point.get('as') == attr: | ||
return mx_point | ||
|
||
|
||
def __is_mx_cell_dataflow(mx_cell): | ||
if 'mxGeometry' not in mx_cell: | ||
return False | ||
|
||
source = mx_cell.get('source') or __get_as_mx_point_in_mx_geometry('sourcePoint', mx_cell['mxGeometry']) | ||
target = mx_cell.get('target') or __get_as_mx_point_in_mx_geometry('targetPoint', mx_cell['mxGeometry']) | ||
|
||
return source and target | ||
|
||
|
||
def __is_mx_cell_component(mx_cell: Dict): | ||
if 'mxGeometry' not in mx_cell: | ||
return False | ||
return not __is_mx_cell_dataflow(mx_cell) | ||
|
||
|
||
def __get_mx_cell_from_source(source): | ||
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))) | ||
|
||
|
||
def get_mxcell_dataflows(source) -> List[Dict]: | ||
return list(filter(lambda c: __is_mx_cell_dataflow(c), __get_mx_cell_from_source(source))) | ||
|
||
|
||
def is_multiple_pages(source): | ||
diagram_pages = source.get("mxfile", {}).get("diagram", None) | ||
return len(diagram_pages) > 1 if isinstance(diagram_pages, list) else False | ||
|
||
|
||
def get_attributes(mx_cell: Dict) -> Dict[str, Any]: | ||
attributes: Dict[str, Any] = {} | ||
styles = mx_cell.get('style', '').split(';') | ||
for style in styles: | ||
if not style: | ||
continue | ||
key, value = style, None | ||
if '=' in style: | ||
key, value = style.split('=', 1) | ||
attributes[key] = value | ||
|
||
return attributes | ||
|
||
|
||
def __str_to_int(value: str): | ||
return int(round(float(value), 0)) | ||
|
||
|
||
def get_position(mx_cell: Dict) -> Dict[str, float]: | ||
mx_geometry = mx_cell.get('mxGeometry', {}) | ||
return { | ||
'x': __str_to_int(mx_geometry.get('x', 0)), | ||
'y': __str_to_int(mx_geometry.get('y', 0)), | ||
} | ||
|
||
|
||
def get_size(mx_cell: Dict) -> Dict[str, float]: | ||
mx_geometry = mx_cell.get('mxGeometry', {}) | ||
return { | ||
'height': __str_to_int(mx_geometry.get('height')), | ||
'width': __str_to_int(mx_geometry.get('width')), | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.