Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Support for varous entity types, with or without attributes
  • Loading branch information
Riduidel committed Oct 17, 2021
1 parent ececf7f commit 78df3cc
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 11 deletions.
35 changes: 35 additions & 0 deletions examples/demo-entity-relation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
from __future__ import print_function

import sys, os
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))

import pyyed

g = pyyed.Graph()
g.add_node('Person', shape_fill="#EEEEEE",
node_type="GenericNode",
ER={"attributes": ["name", "surname"]})

#This is an entity without any attribut, for which only name will be set
g.add_node('Role', shape_fill="#EEEEEE",
node_type="GenericNode",
ER={})

g.add_node('Kind', shape_fill="#EEEEEE",
node_type="GenericNode",
ER={'weak':'true'})

# g.add_node('ICar', shape_fill="#EEEEEE",
# node_type="UMLClassNode",
# UML={"stereotype": "interface",
# "attributes": "",
# "methods": "getModel()\ngetManufacturer()\ngetPrice()\nsetPrice()"})

#g.add_node('Vehicle', shape_fill="#EEEEEE", node_type="UMLClassNode")
#g.add_edge('Car', 'Vehicle', arrowhead="white_delta")
#g.add_edge('Car', 'ICar', arrowhead="white_delta", line_type="dashed")
#g.add_node('This is a note', shape_fill="#EEEEEE", node_type="UMLNoteNode")

# print(g.get_graph())

g.write_graph('demo-entity-relation.graphml')
60 changes: 54 additions & 6 deletions pyyed/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ def __init__(self, node_name, label=None, label_alignment="center", shape="recta
shape_fill="#FF0000", transparent="false", border_color="#000000",
border_type="line", border_width="1.0", height=False, width=False, x=False,
y=False, node_type="ShapeNode", UML=False,
ER=False,
custom_properties=None, description="", url=""):

self.label = label
Expand All @@ -234,8 +235,14 @@ def __init__(self, node_name, label=None, label_alignment="center", shape="recta

self.node_name = node_name

# Entity node must be created as a GenericNode with a configuration attribute
self.node_type = node_type
self.UML = UML
# library defines the used yEd library. Currently, we support UML and Entity Relation
self.library = {}
if UML:
self.library['UML']=UML
elif ER:
self.library['ER']=ER

self.parent = None

Expand Down Expand Up @@ -324,19 +331,49 @@ def convert(self):
alignment=self.label_alignment)
label.text = self.label

ET.SubElement(shape, "y:Shape", type=self.shape)
subshape = ET.SubElement(shape, "y:Shape", type=self.shape)

if self.UML:
if 'UML' in self.library:
UML = ET.SubElement(shape, "y:UML")

attributes = ET.SubElement(UML, "y:AttributeLabel", type=self.shape)
attributes.text = self.UML["attributes"]
attributes.text = self.library['UML']["attributes"]

methods = ET.SubElement(UML, "y:MethodLabel", type=self.shape)
methods.text = self.UML["methods"]
methods.text = self.library['UML']["methods"]

stereotype = self.UML["stereotype"] if "stereotype" in self.UML else ""
stereotype = self.library['UML']["stereotype"] if "stereotype" in self.library['UML'] else ""
UML.set("stereotype", stereotype)
elif 'ER' in self.library:
shape.remove(subshape)
shape.set("configuration", "com.yworks.entityRelationship.big_entity")
label.set("configuration", "com.yworks.entityRelationship.label.name")
if 'attributes' in self.library['ER']:
attributes = ET.SubElement(shape, "y:NodeLabel", fontFamily=self.font_family,
fontSize=self.font_size,
underlinedText=self.underlined_text,
fontStyle=self.font_style,
alignment='left',
configuration="com.yworks.entityRelationship.label.attributes",
modelName='internal',
modelPostion='t')
attributes_param = self.library['ER']['attributes']
if isinstance(attributes_param, list):
attributes_param = "\n".join(attributes_param)
attributes.text = attributes_param
labelModel = ET.SubElement(attributes, "y:LabelModel")
modelParameter = ET.SubElement(attributes, "y:ModelParameter")
ET.SubElement(labelModel, "y:ErdAttributesNodeLabelModel")
ET.SubElement(modelParameter, "y:ErdAttributesNodeLabelModelParameter")

label.set('modelName', 'internal')
label.set('modelPosition', 't')
styledProperty = ET.SubElement(shape, "y:StyleProperties")
ET.SubElement(styledProperty, "y:Property", {'class':"java.lang.Boolean", 'name':"y.view.ShadowNodePainter.SHADOW_PAINTING", 'value':"true"})
weak = 'false'
if 'weak' in self.library['ER'] and self.library['ER']['weak']:
weak = 'true'
ET.SubElement(styledProperty, "y:Property", {'class':"java.lang.Boolean", 'name':"doubleBorder", 'value':weak})

if self.url:
url_node = ET.SubElement(node, "data", key="url_node")
Expand Down Expand Up @@ -565,6 +602,17 @@ def get_graph(self):
return ET.tostring(self.graphml, encoding='UTF-8').decode()

def add_node(self, node_name, **kwargs):
"""
Adds a node to the graph.
Parameters
----------
node_name : str
name of generated node
kwargs : dict, optional
contains a list of additionnal parameters.
Supported values are all parameters to Node constructor
"""
if node_name in self.existing_entities:
raise RuntimeWarning("Node %s already exists" % node_name)

Expand Down
10 changes: 5 additions & 5 deletions tests/test_pyyed.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@ def test_uml_node_properties_are_set():
"attributes": expected_attributes,
"methods": expected_methods})

assert g.nodes["AbstractClass"].UML["stereotype"] == expected_stereotype
assert g.nodes["AbstractClass"].UML["attributes"] == expected_attributes
assert g.nodes["AbstractClass"].UML["methods"] == expected_methods
assert g.nodes["AbstractClass"].library['UML']["stereotype"] == expected_stereotype
assert g.nodes["AbstractClass"].library['UML']["attributes"] == expected_attributes
assert g.nodes["AbstractClass"].library['UML']["methods"] == expected_methods

graphml = g.get_graph()
assertUmlNode(graphml, expected_stereotype,
Expand All @@ -67,8 +67,8 @@ def test_uml_stereotype_is_optional():
UML={"attributes": expected_attributes,
"methods": expected_methods})

assert g.nodes["Class"].UML["methods"] == expected_methods
assert g.nodes["Class"].UML["attributes"] == expected_attributes
assert g.nodes["Class"].library['UML']["methods"] == expected_methods
assert g.nodes["Class"].library['UML']["attributes"] == expected_attributes

graphml = g.get_graph()
assertUmlNode(graphml, "", expected_attributes, expected_methods)
Expand Down
34 changes: 34 additions & 0 deletions tests/test_pyyed_entity_relationship.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import pyyed
import xml.etree.ElementTree as xml

import pytest


def test_er_node_properties_are_set():
expected_attributes = 'attribute 1\nattribute 2'

g = pyyed.Graph()

g.add_node('BigEntity', node_type="GenericNode",
ER={'attributes': expected_attributes})

assert g.nodes["BigEntity"].library['ER']["attributes"] == expected_attributes

graphml = g.get_graph()
# assertERNode(graphml,
# expected_attributes)


# def assertERNode(graphml, expected_stereotype, expected_attributes, expected_methods):
# doc = xml.fromstring(graphml)
# nsmap = {'g': 'http://graphml.graphdrawing.org/xmlns',
# 'y': 'http://www.yworks.com/xml/graphml'
# }
# ernode = doc.find(
# 'g:graph/g:node/g:data/y:UMLClassNode/y:UML', namespaces=nsmap)
# attributes = ernode.find('y:AttributeLabel', namespaces=nsmap)
# methods = ernode.find('y:MethodLabel', namespaces=nsmap)
#
# assert ernode.attrib['stereotype'] == expected_stereotype
# assert attributes.text == expected_attributes
# assert methods.text == expected_methods

0 comments on commit 78df3cc

Please sign in to comment.