class TestUMLModel(unittest.TestCase): def setUp(self): self.root_package = UMLPackage("1", "root") child = UMLPackage("2", "child1", self.root_package) self.root_package.children.append(child) cls = UMLClass(child, "class1", "3") child.classes.append(cls) def test_find_package(self): res = self.root_package.find_by_id("2") self.assertEqual(UMLPackage, type(res)) self.assertEqual("child1", res.name) def test_find_class(self): res = self.root_package.find_by_id("3") self.assertEqual(UMLClass, type(res)) self.assertEqual("class1", res.name) def test_string_to_multiplicity(self): assoc = UMLAssociation(self.root_package, self.root_package.children[0].classes[0], self.root_package.children[0].classes[0], 1) self.assertEqual(assoc.string_to_multiplicity("0..1"), ("0", "1")) self.assertEqual(assoc.string_to_multiplicity("0..*"), ("0", "*")) self.assertEqual(assoc.string_to_multiplicity("*..1"), ("*", "1")) def test_association_cardinality(self): assoc = UMLAssociation(self.root_package, self.root_package.children[0].classes[0], self.root_package.children[0].classes[0], 1) assoc.source_multiplicity = ("0", "1") assoc.destination_multiplicity = ("0", "*") self.assertEqual(assoc.cardinality, Cardinality.ONE_TO_MANY) assoc.source_multiplicity = ("0", "1") assoc.destination_multiplicity = ("0", "1") self.assertEqual(assoc.cardinality, Cardinality.ONE_TO_ONE) assoc.source_multiplicity = ("0", "*") assoc.destination_multiplicity = ("0", "1") self.assertEqual(assoc.cardinality, Cardinality.MANY_TO_ONE) assoc.source_multiplicity = ("0", "*") assoc.destination_multiplicity = ("0", "*") self.assertEqual(assoc.cardinality, Cardinality.MANY_TO_MANY) def test_association_type(self): assoc = UMLAssociation(self.root_package, self.root_package.children[0].classes[0], self.root_package.children[0].classes[0], 1) self.assertEqual(assoc.association_type, UMLAssociationType.ASSOCIATION) assoc = UMLAssociation(self.root_package, self.root_package.children[0].classes[0], self.root_package.children[0].classes[0], 1, UMLAssociationType.COMPOSITION) self.assertEqual(assoc.association_type, UMLAssociationType.COMPOSITION)
def setUp(self): self.package = UMLPackage("id", "name") self.instance = UMLInstance(self.package, "test1", 1) attr = UMLAttribute(self.package, 'testatt', 1) attr.value = "testval" self.instance.attributes.append(attr) self.package.instances.append(self.instance)
def package_parse(element, root_element, parent_package: Optional[UMLPackage]) -> UMLPackage: """ Extract package details, call class parser for classes and self parser for sub-packages. Association linking is not done here, but in a 2nd pass using the parse_associations function. """ name = get_label_name(element) id = element.get('id') package = UMLPackage(id, name, parent_package) package._root_element = root_element model = root_element.find('./diagram/mxGraphModel/root') child_elements = model.findall('object/mxCell[@parent="{}"]'.format(id)) logger.debug("Added UMLPackage {}".format(package.path)) # Parse classes for element in child_elements: object_element = element.find("..") element_type = object_element.get("UMLType") if element_type == "Class": cls = class_parse(package, object_element, root_element) package.classes.append(cls) elif element_type == "Enumeration": enum = enumeration_parse(package, object_element, root_element) package.enumerations.append(enum) elif element_type == "Package": pkg = package_parse(object_element, package._root_element, package) package.children.append(pkg) # Classes are needed to parse generalisations and associations for element in child_elements: object_element = element.find("..") element_type = object_element.get("UMLType") if element_type == "Generalization": generalization_parse(package, object_element, root_element) elif element_type == "Association": association_parse(package, object_element, root_element) elif element_type == "Composition": association_parse(package, object_element, root_element) return package
class TestUMLModel(unittest.TestCase): def setUp(self): self.root_package = UMLPackage("1", "root") child = UMLPackage("2", "child1", self.root_package) self.root_package.children.append(child) cls = UMLClass(child, "class1", "3") child.classes.append(cls) def test_find_package(self): res = self.root_package.find_by_id("2") self.assertEqual(UMLPackage, type(res)) self.assertEqual("child1", res.name) def test_find_class(self): res = self.root_package.find_by_id("3") self.assertEqual(UMLClass, type(res)) self.assertEqual("class1", res.name) def test_string_to_multiplicity(self): assoc = UMLAssociation(self.root_package, self.root_package.children[0].classes[0], self.root_package.children[0].classes[0], 1) self.assertEqual(assoc.string_to_multiplicity("0..1"), ("0", "1")) self.assertEqual(assoc.string_to_multiplicity("0..*"), ("0", "*")) self.assertEqual(assoc.string_to_multiplicity("*..1"), ("*", "1")) def test_association_type(self): assoc = UMLAssociation(self.root_package, self.root_package.children[0].classes[0], self.root_package.children[0].classes[0], 1) assoc.source_multiplicity = ("0", "1") assoc.destination_multiplicity = ("0", "*") self.assertEqual(assoc.association_type, "OneToMany") assoc.source_multiplicity = ("0", "1") assoc.destination_multiplicity = ("0", "1") self.assertEqual(assoc.association_type, "OneToOne") assoc.source_multiplicity = ("0", "*") assoc.destination_multiplicity = ("0", "1") self.assertEqual(assoc.association_type, "ManyToOne")
def association_parse(package: UMLPackage, element, root): id = element.get("id") cell = element.find("mxCell") source: UMLClass = package.find_by_id(cell.get("source")) target: UMLClass = package.find_by_id(cell.get("target")) element_type = element.get("UMLType") association = UMLAssociation(package, source, target, id, UMLAssociationType[element_type.upper()]) # Extract multiplicities ret = root.findall('.//object[@UMLType="DestinationMultiplicity"]') for dest in ret: dm = dest.find('mxCell[@parent="{}"]'.format(association.id)) if dm is not None: label = dest.get("label").strip('<div>').strip('</div>') association.destination_multiplicity = association.string_to_multiplicity( label) break ret = root.findall('.//object[@UMLType="SourceMultiplicity"]') for dest in ret: dm = dest.find('mxCell[@parent="{}"]'.format(association.id)) if dm is not None: label = dest.get("label").strip('<div>').strip('</div>') association.source_multiplicity = association.string_to_multiplicity( label) break # Set association destination name destination_name = element.get("destination_name") if destination_name is not None: association.destination_name = destination_name else: association.destination_name = target.name if association.source_multiplicity[ 1] == '*' and association.association_type == UMLAssociationType.ASSOCIATION: association.destination_name += 's' elif association.destination_multiplicity[ 1] == '*' and association.association_type == UMLAssociationType.COMPOSITION: association.destination_name += 's' # Set association source name source_name = element.get("source_name") if source_name is not None: association.source_name = source_name else: association.source_name = source.name if association.destination_multiplicity[ 1] == '*' and association.association_type == UMLAssociationType.ASSOCIATION: association.source_name += 's' if association.source_multiplicity[ 1] == '*' and association.association_type == UMLAssociationType.COMPOSITION: association.source_name += 's'
def setUp(self): self.tree = etree.fromstring(""" <xmi:XMI xmi:version="2.1" xmlns:uml="http://schema.omg.org/spec/UML/2.1" xmlns:xmi="http://schema.omg.org/spec/XMI/2.1" xmlns:thecustomprofile="http://www.sparxsystems.com/profiles/thecustomprofile/1.0"> <packagedElement xmi:type="uml:Association" xmi:id="EAID_3CFEE303_0F7B_46c6_81DE_D14F1BED8EA7" visibility="public"> <memberEnd xmi:idref="EAID_dstFEE303_0F7B_46c6_81DE_D14F1BED8EA7"/> <memberEnd xmi:idref="EAID_srcFEE303_0F7B_46c6_81DE_D14F1BED8EA7"/> <ownedEnd xmi:type="uml:Property" xmi:id="EAID_srcFEE303_0F7B_46c6_81DE_D14F1BED8EA7" visibility="public" association="EAID_3CFEE303_0F7B_46c6_81DE_D14F1BED8EA7" isStatic="false" isReadOnly="false" isDerived="false" isOrdered="false" isUnique="true" isDerivedUnion="false" aggregation="composite"> <type xmi:idref="EAID_DEFD1F62_622E_479b_8CB9_E219E818F917"/> <lowerValue xmi:type="uml:LiteralInteger" xmi:id="EAID_LI000003__0F7B_46c6_81DE_D14F1BED8EA7" value="0"/> <upperValue xmi:type="uml:LiteralUnlimitedNatural" xmi:id="EAID_LI000004__0F7B_46c6_81DE_D14F1BED8EA7" value="-1"/> </ownedEnd> </packagedElement> </xmi:XMI>""") self.package = UMLPackage("id", "name") self.source = UMLClass(self.package, "source", "id") self.dest = UMLClass(self.package, "dest", "id")
def setUp(self): self.tree = etree.fromstring(""" <xmi:XMI xmi:version="2.1" xmlns:uml="http://schema.omg.org/spec/UML/2.1" xmlns:xmi="http://schema.omg.org/spec/XMI/2.1" xmlns:thecustomprofile="http://www.sparxsystems.com/profiles/thecustomprofile/1.0"> <packagedElement xmi:type="uml:Class" xmi:id="EAID_5A9CB912_F283_41ae_9E4D_D73598C576AE" name="ExternalReference" visibility="public" isAbstract="true"> </packagedElement> <element xmi:idref="EAID_5A9CB912_F283_41ae_9E4D_D73598C576AE" xmi:type="uml:Class" name="ExternalReference" scope="public"> <model package="EAPK_EA154075_33FD_455d_B07A_FCBD08A7882D" tpos="0" ea_localid="664" ea_eleType="element"/> <properties isSpecification="false" sType="Class" nType="0" scope="public" isRoot="false" isLeaf="false" isAbstract="true" isActive="false"/> <project author="atkinp" version="1.0" phase="1.0" created="2019-07-24 08:42:52" modified="2020-06-23 19:23:20" complexity="1" status="Proposed"/> <code gentype="Java"/> <style appearance="BackColor=-1;BorderColor=-1;BorderWidth=-1;FontColor=-1;VSwimLanes=1;HSwimLanes=1;BorderStyle=0;"/> <tags/> <xrefs/> <extendedProperties tagged="0" package_name="Common"/> </element> </xmi:XMI>""") self.package = UMLPackage("id", "name")
def package_parse(element, root_element, parent_package): """ Extract package details, call class parser for classes and self parser for sub-packages. Associations are not done here, but in a 2nd pass using the parse_associations function. :param element: :param root_element: :return: :rtype: UMLPackage """ name = element.get('name') id = element.get('{%s}id' % ns['xmi']) package = UMLPackage(id, name, parent_package) package._element = element package._root_element = root_element # Detail is Sparx specific # TODO: Put modelling tool in settings and use tool specific parser here detail = root_element.xpath("//element[@xmi:idref='%s']" % package.id, namespaces=ns)[0] properties = detail.find('properties') package.stereotype = properties.get('stereotype') if package.stereotype is not None: package.inherited_stereotypes.append([package.stereotype, package]) package.documentation = properties.get('documentation') if package.documentation is None: package.documentation = "" project = detail.find('project') package.status = project.get('status') diagram_elements = root_element.xpath( "//diagrams/diagram/model[@package='%s']" % package.id) for diagram_model in diagram_elements: diagram = diagram_model.getparent() package.diagrams.append(diagram.get('{%s}id' % ns['xmi'])) logger.debug("Added UMLPackage {}".format(package.path)) package_parse_children(element, package) return package
def setUp(self): self.tree = etree.fromstring(""" <xmi:XMI xmi:version="2.1" xmlns:uml="http://schema.omg.org/spec/UML/2.1" xmlns:xmi="http://schema.omg.org/spec/XMI/2.1" xmlns:thecustomprofile="http://www.sparxsystems.com/profiles/thecustomprofile/1.0"> <ownedAttribute xmi:type="uml:Property" xmi:id="EAID_7EBDF95C_3A97_4163_A683_3ACC3CF507E4" name="system" visibility="private" isStatic="false" isReadOnly="false" isDerived="false" isOrdered="false" isUnique="true" isDerivedUnion="false"> <type xmi:idref="EAJava_int"/> </ownedAttribute> <attribute xmi:idref="EAID_7EBDF95C_3A97_4163_A683_3ACC3CF507E4" name="id" scope="Private"> <initial/> <documentation/> <model ea_localid="1213" ea_guid="{47318F66-BBA6-4e9f-9045-83B2E12E25C8}"/> <properties type="int" precision="0" collection="false" length="0" static="0" duplicates="0" changeability="changeable"/> <coords ordered="0" scale="0"/> <containment containment="Not Specified" position="0"/> <stereotype/> <bounds lower="1" upper="1"/> <options/> <style/> <styleex value="volatile=0;"/> <tags/> <xrefs value="$XREFPROP=$XID={EA9F1375-D590-4c2b-8721-DC0B55BFE4A9}$XID;$NAM=CustomProperties$NAM;$TYP=attribute property$TYP;$VIS=Public$VIS;$PAR=0$PAR;$DES=@PROP=@NAME=isID@ENDNAME;@TYPE=Boolean@ENDTYPE;@VALU=1@ENDVALU;@PRMT=@ENDPRMT;@ENDPROP;$DES;$CLT={47318F66-BBA6-4e9f-9045-83B2E12E25C8}$CLT;$SUP=<none>$SUP;$ENDXREF;"/> </attribute> </xmi:XMI>""") self.package = UMLPackage("id", "name") self.parent = UMLClass(self.package, "name", "id")
def setUp(self): self.root_package = UMLPackage("1", "root") child = UMLPackage("2", "child1", self.root_package) self.root_package.children.append(child) cls = UMLClass(child, "class1", "3") child.classes.append(cls)
def generalization_parse(package: UMLPackage, element, root): cell = element.find("mxCell") source: UMLClass = package.find_by_id(cell.get("source")) target: UMLClass = package.find_by_id(cell.get("target")) source.generalization = target
class TestUMLModel(unittest.TestCase): def setUp(self): self.root_package = UMLPackage("1", "root") child = UMLPackage("2", "child1", self.root_package) self.root_package.children.append(child) cls = UMLClass(child, "class1", "3") child.classes.append(cls) def test_find_package(self): res = self.root_package.find_by_id("2") self.assertEqual(UMLPackage, type(res)) self.assertEqual("child1", res.name) def test_find_class(self): res = self.root_package.find_by_id("3") self.assertEqual(UMLClass, type(res)) self.assertEqual("class1", res.name) def test_string_to_multiplicity(self): assoc = UMLAssociation(self.root_package, self.root_package.children[0].classes[0], self.root_package.children[0].classes[0], 1) self.assertEqual(assoc.string_to_multiplicity("0..1"), ("0", "1")) self.assertEqual(assoc.string_to_multiplicity("0..*"), ("0", "*")) self.assertEqual(assoc.string_to_multiplicity("*..1"), ("*", "1")) def test_association_cardinality(self): assoc = UMLAssociation(self.root_package, self.root_package.children[0].classes[0], self.root_package.children[0].classes[0], 1) assoc.source_multiplicity = ("0", "1") assoc.destination_multiplicity = ("0", "*") self.assertEqual(assoc.cardinality, Cardinality.ONE_TO_MANY) assoc.source_multiplicity = ("0", "1") assoc.destination_multiplicity = ("0", "1") self.assertEqual(assoc.cardinality, Cardinality.ONE_TO_ONE) assoc.source_multiplicity = ("0", "*") assoc.destination_multiplicity = ("0", "1") self.assertEqual(assoc.cardinality, Cardinality.MANY_TO_ONE) assoc.source_multiplicity = ("0", "*") assoc.destination_multiplicity = ("0", "*") self.assertEqual(assoc.cardinality, Cardinality.MANY_TO_MANY) def test_association_type(self): assoc = UMLAssociation(self.root_package, self.root_package.children[0].classes[0], self.root_package.children[0].classes[0], 1) self.assertEqual(assoc.association_type, UMLAssociationType.ASSOCIATION) assoc = UMLAssociation(self.root_package, self.root_package.children[0].classes[0], self.root_package.children[0].classes[0], 1, UMLAssociationType.COMPOSITION) self.assertEqual(assoc.association_type, UMLAssociationType.COMPOSITION) def test_attribute_type(self): attr = UMLAttribute(None, "test", 123) attr.set_type('String') self.assertEqual(attr.dest_type, 'CharField') attr.set_type('String (123)') self.assertEqual(attr.dest_type, 'CharField') self.assertEqual(attr.length, 123) attr.set_type('decimal (12,2)') self.assertEqual(attr.dest_type, 'DecimalField') self.assertEqual(attr.precision, 12) self.assertEqual(attr.scale, 2) def test_attribute_get_type(self): attr = UMLAttribute(None, "test", 123) attr.set_type('String') self.assertEqual(attr.get_type('default'), 'string')