mwgencode 1.4.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- gencode/__init__.py +140 -0
- gencode/dd_models.py +256 -0
- gencode/ext.py +19 -0
- gencode/gen_code.py +343 -0
- gencode/gencode/__init__.py +0 -0
- gencode/gencode/export_class2swgclass.py +206 -0
- gencode/gencode/gen_bo_models_code.py +719 -0
- gencode/gencode/gen_state_code.py +171 -0
- gencode/gencode/gen_swagger_code.py +94 -0
- gencode/gencode/gen_tests_code.py +113 -0
- gencode/gencode/sample/__init__.py +2 -0
- gencode/gencode/sample/babel.cfg +3 -0
- gencode/gencode/sample/config-sample.ini +9 -0
- gencode/gencode/sample/config.ini +14 -0
- gencode/gencode/sample/create_new_table_run.pys +19 -0
- gencode/gencode/sample/dockerignore.dock +57 -0
- gencode/gencode/sample/file_utils.pys +396 -0
- gencode/gencode/sample/gencode.xmi +33 -0
- gencode/gencode/sample/gitignore.git +14 -0
- gencode/gencode/sample/migrate_run.bat +5 -0
- gencode/gencode/sample/migrate_run.pys +9 -0
- gencode/gencode/sample/requirements.txt +17 -0
- gencode/gencode/sample/run.sh +27 -0
- gencode/gencode/sample/seeds/__init__.py +0 -0
- gencode/gencode/sample/seeds/models_rm.pys +187 -0
- gencode/gencode/sample/seeds/seed_dev_data.pys +21 -0
- gencode/gencode/sample/seeds/seed_init.pys +17 -0
- gencode/gencode/sample/seeds/seed_rm.pys +39 -0
- gencode/gencode/sample/seeds/seed_run.pys +13 -0
- gencode/gencode/sample/seeds/seed_utils.pys +23 -0
- gencode/gencode/sample/test__init__.pys +6 -0
- gencode/gencode/sample/test_run.pys +4 -0
- gencode/gencode/sample/utils.pys +92 -0
- gencode/gencode/template/Dockerfile.tmp +55 -0
- gencode/gencode/template/README.md +91 -0
- gencode/gencode/template/__init__.py +0 -0
- gencode/gencode/template/__init__.pys +99 -0
- gencode/gencode/template/config.pys +134 -0
- gencode/gencode/template/default.conf +21 -0
- gencode/gencode/template/docker-compose-dev.yaml +52 -0
- gencode/gencode/template/docker-compose.yaml +55 -0
- gencode/gencode/template/drone.tmp +45 -0
- gencode/gencode/template/flask_models.pys +107 -0
- gencode/gencode/template/flask_models_base.pys +159 -0
- gencode/gencode/template/gen_code_flask.yaml +21 -0
- gencode/gencode/template/gen_code_run.pys +28 -0
- gencode/gencode/template/k8s-tmp.yml +141 -0
- gencode/gencode/template/run.pys +52 -0
- gencode/gencode/template/sample.mdj +1193 -0
- gencode/gencode/template/setup.tmp +48 -0
- gencode/gencode/template/supervisord.conf +21 -0
- gencode/gencode/template/swagger_file.yaml +195 -0
- gencode/gencode/template/swg_class.tmp +41 -0
- gencode/gencode/template/swg_ctrl_code.pys +130 -0
- gencode/gencode/template/swg_package_mng.tmp +4423 -0
- gencode/gencode/template/test_test_base.tmp +34 -0
- gencode/gencode/template/tests/__init__.py +0 -0
- gencode/gencode/template/tests/__init__.pys +5 -0
- gencode/gencode/template/tests/init_test_data.pys +80 -0
- gencode/gencode/template/tests/run.pys +4 -0
- gencode/gencode/template/tests/test_base.pys +87 -0
- gencode/gencode/template/tests/test_classmng.pys +58 -0
- gencode/gencode/template/uwsgi.ini +20 -0
- gencode/gencode/template/uwsgi_run.pys +44 -0
- gencode/importmdj/__init__.py +0 -0
- gencode/importmdj/import_dd_classes.py +369 -0
- gencode/importmdj/import_swagger2_class.py +371 -0
- gencode/importmdj/import_uml_models.py +466 -0
- gencode/importxmi/__init__.py +1 -0
- gencode/importxmi/import_classes.py +342 -0
- gencode/importxmi/import_sequences.py +291 -0
- gencode/importxmi/import_states.py +150 -0
- gencode/importxmi/import_swagger.py +151 -0
- gencode/swg2_class_models.py +179 -0
- gencode/uml_class_models.py +295 -0
- gencode/upgrade.py +113 -0
- gencode/utils.py +225 -0
- manage.py +194 -0
- mwgencode-1.4.1.dist-info/METADATA +325 -0
- mwgencode-1.4.1.dist-info/RECORD +84 -0
- mwgencode-1.4.1.dist-info/WHEEL +5 -0
- mwgencode-1.4.1.dist-info/entry_points.txt +2 -0
- mwgencode-1.4.1.dist-info/licenses/LICENSE.txt +19 -0
- mwgencode-1.4.1.dist-info/top_level.txt +2 -0
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
try: # 导入模块
|
|
2
|
+
import xml.etree.cElementTree as ET
|
|
3
|
+
except ImportError:
|
|
4
|
+
import xml.etree.ElementTree as ET
|
|
5
|
+
from gencode.dd_models import *
|
|
6
|
+
from gencode.ext import Session,engine
|
|
7
|
+
|
|
8
|
+
from gencode.utils import Keytype,FieldFrom,DBDataType,DBDataType_len,convert2dbType
|
|
9
|
+
uml="http://schema.omg.org/spec/UML/2.0"
|
|
10
|
+
xmi="{http://schema.omg.org/spec/XMI/2.1}"
|
|
11
|
+
_id = xmi+"id"
|
|
12
|
+
_type = xmi+"type"
|
|
13
|
+
_extension = xmi+'Extension'
|
|
14
|
+
|
|
15
|
+
class ImportModels():
|
|
16
|
+
def __init__(self,underline=False,isIntID=False):
|
|
17
|
+
'''
|
|
18
|
+
:param underline: Id 为int 时,如果underline 为True 则关联id前加下划线
|
|
19
|
+
:param isIntID: True为没有指定类型时为int id
|
|
20
|
+
'''
|
|
21
|
+
self.database = None
|
|
22
|
+
self.tables = {}
|
|
23
|
+
self.roles = []
|
|
24
|
+
self.underline = underline
|
|
25
|
+
self.isIntID = isIntID
|
|
26
|
+
|
|
27
|
+
def _create_db(self,dbname,dbdesc):
|
|
28
|
+
database = Databasedictionary()
|
|
29
|
+
database.name = dbname
|
|
30
|
+
database.description = dbdesc
|
|
31
|
+
database.id = 'dbid'
|
|
32
|
+
self.session = Session()
|
|
33
|
+
return database
|
|
34
|
+
# self.session.add(db)
|
|
35
|
+
|
|
36
|
+
def _create_tb(self, cls):
|
|
37
|
+
# print(' ')
|
|
38
|
+
# print(' class:', cls.attrib)
|
|
39
|
+
if cls.attrib.get('isAbstract', 'false') != 'false':
|
|
40
|
+
return
|
|
41
|
+
table = Tabledictionary()
|
|
42
|
+
table.databasedictionaryid = self.database.id
|
|
43
|
+
table.tablename = cls.attrib.get('name', None).lower().replace(' ','')
|
|
44
|
+
table.id = cls.attrib.get(_id, None)
|
|
45
|
+
# print('class name',tb.attrib.get('name',None))
|
|
46
|
+
extens = cls.find(_extension)
|
|
47
|
+
if extens is not None:
|
|
48
|
+
# print(' extens:',extens.attrib)
|
|
49
|
+
cls_doc = extens.find('documentation')
|
|
50
|
+
if cls_doc is not None:
|
|
51
|
+
# print(' doc:',cls_doc.attrib)
|
|
52
|
+
table.description = cls_doc.attrib.get('value','')
|
|
53
|
+
stereotype = extens.find('stereotype')
|
|
54
|
+
if stereotype is not None:
|
|
55
|
+
stereotype=stereotype.attrib.get('value','').split('/')
|
|
56
|
+
for stype in stereotype:
|
|
57
|
+
if stype.lower().startswith('map'):
|
|
58
|
+
# 如:customerid = map{c_id}
|
|
59
|
+
table.maptablename = stype[4:-1].lower()
|
|
60
|
+
break
|
|
61
|
+
return table
|
|
62
|
+
|
|
63
|
+
def _create_idfld(self,clsidvalue):
|
|
64
|
+
field = Fielddictionary()
|
|
65
|
+
field.id = clsidvalue
|
|
66
|
+
field.tabledictionaryid = clsidvalue
|
|
67
|
+
field.fieldname = 'id'
|
|
68
|
+
if self.isIntID:
|
|
69
|
+
field.fieldtype = DBDataType.int.value
|
|
70
|
+
field.fieldsize = DBDataType_len.int.value
|
|
71
|
+
else:
|
|
72
|
+
field.fieldtype = DBDataType.varchar.value
|
|
73
|
+
field.fieldsize = DBDataType_len.varchar.value
|
|
74
|
+
field.englishname = field.fieldname
|
|
75
|
+
field.othername = field.fieldname
|
|
76
|
+
field.keytype = Keytype.key.value
|
|
77
|
+
field.fieldfrom = FieldFrom.database.value
|
|
78
|
+
field.gb32name = field.fieldname
|
|
79
|
+
field.isallownull = False
|
|
80
|
+
return field
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def create_fnkeyfld(self,role):
|
|
84
|
+
if role.assocmulitplicity != 1 or not role.assocnavigable:
|
|
85
|
+
return None
|
|
86
|
+
# role = Roledictionary()
|
|
87
|
+
field = Fielddictionary()
|
|
88
|
+
field.id = role.id
|
|
89
|
+
field.tabledictionaryid = role.ownertableid
|
|
90
|
+
tb = self.session.query(Tabledictionary).filter_by(id=role.reftableid).first()
|
|
91
|
+
key_fld = tb.get_keyfield()
|
|
92
|
+
# # 如果是autoint 则采用_id,传统的用id
|
|
93
|
+
# get_id = lambda key_fld:'_id' if key_fld.fieldtype == 'int' and self.underline else 'id'
|
|
94
|
+
# if role.assocrolename:
|
|
95
|
+
# field.fieldname = (role.assocrolename +get_id(key_fld)).lower()
|
|
96
|
+
# else:
|
|
97
|
+
field.fieldname = role.get_role_id(self.session)
|
|
98
|
+
field.fieldtype = key_fld.fieldtype
|
|
99
|
+
field.fieldsize = key_fld.fieldsize
|
|
100
|
+
field.englishname = field.fieldname
|
|
101
|
+
field.othername = field.fieldname
|
|
102
|
+
field.keytype = Keytype.foreignkey.value
|
|
103
|
+
field.fieldfrom = FieldFrom.database.value
|
|
104
|
+
field.gb32name = field.fieldname
|
|
105
|
+
if role.req:
|
|
106
|
+
field.isallownull = False
|
|
107
|
+
return field
|
|
108
|
+
|
|
109
|
+
def _create_fld(self,attr,table):
|
|
110
|
+
field = Fielddictionary()
|
|
111
|
+
field.id = attr.attrib.get(_id)
|
|
112
|
+
field.tabledictionaryid = table.id
|
|
113
|
+
field.fieldname = attr.attrib.get('name').replace(' ','').lower()
|
|
114
|
+
field.fieldtype = convert2dbType(attr.attrib.get('type').split('_')[0])
|
|
115
|
+
type_s = attr.attrib.get('type').split('_')[0].lower().strip()
|
|
116
|
+
if type_s.startswith('string') and len(type_s)>6:
|
|
117
|
+
type_len = int(type_s[6:])
|
|
118
|
+
else:
|
|
119
|
+
type_len = DBDataType_len[field.fieldtype].value
|
|
120
|
+
field.fieldsize = type_len
|
|
121
|
+
field.englishname = field.fieldname
|
|
122
|
+
field.othername = field.fieldname
|
|
123
|
+
field.gb32name = field.fieldname
|
|
124
|
+
field.big5name = field.fieldname
|
|
125
|
+
if attr.attrib.get('isID') != 'false':
|
|
126
|
+
field.keytype = Keytype.key.value
|
|
127
|
+
else:
|
|
128
|
+
field.keytype = Keytype.notkey.value
|
|
129
|
+
if attr.attrib.get('isUnique') != 'false':
|
|
130
|
+
field.repfields = field.fieldname
|
|
131
|
+
field.fieldfrom = FieldFrom.database.value
|
|
132
|
+
lowv = attr.find('lowerValue')
|
|
133
|
+
if lowv is not None:
|
|
134
|
+
# print(' lv:', lowv.attrib)
|
|
135
|
+
field.fieldsize = int(lowv.attrib.get('value'))
|
|
136
|
+
upperv = attr.find('upperValue')
|
|
137
|
+
if upperv is not None:
|
|
138
|
+
# print(' uv:', upperv.attrib)
|
|
139
|
+
field.fieldsize = int(lowv.attrib.get('value'))
|
|
140
|
+
defaultv = attr.find('defaultValue')
|
|
141
|
+
if defaultv is not None:
|
|
142
|
+
# print(' dv:', defaultv.attrib)
|
|
143
|
+
field.defaultvalue = defaultv.attrib.get('value')
|
|
144
|
+
|
|
145
|
+
# print(' attr:', attr.attrib)
|
|
146
|
+
extens_attr = attr.find(_extension)
|
|
147
|
+
if extens_attr is not None:
|
|
148
|
+
attr_doc = extens_attr.find('documentation')
|
|
149
|
+
if attr_doc is not None:
|
|
150
|
+
# print(' doc:', attr_doc.attrib)
|
|
151
|
+
field.gb32name = attr_doc.attrib.get('value')
|
|
152
|
+
attr_stype = extens_attr.find('stereotype')
|
|
153
|
+
if attr_stype is not None:
|
|
154
|
+
# print(' stype:', attr_stype.attrib)
|
|
155
|
+
stypes = attr_stype.attrib.get('value').split('/')
|
|
156
|
+
for stype in stypes:
|
|
157
|
+
if stype.lower() == 'req':
|
|
158
|
+
field.isallownull = False
|
|
159
|
+
elif stype.lower() == 'rep':
|
|
160
|
+
field.repfields = field.fieldname.lower()
|
|
161
|
+
elif stype.lower().startswith('map'):
|
|
162
|
+
# 如:customerid = map{c_id}
|
|
163
|
+
field.mapname = stype[4:-1].lower()
|
|
164
|
+
elif stype.lower().startswith('rep'):
|
|
165
|
+
# 如:rep{id;name}
|
|
166
|
+
# stype[4:-1].split(';')=>['id','name']
|
|
167
|
+
stype_l = stype[4:-1].lower().split(';')
|
|
168
|
+
stype_l.append(field.fieldname)
|
|
169
|
+
field.repfields = ';'.join(stype_l)
|
|
170
|
+
elif stype.lower().startswith('plk'):
|
|
171
|
+
field.plkfieldcode = field.gb32name
|
|
172
|
+
field.plkfieldpath = stype[4:-1].lower()
|
|
173
|
+
field.fieldfrom = FieldFrom.lookup.value
|
|
174
|
+
|
|
175
|
+
return field
|
|
176
|
+
# self.session.add(field)
|
|
177
|
+
|
|
178
|
+
def _create_role(self,memb,table):
|
|
179
|
+
def getMultiplicitye(end):
|
|
180
|
+
upperv = end.find('upperValue')
|
|
181
|
+
if upperv is not None:
|
|
182
|
+
# print(' uv:', upperv0.attrib)
|
|
183
|
+
if upperv.attrib.get('value') == '*':
|
|
184
|
+
return 65535
|
|
185
|
+
elif upperv.attrib.get('value') == '1':
|
|
186
|
+
return 1
|
|
187
|
+
else:
|
|
188
|
+
return 65535
|
|
189
|
+
|
|
190
|
+
def getReqire(end):
|
|
191
|
+
lowerv = end.find('lowerValue')
|
|
192
|
+
if lowerv is not None:
|
|
193
|
+
# print(' uv:', upperv0.attrib)
|
|
194
|
+
return lowerv.attrib.get('value') != '0'
|
|
195
|
+
return False
|
|
196
|
+
|
|
197
|
+
def getRole(end0,end1,table,stereotype):
|
|
198
|
+
'''
|
|
199
|
+
因xmi档案不能带入navigable,只能根据end的顺序和multiplicity 来确定
|
|
200
|
+
1,1 -> 1 只有单向关系
|
|
201
|
+
2,* -> 1 lookup的关系 (非组合或聚合的关系视为单向)
|
|
202
|
+
3,* <-> 1 组合或聚合关系 (为双向)
|
|
203
|
+
'''
|
|
204
|
+
if end0.attrib.get('isDerived')=='true' or end1.attrib.get('isDerived')=='true':
|
|
205
|
+
return None
|
|
206
|
+
role = Roledictionary()
|
|
207
|
+
role.id = end0.attrib.get(_id)
|
|
208
|
+
role.underline = self.underline or '_id' in stereotype
|
|
209
|
+
role.ownertableid = end0.attrib.get('type', '')
|
|
210
|
+
role.end1_multiplicity = getMultiplicitye(end0)
|
|
211
|
+
# 取另一端的requre
|
|
212
|
+
role.req = getReqire(end1)
|
|
213
|
+
role.end1_rolename = end0.attrib.get('name', '').lower().replace(' ', '')
|
|
214
|
+
if role == '':
|
|
215
|
+
role.end1_rolename = table.tablename
|
|
216
|
+
# master 和 detail 均有masterdetail role
|
|
217
|
+
role.masterdetail = end0.attrib.get('aggregation') == 'composite' or\
|
|
218
|
+
end1.attrib.get('aggregation') == 'composite'
|
|
219
|
+
role.end2_reftableid = end1.attrib.get('type', '')
|
|
220
|
+
role.end2_rolename = end1.attrib.get('name', '').lower().replace(' ', '')
|
|
221
|
+
if role.end2_rolename== '' and role.end2_reftableid==table.id:
|
|
222
|
+
role.end2_rolename=table.tablename
|
|
223
|
+
role.end2_multiplicity = getMultiplicitye(end1)
|
|
224
|
+
role.end1_navigable = end0.attrib.get('aggregation') != 'none' or \
|
|
225
|
+
end1.attrib.get('aggregation') != 'none'
|
|
226
|
+
role.end2_navigable = end0.attrib.get('aggregation') != 'none' or \
|
|
227
|
+
end1.attrib.get('aggregation') != 'none'
|
|
228
|
+
# 如果aggregation 都为none 代表是单向关系,画图时需要顺着方向画
|
|
229
|
+
if not role.end1_navigable and not role.end2_navigable:
|
|
230
|
+
# 1 -> 1 关系只返回
|
|
231
|
+
if role.end1_multiplicity == 1 and role.end2_multiplicity == 1:
|
|
232
|
+
if role.ownertableid == table.id:
|
|
233
|
+
role.end1_navigable = False
|
|
234
|
+
role.end2_navigable = True
|
|
235
|
+
else:
|
|
236
|
+
role.end1_navigable = True
|
|
237
|
+
role.end2_navigable = False
|
|
238
|
+
# * -> 1 关系,1 方为True,*方为false
|
|
239
|
+
elif role.end1_multiplicity == 1:
|
|
240
|
+
role.end1_navigable = True
|
|
241
|
+
role.end2_navigable = False
|
|
242
|
+
else:
|
|
243
|
+
role.end1_navigable = False
|
|
244
|
+
role.end2_navigable = True
|
|
245
|
+
return role
|
|
246
|
+
|
|
247
|
+
ends = memb.findall('ownedEnd')
|
|
248
|
+
if not ends:
|
|
249
|
+
return []
|
|
250
|
+
extens = memb.find(_extension)
|
|
251
|
+
stereotype = []
|
|
252
|
+
if extens is not None:
|
|
253
|
+
# print(' extens:',extens.attrib)
|
|
254
|
+
stereotype_s = extens.find('stereotype')
|
|
255
|
+
if stereotype_s is not None:
|
|
256
|
+
stereotype=stereotype_s.attrib.get('value','').split('/')
|
|
257
|
+
# 任何一个memb 都会产生两个role
|
|
258
|
+
role0 = getRole(ends[0],ends[1],table,stereotype)
|
|
259
|
+
role1 = getRole(ends[1],ends[0],table,stereotype)
|
|
260
|
+
if role0 and role1:
|
|
261
|
+
return [role0,role1]
|
|
262
|
+
else:
|
|
263
|
+
return []
|
|
264
|
+
|
|
265
|
+
def handle_cls(self,pkg):
|
|
266
|
+
table = self._create_tb(pkg)
|
|
267
|
+
if not table:
|
|
268
|
+
return
|
|
269
|
+
self.tables[table.id] = table
|
|
270
|
+
self.session.add(table)
|
|
271
|
+
attrs = pkg.findall('ownedAttribute')
|
|
272
|
+
hasid = False
|
|
273
|
+
for attr in attrs:
|
|
274
|
+
if attr.attrib.get(_type, None) == 'uml:Property':
|
|
275
|
+
field = self._create_fld(attr,table)
|
|
276
|
+
if field.keytype == Keytype.key.value:
|
|
277
|
+
hasid = True
|
|
278
|
+
self.session.add(field)
|
|
279
|
+
if not hasid:
|
|
280
|
+
self.session.add(self._create_idfld(table.id))
|
|
281
|
+
|
|
282
|
+
members = pkg.findall('ownedMember')
|
|
283
|
+
for memb in members:
|
|
284
|
+
if memb.attrib.get(_type,None) == 'uml:Association':
|
|
285
|
+
roles = self._create_role(memb,table)
|
|
286
|
+
self.roles.extend(roles)
|
|
287
|
+
|
|
288
|
+
def handle_pkgElm(self,pkgElms):
|
|
289
|
+
for pkg in pkgElms:
|
|
290
|
+
pkg_type = pkg.attrib.get(_type, None)
|
|
291
|
+
# swagger 包中的uml:class不用处理
|
|
292
|
+
if pkg.attrib.get('name',None) == 'swagger':
|
|
293
|
+
continue
|
|
294
|
+
if pkg_type == 'uml:Class':
|
|
295
|
+
self.handle_cls(pkg)
|
|
296
|
+
else:
|
|
297
|
+
node = pkg.findall('packagedElement')
|
|
298
|
+
if node:
|
|
299
|
+
self.handle_pkgElm(node)
|
|
300
|
+
|
|
301
|
+
def init_database(self):
|
|
302
|
+
Base.metadata.drop_all(engine)
|
|
303
|
+
Base.metadata.create_all(engine) # 创建资料库结构
|
|
304
|
+
# if current_app.config['SQLALCHEMY_DATABASE_URI'].startswith('sqlite'):
|
|
305
|
+
# drop_all()
|
|
306
|
+
# create_all()
|
|
307
|
+
# else:
|
|
308
|
+
# self.session.execute('DELETE FROM [dbo].[databasedictionary]')
|
|
309
|
+
# self.session.commit()
|
|
310
|
+
|
|
311
|
+
def handleRoles(self):
|
|
312
|
+
for role in self.roles:
|
|
313
|
+
field = self.create_fnkeyfld(role)
|
|
314
|
+
if field is not None:
|
|
315
|
+
self.session.add(field)
|
|
316
|
+
self.session.add_all(self.roles)
|
|
317
|
+
self.session.commit()
|
|
318
|
+
for role in self.roles:
|
|
319
|
+
if role.assocrolename == '':
|
|
320
|
+
role.assocrolename=role.reftable.tablename
|
|
321
|
+
self.session.add_all(self.roles)
|
|
322
|
+
self.session.commit()
|
|
323
|
+
|
|
324
|
+
def impxml(self,file):
|
|
325
|
+
self.init_database()
|
|
326
|
+
self.database = self._create_db(file.split()[-1].split('.')[0],"")
|
|
327
|
+
self.session.add(self.database)
|
|
328
|
+
self.session.commit()
|
|
329
|
+
tree = ET.parse(file) # 分析XML文件
|
|
330
|
+
root = tree.getroot()
|
|
331
|
+
# print('0', root)
|
|
332
|
+
for idx0,r in enumerate(root):
|
|
333
|
+
# print('%d'%idx0, r.attrib)
|
|
334
|
+
if r.attrib.get('name',None) != 'RootModel':
|
|
335
|
+
continue
|
|
336
|
+
self.handle_pkgElm(r.findall('packagedElement'))
|
|
337
|
+
self.handleRoles()
|
|
338
|
+
|
|
339
|
+
if __name__ == '__main__':
|
|
340
|
+
i = ImportModels()
|
|
341
|
+
i.impxml(r"Untitled.xml")
|
|
342
|
+
# i.impxml(r"test.xml")
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
try: # 导入模块
|
|
2
|
+
import xml.etree.cElementTree as ET
|
|
3
|
+
except ImportError:
|
|
4
|
+
import xml.etree.ElementTree as ET
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
from jinja2 import FileSystemLoader,Environment
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
uml="http://schema.omg.org/spec/UML/2.0"
|
|
11
|
+
xmi="{http://schema.omg.org/spec/XMI/2.1}"
|
|
12
|
+
_id = xmi+"id"
|
|
13
|
+
_type = xmi+"type"
|
|
14
|
+
_extension = xmi+'Extension'
|
|
15
|
+
|
|
16
|
+
PORT =8000
|
|
17
|
+
|
|
18
|
+
class Tag:
|
|
19
|
+
def __init__(self,name,desc):
|
|
20
|
+
self.name=name
|
|
21
|
+
self.desc=desc
|
|
22
|
+
|
|
23
|
+
class Path:
|
|
24
|
+
def __init__(self,tag_name,summy,desc):
|
|
25
|
+
self.summy=summy
|
|
26
|
+
self.tag_name=tag_name
|
|
27
|
+
self.desc=desc
|
|
28
|
+
self.action=None
|
|
29
|
+
self.name=None
|
|
30
|
+
self.params=[]
|
|
31
|
+
self.resps=[]
|
|
32
|
+
|
|
33
|
+
class Path_param:
|
|
34
|
+
def __init__(self,name,type,desc):
|
|
35
|
+
self.name=name
|
|
36
|
+
self.type=type
|
|
37
|
+
self.desc=desc
|
|
38
|
+
class Resp:
|
|
39
|
+
def __init__(self,type,code):
|
|
40
|
+
self.type=type
|
|
41
|
+
self.code =code
|
|
42
|
+
self.class_name=''
|
|
43
|
+
|
|
44
|
+
class Defin:
|
|
45
|
+
def __init__(self,id,name,desc):
|
|
46
|
+
self.id=id
|
|
47
|
+
self.name=name
|
|
48
|
+
self.desc=desc
|
|
49
|
+
self.attrs=[]
|
|
50
|
+
|
|
51
|
+
class DeAttr:
|
|
52
|
+
def __init__(self,name, type, desc ):
|
|
53
|
+
self.name=name
|
|
54
|
+
self.type=type
|
|
55
|
+
self.desc=desc
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class RestFile:
|
|
60
|
+
def __init__(self,name,desc):
|
|
61
|
+
self.name=name
|
|
62
|
+
self.desc=desc
|
|
63
|
+
self.tags=[]
|
|
64
|
+
self.paths=[]
|
|
65
|
+
self.defines=[]
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def has_defin(self,id):
|
|
69
|
+
for defin in self.defines:
|
|
70
|
+
if defin.id==id:
|
|
71
|
+
return True
|
|
72
|
+
return False
|
|
73
|
+
|
|
74
|
+
def gen_text(self,templ):
|
|
75
|
+
return templ.render(name=self.name,
|
|
76
|
+
desc=self.desc,
|
|
77
|
+
port =PORT,
|
|
78
|
+
tags=self.tags,
|
|
79
|
+
paths=self.paths,
|
|
80
|
+
defines=self.defines)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
# def gen_text(self):
|
|
84
|
+
# head =f_head.format(desc=self.desc,
|
|
85
|
+
# name=self.name,
|
|
86
|
+
# tags=self.tags)
|
|
87
|
+
# if len(self.paths)>0:
|
|
88
|
+
# head+='paths:\r\n'
|
|
89
|
+
# for path in self.paths:
|
|
90
|
+
# head+=path
|
|
91
|
+
# if len(self.definitions)>0:
|
|
92
|
+
# head += 'definitions:\r\n'
|
|
93
|
+
# for defin in self.definitions:
|
|
94
|
+
# head+=defin
|
|
95
|
+
#
|
|
96
|
+
#
|
|
97
|
+
# return head
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
class XmlParser:
|
|
102
|
+
def filter_els(self,parent_el,el_name,el_type):
|
|
103
|
+
els =parent_el.findall(el_name)
|
|
104
|
+
def match_type(el):
|
|
105
|
+
return el.attrib.get(_type,None)==el_type
|
|
106
|
+
return filter(match_type,els)
|
|
107
|
+
|
|
108
|
+
def load(self,filename):
|
|
109
|
+
tree = ET.parse(filename) # 分析XML文件
|
|
110
|
+
root = tree.getroot()
|
|
111
|
+
# print('0', root)
|
|
112
|
+
for idx0,r in enumerate(root):
|
|
113
|
+
# print('%d'%idx0, r.attrib)
|
|
114
|
+
if r.attrib.get('name', None) != 'RootModel':
|
|
115
|
+
continue
|
|
116
|
+
self.r =r
|
|
117
|
+
|
|
118
|
+
def _get_exten_value(self,el,name):
|
|
119
|
+
exten =el.find(_extension)
|
|
120
|
+
if exten is not None:
|
|
121
|
+
docu =exten.find(name)
|
|
122
|
+
if docu is not None:
|
|
123
|
+
return docu.attrib.get('value','')
|
|
124
|
+
return ''
|
|
125
|
+
|
|
126
|
+
def _get_exten_list(self,el,name):
|
|
127
|
+
exten =el.find(_extension)
|
|
128
|
+
if exten is not None:
|
|
129
|
+
return exten.findall(name)
|
|
130
|
+
return None
|
|
131
|
+
|
|
132
|
+
def _get_documentation(self,el):
|
|
133
|
+
return self._get_exten_value(el,'documentation')
|
|
134
|
+
|
|
135
|
+
def _get_stereotype(self,el):
|
|
136
|
+
return self._get_exten_value(el,'stereotype')
|
|
137
|
+
|
|
138
|
+
#根据class name 找class
|
|
139
|
+
def _get_class_el(self,name):
|
|
140
|
+
pkgs=self.r.findall('packagedElement')
|
|
141
|
+
for pkg in pkgs:
|
|
142
|
+
if pkg.attrib.get(_type, None) =='uml:Model':
|
|
143
|
+
classes =pkg.findall('packagedElement')
|
|
144
|
+
for cls in classes:
|
|
145
|
+
if cls.attrib.get('name',None)==name :
|
|
146
|
+
return cls
|
|
147
|
+
return None
|
|
148
|
+
|
|
149
|
+
# 根据class id 找class
|
|
150
|
+
def _get_class_el_byid(self,class_id):
|
|
151
|
+
pkgs=self.r.findall('packagedElement')
|
|
152
|
+
for pkg in pkgs:
|
|
153
|
+
if pkg.attrib.get(_type, None) =='uml:Model':
|
|
154
|
+
classes =pkg.findall('packagedElement')
|
|
155
|
+
for cls in classes:
|
|
156
|
+
if cls.attrib.get(_id,None)==class_id :
|
|
157
|
+
return cls
|
|
158
|
+
return None
|
|
159
|
+
|
|
160
|
+
def _get_class_attr(self,attr):
|
|
161
|
+
name =attr.attrib.get('name','')
|
|
162
|
+
if name.find(':')>=0:
|
|
163
|
+
ls=name.split(':')
|
|
164
|
+
name=ls[0]
|
|
165
|
+
datatype=ls[1]
|
|
166
|
+
else:
|
|
167
|
+
datatype=attr.attrib.get('type','').split('_')[0]
|
|
168
|
+
if datatype=='double':
|
|
169
|
+
datatype='number'
|
|
170
|
+
desc =self._get_documentation(attr)
|
|
171
|
+
|
|
172
|
+
return name,datatype,desc
|
|
173
|
+
|
|
174
|
+
#取得 message的参数
|
|
175
|
+
def _get_message_args(self,msg):
|
|
176
|
+
args =msg.find('argument')
|
|
177
|
+
if args is not None:
|
|
178
|
+
return args.attrib.get('value',None)
|
|
179
|
+
return None
|
|
180
|
+
|
|
181
|
+
class SequencetoRest(XmlParser):
|
|
182
|
+
def __init__(self):
|
|
183
|
+
self.rests = []
|
|
184
|
+
|
|
185
|
+
def _handle_class_params(self,class_type,cls,path):
|
|
186
|
+
if cls is not None:
|
|
187
|
+
if class_type=='inquery':
|
|
188
|
+
attrs =self.filter_els(cls,'ownedAttribute','uml:Property')
|
|
189
|
+
for attr in attrs:
|
|
190
|
+
name,datatype,desc=self._get_class_attr(attr)
|
|
191
|
+
path.params.append(Path_param(name,datatype,desc))
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
def _handle_message_params(self,path,msg):
|
|
195
|
+
tags= self._get_exten_list(msg,'tag')
|
|
196
|
+
for tag in tags:
|
|
197
|
+
keys=tag.keys()
|
|
198
|
+
for key in keys:
|
|
199
|
+
value =tag.attrib.get(key,None) #class id
|
|
200
|
+
if value is not None:
|
|
201
|
+
cls = self._get_class_el_byid(value)
|
|
202
|
+
self._handle_class_params(key, cls, path)
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
def _add_definitions(self,rs,cls,cls_id):
|
|
206
|
+
defin =Defin(cls_id,cls.attrib.get('name',''),self._get_documentation(cls))
|
|
207
|
+
rs.defines.append(defin)
|
|
208
|
+
attrs = self.filter_els(cls, 'ownedAttribute', 'uml:Property')
|
|
209
|
+
for attr in attrs:
|
|
210
|
+
attr_name, datatype, desc = self._get_class_attr(attr)
|
|
211
|
+
defin.attrs.append(DeAttr(attr_name, datatype, desc))
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
def _handle_msg_tag(self,tag,path,rs):
|
|
215
|
+
keys=tag.keys()
|
|
216
|
+
|
|
217
|
+
# key like str|obj|array:response_code
|
|
218
|
+
for key in keys:
|
|
219
|
+
value =tag.attrib.get(key,None)
|
|
220
|
+
ls =key.split("_")
|
|
221
|
+
resp=Resp(ls[0],ls[1])
|
|
222
|
+
path.resps.append(resp)
|
|
223
|
+
cls = self._get_class_el_byid(value)
|
|
224
|
+
if cls is not None:
|
|
225
|
+
resp.class_name=cls.attrib.get('name','')
|
|
226
|
+
|
|
227
|
+
#add definitions
|
|
228
|
+
if rs.has_defin(value)==False:
|
|
229
|
+
self._add_definitions(rs,cls,value)
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
def _get_rest_path(self,rs,path,interact):
|
|
236
|
+
path.action =self._get_stereotype(interact)
|
|
237
|
+
|
|
238
|
+
#get message
|
|
239
|
+
|
|
240
|
+
msgs =self.filter_els(interact,'message','uml:Message')
|
|
241
|
+
for msg in msgs :
|
|
242
|
+
if (self._get_stereotype(msg)=='send'):
|
|
243
|
+
path.name=msg.attrib.get('name','')
|
|
244
|
+
self._handle_message_params(path,msg)
|
|
245
|
+
|
|
246
|
+
#response msg
|
|
247
|
+
elif (msg.attrib.get(_type,None)=='uml:Message') and (self._get_stereotype(msg)=='ack'):
|
|
248
|
+
tags = self._get_exten_list(msg, 'tag')
|
|
249
|
+
for tag in tags:
|
|
250
|
+
self._handle_msg_tag( tag, path,rs)
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
def _handle_package(self,pkg):
|
|
254
|
+
# each package is a rest file
|
|
255
|
+
rs = RestFile(pkg.attrib.get('name', ''),self._get_documentation(pkg))
|
|
256
|
+
self.rests.append(rs)
|
|
257
|
+
|
|
258
|
+
collabs =self.filter_els(pkg,'packagedElement',"uml:Collaboration")
|
|
259
|
+
|
|
260
|
+
for collab in collabs:
|
|
261
|
+
tag_name = collab.attrib.get('name', '')
|
|
262
|
+
rs.tags.append(Tag(tag_name ,self._get_documentation(collab)))
|
|
263
|
+
|
|
264
|
+
#get Interaction
|
|
265
|
+
interacts =self.filter_els(collab,'ownedMember','uml:Interaction')
|
|
266
|
+
for interact in interacts:
|
|
267
|
+
path=Path(tag_name,interact.attrib.get('name', ''),
|
|
268
|
+
self._get_documentation(interact))
|
|
269
|
+
rs.paths.append(path)
|
|
270
|
+
self._get_rest_path(rs,path,interact)
|
|
271
|
+
#
|
|
272
|
+
#rs.paths.append(self._get_rest_path(interact,tag_name,rs))
|
|
273
|
+
|
|
274
|
+
def parse_xml_data(self): ##
|
|
275
|
+
# get package
|
|
276
|
+
pkgs =self.filter_els(self.r,'packagedElement',"uml:Package")
|
|
277
|
+
for pkg in pkgs:
|
|
278
|
+
self._handle_package(pkg)
|
|
279
|
+
|
|
280
|
+
if __name__ == '__main__':
|
|
281
|
+
|
|
282
|
+
load=FileSystemLoader('./template')
|
|
283
|
+
env =Environment(loader=load)
|
|
284
|
+
t=env.get_template('swagger_file')
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
rests = SequencetoRest()
|
|
288
|
+
rests.load(r"/home/vagrant/data/docs/test.xmi")
|
|
289
|
+
rests.parse_xml_data()
|
|
290
|
+
for rest in rests.rests:
|
|
291
|
+
print(rest.gen_text(t))
|