-
Notifications
You must be signed in to change notification settings - Fork 0
/
import_scn.py
379 lines (329 loc) · 13.9 KB
/
import_scn.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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
import re
model = modelingSession.getModel()
def select_scn_file():
from org.eclipse.swt.widgets import Display, FileDialog, Shell
from org.eclipse.swt import SWT
display = Display.getDefault().getActiveShell()
shell = Shell(display)
fd = FileDialog(shell, SWT.OPEN)
fd.setText('Open')
filterExt = ['*.scn', '*.*']
fd.setFilterExtensions(filterExt)
return fd.open()
def import_tree(scn_file, pkg):
t = TextualTreeReader(scn_file).getTextualTree()
#print len(tree.getChildren())
for c in t.getChildren():
name = c.getHeadline()
if name.split()[0] in ['e', 'enum']:
create_enum(c, pkg)
else:
create_class(c, pkg)
def add_comments(elem, children):
description = ''
summary = ''
for c in children:
if c.getHeadline()[:3] is 'D: ':
description += c.getHeadline()[3:] + '\n'
elif c.getHeadline()[:3] is 'S: ':
summary += c.getHeadline()[3:] + '\n'
# i dont know what the first parameter is supposed to be
# https://www.modelio.org/documentation/javadoc-3.1/org/modelio/metamodel/uml/infrastructure/ModelElement.html#putNoteContent(java.lang.String, java.lang.String, java.lang.String)
if summary: elem.putNoteContent('org.modelio.module.modelermodule.impl.ModelerModuleModule', 'summary', summary)
if description: elem.putNoteContent('org.modelio.module.modelermodule.impl.ModelerModuleModule', 'description', description)
def ignore_line(line):
return line.split()[0] in ['D:', 'S:', 'd:', 's:']
def is_role(line):
split = line.replace(' ', '').split(':')
try:
if split[1].split('[')[0] in basicTypes: return False
except:
return False
return True
def is_attribute(line):
return not is_operation(line) and not is_role(line)
def is_operation(line):
return '()' in line
basicTypes = ['string', 's', 'integer', 'i', 'float', 'f', 'boolean', 'b', 'date', 'd']
types = {'s': model.getUmlTypes().getSTRING(),
'i': model.getUmlTypes().getINTEGER(),
'f': model.getUmlTypes().getFLOAT(),
'b': model.getUmlTypes().getBOOLEAN(),
'd': model.getUmlTypes().getDATE()}
visi = {'+': VisibilityMode.PUBLIC,
'-': VisibilityMode.PRIVATE,
'#': VisibilityMode.PROTECTED,
'~': VisibilityMode.PACKAGEVISIBILITY}
rkind = {'<#>': AggregationKind.KINDISCOMPOSITION,
'<>': AggregationKind.KINDISAGGREGATION}
def create_class(node, pkg):
trans = modelingSession.createTransaction("Class creation")
try:
name = node.getHeadline()
abstract = name.split()[0] in ['a', 'abstract']
if abstract:
cla = model.createClass(name.split()[1], pkg)
cla.setIsAbstract(abstract)
else:
cla = model.createClass(name.split()[0], pkg)
add_comments(cla, node.getChildren())
for c in node.getChildren():
line = c.getHeadline()
if not ignore_line(line):
if is_attribute(line):
line = line.replace(' ', '') # on vire les espaces
att = model.createAttribute()
att.setOwner(cla)
if line[0] is '/':
att.setIsDerived(True)
line = line[1:]
visibility = visi[line[:1]] if line[:1] in visi.keys() else visi['+']
att.setVisibility(visibility)
for v in visi.keys(): line = line.replace(v, '') # on vire la visibilité
name = line.split(':')
att.setName(name[0])
try:
typeregex = r'^(\w*)(\[.*\])?$'
typematch = re.match(typeregex, name[1])
if typematch:
if typematch.group(1): # on a un type
att.setType(types[typematch.group(1)[0]])
if typematch.group(2): # on a une carinalité
card = typematch.group(2)
cardregex = r'^\[(.*?)(?:\.\.(.*?))?\]$'
cardmatch = re.match(cardregex, card)
if cardmatch:
mini = cardmatch.group(1)
maxi = cardmatch.group(2)
if not maxi:
maxi = mini
att.setMultiplicityMin(mini)
att.setMultiplicityMax(maxi)
except:
pass
elif is_operation(line):
op = model.createOperation()
op.setOwner(cla)
abstract = line.split()[0] in ['a', 'abstract']
line = line.replace(' ', '') # on vire les espaces
if abstract:
op.setIsAbstract(abstract)
line = line.split(num=1)[1]
if line[0] is '/':
op.setIsDerived(True)
line = line[1:]
visibility = visi[line[:1]] if line[:1] in visi.keys() else visi['+']
op.setVisibility(visibility)
name = line.split('()')
op.setName(name[0])
pass
elif is_role(line):
pass
trans.commit()
except:
trans.rollback()
raise
def create_enum(node, pkg):
trans = modelingSession.createTransaction("Enum creation")
try:
name = node.getHeadline()
enum = model.createEnumeration(name.split()[1], pkg)
add_comments(enum, node.getChildren())
for c in node.getChildren():
if not ignore_line(c.getHeadline()):
lit = model.createEnumerationLiteral(c.getHeadline(), enum)
trans.commit()
except:
trans.rollback()
raise
#----------------------------------------------------------------------------
# textual_tree
#----------------------------------------------------------------------------
# Support for reading trees represented as nested lines.
#
# Licence: LGPL
# Author: jmfavre
#
# History
# Version 1.0 - March 22, 2014
# - first version. Line numbering not implemented yet.
#
#--- Tree ---
# Simple tree structure where each node has the following elements:
# - "headline" : a (possibly multiline) string corresponding to
# the main content of the node.
# - "children" : a list of subtrees. This list is empty for leaves.
# - "parent" : the parent of a node or None for the root.
# Note that the subclass TextualTree possess additional elements
class Tree(object):
#-- main interface
def getHeadline(self): return self.headline
def getChildren(self): return self.children
def getParent(self): return self.parent
def hasChildren(self): return len(self.children) > 0
def getLastChild(self): return self.children[len(self.children) - 1]
def getLastNode(self):
if self.hasChildren():
return self.getLastChild().getLastNode()
else:
return self
#-- update interface
def addChild(self, tree):
self.children = self.children + [tree]
def __init__(self, headline=None, children=[], parent=None):
self.headline = headline
self.children = children
self.parent = parent
for child in children:
child.parent = self
#--- TextualTree ---
# This class enables to deal textual representation of trees.
# Additionnaly to the "Tree" structure the following elements
# are added on each node:
# - "indent" : a integer value corresponding to the indentation
# - "comment" : a potentially multiline string corresponding to
# the comments appearing before the node
class TextualTree(Tree):
#-- main interface
def getIndent(self): return self.indent
def getComment(self): return self.comment
def getLineNumber(self): return self.lineNumber
# update interface
def __init__(self, lineNumber=None, indent=None, comment=None, headline=None, children=[], parent=None):
Tree.__init__(self, headline, children, parent)
self.indent = indent
self.comment = comment
self.lineNumber = lineNumber
def setLineNumber(self, lineNum): self.lineNumber = lineNum
def setIndent(self, indent): self.indent = indent
def setComment(self, comment): self.comment = comment
def searchTree(self, indent):
""" Search for the last tree matching this indent
"""
if self.indent == indent:
return self
elif self.hasChildren():
return self.getLastChild().searchTree(indent)
else:
return None
def addLine(self, lineNumber, indent, comment, headline):
# print "addLine("+str(indent)+headline+")"
lastNode = self.getLastNode()
# print "indent is ",indent
if indent == lastNode.getIndent():
# same level as the last node
parent = lastNode.getParent()
# print " same level as "+("root" if parent.headline is None else
# parent.headline)
elif indent > lastNode.getIndent():
# this is a new nesting
parent = lastNode
# print " nested level in "+("root" if parent.headline is None else
# parent.headline)
else:
# search in previous open nestings
sameLevelNode = self.searchTree(indent)
if sameLevelNode is None:
print "***error*** cannot find node with nesting " + str(indent)
parent = sameLevelNode.getParent()
# print " previous nesting, added in "+("root" if parent.headline is None
# else parent.headline)
node = TextualTree(lineNumber, indent, comment, headline, [], parent)
parent.children += [node]
def text(self):
if self.headline is None or self.indent is None:
out = ""
else:
if self.comment is None or self.comment == "":
out = ""
else:
self.comment + "\n"
out += (" " * self.indent) + self.headline + "\n"
for child in self.children:
out += child.text()
return out
def toList(self):
if self.headline is None or self.indent is None:
out = ""
else:
out = self.headline
for child in self.children:
out += "(" + child.toList() + " )"
return out
class TextualTreeReader(object):
def __init__(self, linesOrFilename):
""" Create the tree from a file or a list of lines.
"""
if isinstance(linesOrFilename, basestring):
lines = [line.strip("\n") for line in open(linesOrFilename)]
else:
lines = linesOrFilename
self.rawLines = lines
self.structuredLines = None
def _getStructuredLines(self):
import re
if self.structuredLines is not None:
return self.structuredLines
else:
self.structuredLines = []
commentRE = r"^ *(--.*)?$"
indentedRE = r"^( *)(.*)$"
continuationRE = r"^ *: ?(.*)$"
index = 0
comment = ""
headline = None
indentString = None
for rawLine in self.rawLines:
matchComment = re.match(commentRE, rawLine)
if matchComment:
#-- This is a comment line
if headline is not None:
# the previous headline is now finished
self._addLine(comment, indentString, headline)
headline = None
comment = ""
# In all cases add the comment line to the comment
comment += ("" if comment == "" else "\n") + matchComment.group()
else:
matchContinuation = re.match(continuationRE, rawLine)
if matchContinuation:
#-- This is a continuation line
if headline is not None:
# Add the continuation to the headline
headline += "\n" + matchContinuation.group(1)
else:
# Ignore the continuation
pass
else:
matchIndentedLine = re.match(indentedRE, rawLine)
# There is always a match given the pattern
#-- this is neither a comment, nor a continuation, hence a headline
if headline is not None:
# After a headline. Push this one to the list.
self._addLine(comment, indentString, headline)
comment = ""
indentString = matchIndentedLine.group(1)
headline = matchIndentedLine.group(2)
if headline is not None:
self._addLine(comment, indentString, headline)
return self.structuredLines
def _addLine(self, comment, indentString, headline):
self.structuredLines += [(comment, len(indentString), headline)]
def getTextualTree(self):
tree = TextualTree(-1, -1)
lines = self._getStructuredLines()
for (comment, indent, headline) in lines:
tree.addLine(-1, indent, comment, headline)
return tree
if len(selectedElements) == 1:
elem=selectedElements[0]
if not isinstance(elem, Package):
print 'Please select a package first, aborting.'
else :
scn_file = select_scn_file()
if scn_file:
import_tree(scn_file, elem)
else:
print 'No file selected, aborting.'
else:
print 'Please select only one package, aborting.'