-
Notifications
You must be signed in to change notification settings - Fork 0
/
archiToOFN.py
151 lines (146 loc) · 7.51 KB
/
archiToOFN.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
import sys
import archiBindings
from lxml import etree
from ofnClasses import ClassType, Relationship, Trope, Vocabulary, Term, VocabularyType, getClass, getTrope
from outputToRDF import convertToRDF
# TODO: Security!!!
# TODO: Support multiple vocabularies?
# ARCHIMATE_NAMESPACE = 'http://www.w3.org/2001/XMLSchema-instance'
inputLocation = sys.argv[1]
outputLocation = sys.argv[2]
propertyDefinitions = {}
with open(inputLocation, "r", encoding="utf-8") as inputFile:
tree = etree.parse(inputLocation, parser=etree.XMLParser())
root = tree.getroot()
vocabularyNameElement = root.find(
"{http://www.opengroup.org/xsd/archimate/3.0/}name")
vocabularyName: str = "slovník"
defaultLanguage: str = "cs"
if vocabularyNameElement is not None:
vocabularyName = vocabularyNameElement.text
else:
raise LookupError(
"Cannot find model name. Are you sure you are passing an Archi export?")
vocabulary = Vocabulary()
defaultLanguage = vocabularyNameElement.attrib['{http://www.w3.org/XML/1998/namespace}lang']
vocabulary.name[defaultLanguage] = vocabularyName
properties = root.findall(
".//{http://www.opengroup.org/xsd/archimate/3.0/}propertyDefinition[@identifier]")
elements = root.findall(
".//{http://www.opengroup.org/xsd/archimate/3.0/}element[@{http://www.w3.org/2001/XMLSchema-instance}type]")
relationships = root.findall(
".//{http://www.opengroup.org/xsd/archimate/3.0/}relationship[@{http://www.w3.org/2001/XMLSchema-instance}type]")
for property in properties:
name = property.find(
".//{http://www.opengroup.org/xsd/archimate/3.0/}name")
propertyDefinitions[property.attrib['identifier']
] = getattr(name, "text", "name")
for element in elements:
if element.attrib['{http://www.w3.org/2001/XMLSchema-instance}type'] == "BusinessObject":
term = Term()
term.id = element.attrib['identifier']
# Name
names = element.findall(
"{http://www.opengroup.org/xsd/archimate/3.0/}name")
for name in names:
lang = name.attrib['{http://www.w3.org/XML/1998/namespace}lang']
term.name[lang] = name.text
# Properties
termProperties: dict[str, tuple[str, str]] = {}
termPropertyElements = element.findall(
".//{http://www.opengroup.org/xsd/archimate/3.0/}property")
for termPropertyElement in termPropertyElements:
identifier = termPropertyElement.attrib['propertyDefinitionRef']
value = termPropertyElement.find(
"{http://www.opengroup.org/xsd/archimate/3.0/}value")
valueLang = value.attrib['{http://www.w3.org/XML/1998/namespace}lang']
valueText = value.text
propertyType = propertyDefinitions[identifier]
termProperties[propertyType] = (valueText, valueLang)
if archiBindings.OFN_TYPE in termProperties and termProperties[archiBindings.OFN_TYPE][0] is not None:
valueTextNormalized = termProperties[archiBindings.OFN_TYPE][0].strip(
).lower()
match valueTextNormalized:
case archiBindings.OFN_SUBJECT_TYPE:
term = getClass(term)
term.type = ClassType.SUBJECT
case archiBindings.OFN_OBJECT_TYPE:
term = getClass(term)
term.type = ClassType.OBJECT
case archiBindings.OFN_TROPE_TYPE:
term = getTrope(term)
# Source
if archiBindings.OFN_RELATION in termProperties:
term.source = termProperties[archiBindings.OFN_RELATION][0]
# Definition
if archiBindings.OFN_DEFINITION in termProperties:
term.definition[termProperties[archiBindings.OFN_DEFINITION]
[1]] = termProperties[archiBindings.OFN_DEFINITION][0]
# Description
if archiBindings.OFN_DESCRIPTION in termProperties:
term.description[termProperties[archiBindings.OFN_DESCRIPTION]
[1]] = termProperties[archiBindings.OFN_DESCRIPTION][0]
if archiBindings.OFN_DATATYPE in termProperties and isinstance(term, Trope):
term.datatype = termProperties[archiBindings.OFN_DATATYPE][0]
vocabulary.terms.append(term)
for relationship in relationships:
identifier = relationship.attrib['identifier']
domain = relationship.attrib['source']
range = relationship.attrib['target']
domainTerm = None
rangeTerm = None
for term in vocabulary.terms:
if term.id == domain:
domainTerm = term
if term.id == range:
rangeTerm = term
if domainTerm is not None and rangeTerm is not None:
break
relationshipType = relationship.attrib['{http://www.w3.org/2001/XMLSchema-instance}type']
if domainTerm is None or rangeTerm is None:
continue
if relationshipType == "Specialization":
domainTerm.subClassOf.append(rangeTerm.iri)
elif relationshipType == "Composition" and isinstance(rangeTerm, Trope):
rangeTerm.target = domainTerm.iri
elif relationshipType == "Association":
isDirected = relationship.attrib.get("isDirected", False)
if not isDirected or isDirected != "true":
continue
term = Relationship(domainTerm.getIRI(
vocabulary, defaultLanguage), rangeTerm.getIRI(vocabulary, defaultLanguage))
term.id = identifier
# Name
names = relationship.findall(
"{http://www.opengroup.org/xsd/archimate/3.0/}name")
for name in names:
lang = name.attrib['{http://www.w3.org/XML/1998/namespace}lang']
term.name[lang] = name.text
# Properties
termPropertyElements = relationship.findall(
".//{http://www.opengroup.org/xsd/archimate/3.0/}property")
for termPropertyElement in termPropertyElements:
identifier = termPropertyElement.attrib['propertyDefinitionRef']
value = termPropertyElement.find(
".//{http://www.opengroup.org/xsd/archimate/3.0/}value")
valueLang = value.attrib['{http://www.w3.org/XML/1998/namespace}lang']
valueText = value.text
propertyType = propertyDefinitions[identifier]
match propertyType:
# Not interested in type
# Source
case archiBindings.OFN_RELATION:
term.source = valueText
# Definition
case archiBindings.OFN_DEFINITION:
term.definition[valueLang] = valueText
# Description
case archiBindings.OFN_DESCRIPTION:
term.description[valueLang] = valueText
for name in names:
lang = name.attrib['{http://www.w3.org/XML/1998/namespace}lang']
term.name[lang] = name.text
vocabulary.terms.append(term)
if (next(x for x in vocabulary.terms if isinstance(x, Trope) or isinstance(x, Relationship))):
vocabulary.type = VocabularyType.CONCEPTUAL_MODEL
convertToRDF(vocabulary, "cs", outputLocation)