sccd_to_xml.py 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. import re
  2. #from sccd_modelverse_sources.sccd_metamodel import Gen as GenSCCD
  3. #from sccd_modelverse_sources.bouncing_tkinter import Gen as GenBBals
  4. from mvk.impl.python.constants import CreateConstants, UpdateConstants
  5. from mvk.impl.python.datatype import TypeFactory, Type, IntegerType, StringType, \
  6. BooleanType, FloatType
  7. from mvk.impl.python.datavalue import MappingValue, \
  8. LocationValue, StringValue, FloatValue, \
  9. IntegerValue, BooleanValue, InfiniteValue, Iterator, AnyValue
  10. from mvk.impl.python.object import ClabjectReference, Clabject
  11. from mvk.mvk import MvK
  12. import mvk
  13. from shell import Shell
  14. #from sccd_to_xml_rules import XMLRules
  15. DEBUG = False
  16. def debug_print(_str_):
  17. if(DEBUG is False):
  18. return
  19. print('>>> debug: ' + _str_)
  20. class SCCD_to_XML(object):
  21. def __init__(self, rules, modelverse=None):
  22. self.modelpackage = ''
  23. self.modelname = ''
  24. self.modelitem = None
  25. self.rules = rules
  26. self.outputStream = ''
  27. self.reset_indentation()
  28. # if(modelverse is None): # load default...
  29. # self.mvk = MvK()
  30. # gmm = GenSCCD()
  31. # gmm.mvk = self.mvk
  32. # gmm.instance()
  33. # gbb = GenBBals()
  34. # gbb.mvk = gmm.mvk
  35. # gbb.instance()
  36. # else:
  37. self.mvk = modelverse
  38. self.reservedwords = ['@newline', '@indent', '@dedent']
  39. def reset_indentation(self):
  40. self.indentation = 0
  41. self.lastnewline = False
  42. def increase_indentation(self):
  43. self.indentation = self.indentation + 1
  44. def decrease_indentation(self):
  45. self.indentation = self.indentation - 1
  46. def getidentstring(self):
  47. ntabs = self.indentation
  48. outstring = ''
  49. while ntabs > 0:
  50. outstring = outstring + '\t'
  51. ntabs = ntabs - 1
  52. return outstring
  53. ## override this to emmit to other outputs
  54. def emmitCode(self, string, tabs=False):
  55. string = string.replace('\[','{')
  56. string = string.replace('\]','}')
  57. if tabs is True or self.lastnewline is True:
  58. self.write(self.getidentstring() + string)
  59. else:
  60. self.write(string)
  61. self.lastnewline = False
  62. def newline(self):
  63. self.write('\n')
  64. self.lastnewline = True
  65. def write(self, string):
  66. self.outputStream += string
  67. def compile(self, location='MyFormalisms.BouncingBalls'):
  68. modelrule = None
  69. for key in self.rules:
  70. if(self.rules[key]['type'] == 'Model'):
  71. modelrule = {'key': key, 'body': self.rules[key]}
  72. if modelrule == None:
  73. raise Exception('Error: no model rule defined')
  74. rl = self.mvk.read(LocationValue(location))
  75. if(not rl.is_success()):
  76. raise Exception('Error: Invalid location: ' + location)
  77. item = rl.get_item()
  78. typename = str(item.typed_by().get_location())
  79. debug_print(typename)
  80. self.modelpackage = modelrule['body']['package']
  81. self.modelname = modelrule['body']['name']
  82. self.modelitem = item
  83. expectedtype = self.modelpackage + '.' + modelrule['body']['name']
  84. if(typename != expectedtype):
  85. raise Exception('Model at specified location is not an ' + expectedtype + ' model!')
  86. if(self.isEnabled(modelrule, item)):
  87. self.evaluateRule(modelrule, item)
  88. def processReserved(self, elem):
  89. if(elem == '@newline'):
  90. self.newline()
  91. elif(elem == '@indent'):
  92. self.increase_indentation()
  93. elif(elem == '@dedent'):
  94. self.decrease_indentation()
  95. def evaluateRule(self, rule, item):
  96. debug_print('evaluateRule: ' + str(rule))
  97. debug_print('evaluateRule: ' + str(item))
  98. pattern = rule['body']['pattern']
  99. for elem in pattern:
  100. if(elem.startswith('@')):
  101. if(elem in self.reservedwords):
  102. self.processReserved(elem)
  103. elif(elem[1:] == '@'):
  104. continue ## just ignore mute attributes
  105. elif(self.isAttributeIn(elem[1:], item)):
  106. self.processAttributeIn(elem[1:], item)
  107. elif(elem[1:] in self.rules):
  108. self.evaluateIn(elem[1:], item)
  109. else:
  110. raise Exception(elem + ' not found!')
  111. elif(elem.startswith('\@')):
  112. self.emmitCode(elem[2:])
  113. else:
  114. self.emmitCode(elem)
  115. def evaluateRuleOnSet(self, rule, item, list):
  116. #debug_print('evaluateRuleOnSet: ' + str(rule))
  117. #debug_print('evaluateRuleOnSet: ' + str(item))
  118. pattern = rule['body']['pattern']
  119. for elem in pattern:
  120. if(elem.startswith('@')):
  121. if(elem in self.reservedwords):
  122. self.processReserved(elem)
  123. elif(elem[1:] == '@'):
  124. continue ## just ignore mute attributes
  125. elif(self.isAttributeIn(elem[1:], item)):
  126. self.processAttributeIn(elem[1:], item)
  127. elif(elem[1:] in self.rules):
  128. for itemlist in list:
  129. self.evaluateIn(elem[1:], itemlist)
  130. else:
  131. raise Exception(elem + ' not found!')
  132. elif(elem.startswith('\@')):
  133. self.emmitCode(elem[2:])
  134. else:
  135. self.emmitCode(elem)
  136. def evaluateIn(self, rulename, item):
  137. #debug_print('evaluateIn: ' + str(rulename))
  138. #debug_print('evaluateIn: ' + str(item))
  139. rule = {'key': rulename, 'body': self.rules[rulename]}
  140. if(not self.isEnabledIn(rulename, item)):
  141. return
  142. if(rule['body']['type'] == 'Class'):
  143. if(isinstance(item, mvk.interfaces.object.Clabject)):
  144. self.evaluateRule(rule, item)
  145. else:
  146. iterator = Iterator(self.modelitem.get_elements().keys())
  147. while(iterator.has_next()):
  148. itemin = iterator.next()
  149. value = self.modelitem.get_elements()[itemin]
  150. #debug_print('item.get_elements()[itemin]: ' + str(value))
  151. if(not isinstance(value, mvk.interfaces.object.Association)):
  152. typename = str(value.typed_by().get_location())
  153. if((self.modelpackage + '.' + rule['body']['name']) == typename):
  154. self.evaluateRule(rule, value)
  155. elif(rule['body']['type'] == 'Association'):
  156. #debug_print('Association?')
  157. iterator = Iterator(item.out_associations.keys())
  158. alist = []
  159. while(iterator.has_next()):
  160. itemin = iterator.next()
  161. relvalue = item.out_associations[itemin]
  162. #debug_print('item.out_associations[itemin]: ' + str(relvalue))
  163. typename = str(relvalue.typed_by().get_location())
  164. #debug_print('typename: ' + typename)
  165. expectedtypename = self.modelpackage + '.' + rule['body']['name']
  166. if(expectedtypename == typename):
  167. #debug_print('expectedtypename: ' + expectedtypename)
  168. alist.append(relvalue.get_to_multiplicity().get_node())
  169. self.evaluateRuleOnSet(rule, item, alist)
  170. else:
  171. self.evaluateRule(rule, item)
  172. def processAttributeIn(self, elem, item):
  173. debug_print('processAttributeIn: ' + elem)
  174. reverse = False
  175. if(elem.startswith('-')):
  176. elem = elem[1:]
  177. reverse = True
  178. if(elem.startswith('(')):
  179. splitres = re.split('\).', elem[1:])
  180. if(len(splitres) == 2):
  181. item = self.resolveNavItem(splitres[0], reverse, item)
  182. debug_print('setting new item: ' + str(item))
  183. self.processAttributeIn(splitres[1], item)
  184. return
  185. else:
  186. raise Exception('Internal Syntax error on: ' + elem)
  187. value = item.get_attribute(StringValue(elem)).get_value()
  188. if(isinstance(value,AnyValue)):
  189. return
  190. self.emmitCode(str(value))
  191. def isEnabledIn(self, rulename, item):
  192. #debug_print('isEnabledIn: ' + str(rulename))
  193. #debug_print('isEnabledIn: ' + str(item))
  194. rule = {'key': rulename, 'body': self.rules[rulename]}
  195. if(rule['body']['type'] == 'Class'):
  196. #debug_print('isEnabledIn: ' + str(rule['body']['name']))
  197. if(isinstance(item, mvk.interfaces.object.Clabject)):
  198. if(self.isEnabled(rule, item)):
  199. return True
  200. else:
  201. iterator = Iterator(item.get_elements().keys())
  202. while(iterator.has_next()):
  203. itemin = iterator.next()
  204. value = item.get_elements()[itemin]
  205. if(not isinstance(value, mvk.interfaces.object.Association)):
  206. typename = str(value.typed_by().get_location())
  207. if((self.modelpackage + '.' + rule['body']['name']) == typename):
  208. if(self.isEnabled(rule, value)):
  209. return True
  210. elif(rule['body']['type'] == 'Association'):
  211. #debug_print('isEnabledIn: ' + str(rule['body']['target']))
  212. iterator = Iterator(item.out_associations.keys())
  213. while(iterator.has_next()):
  214. itemin = iterator.next()
  215. relvalue = item.out_associations[itemin]
  216. typename = str(relvalue.typed_by().get_location())
  217. #debug_print('typename: ' + typename)
  218. expectedtypename = self.modelpackage + '.' + rule['body']['name']
  219. #debug_print('expectedtypename: ' + expectedtypename)
  220. if(expectedtypename == typename):
  221. if(self.isEnabled(rule, relvalue.get_to_multiplicity().get_node())):
  222. return True
  223. elif(rule['body']['type'] == 'Attribute'):
  224. return self.isEnabled(rule, item)
  225. return False
  226. def hasExpectedType(self, expectedtype, elem):
  227. item = elem.typed_by()
  228. lastname = re.compile('\w+').findall(str(item.get_location())).pop()
  229. if(self.modelname + '.' + lastname == expectedtype):
  230. return True
  231. iterator = Iterator(item.get_all_super_classes())
  232. while(iterator.has_next()):
  233. itemin = iterator.next()
  234. lastname = re.compile('\w+').findall(str(itemin.get_location())).pop()
  235. if(self.modelname + '.' + lastname == expectedtype):
  236. return True
  237. return False
  238. def isEnabled(self, rule, item):
  239. debug_print('isEnabled rule: ' + str(rule))
  240. debug_print('isEnabled item: ' + str(item.typed_by().get_location()))
  241. if(rule['body']['type'] == 'Class'):
  242. if(not self.hasExpectedType(rule['body']['name'], item)):
  243. return False
  244. pattern = rule['body']['pattern']
  245. nonterminalFound = False
  246. for elem in pattern:
  247. if(elem.startswith('@')):
  248. if(elem in self.reservedwords):
  249. continue
  250. if(elem[1:] == '@'):
  251. return True
  252. elif(self.isAttributeIn(elem[1:], item)):
  253. nonterminalFound = True
  254. if(self.hasValue(elem[1:], item)):
  255. return True
  256. elif(elem[1:] in self.rules):
  257. nonterminalFound = True
  258. if(self.isEnabledIn(elem[1:], item)):
  259. return True
  260. else:
  261. continue
  262. return not nonterminalFound
  263. def resolveNavItem(self, navexpr, reverse, item):
  264. debug_print('resolveNavItem: ' + navexpr)
  265. if(isinstance(item, mvk.interfaces.object.Association)):
  266. return item
  267. if(isinstance(item, mvk.interfaces.object.Clabject)):
  268. if(reverse):
  269. iterator = Iterator(item.get_in_associations())
  270. else:
  271. iterator = Iterator(item.get_out_associations())
  272. debug_print('here!!!!')
  273. while(iterator.has_next()):
  274. association = iterator.next()
  275. name = str(association.get_name())
  276. typename = str(association.typed_by().get_location())
  277. debug_print('name: ' + name)
  278. debug_print('typename: ' + typename)
  279. if(typename.endswith(navexpr)):
  280. if(reverse):
  281. return association.get_from_multiplicity().get_node()
  282. else:
  283. return association.get_to_multiplicity().get_node()
  284. raise Exception('Type not found: ' + navexpr)
  285. def isAttributeIn(self, elem, item):
  286. debug_print('isAttributeIn: ' + elem)
  287. debug_print('isAttributeIn item: ' + str(item))
  288. reverse = False
  289. if(elem.startswith('-')):
  290. elem = elem[1:]
  291. reverse = True
  292. if(elem.startswith('(')):
  293. splitres = re.split('\).', elem[1:])
  294. if(len(splitres) == 2):
  295. item = self.resolveNavItem(splitres[0], reverse, item)
  296. debug_print('setting new item: ' + str(item))
  297. isattribute = self.isAttributeIn(splitres[1], item)
  298. debug_print('was found? ' + str(isattribute))
  299. return isattribute
  300. else:
  301. raise Exception('Internal Syntax error on: ' + elem)
  302. iterator = Iterator(item.get_attributes())
  303. while(iterator.has_next()):
  304. attribute = iterator.next()
  305. name = str(attribute.get_name())
  306. if(elem == name):
  307. return True
  308. def hasValue(self, elem, item):
  309. debug_print('hasValue: ' + elem + ' in ' + str(item))
  310. reverse = False
  311. if(elem.startswith('-')):
  312. elem = elem[1:]
  313. reverse = True
  314. if(elem.startswith('(')):
  315. splitres = re.split('\).', elem[1:])
  316. if(len(splitres) == 2):
  317. item = self.resolveNavItem(splitres[0], reverse, item)
  318. debug_print('setting new item: ' + str(item))
  319. hasValue = self.hasValue(splitres[1], item)
  320. debug_print('has value? ' + str(hasValue))
  321. return hasValue
  322. else:
  323. raise Exception('Internal Syntax error on: ' + elem)
  324. value = item.get_attribute(StringValue(elem)).get_value()
  325. if(isinstance(value,AnyValue)):
  326. return False
  327. #debug_print('has indeed a value! on: ' + elem + str(value))
  328. return True
  329. def outputTo(self, output='console'):
  330. if(output == 'console'):
  331. print(self.outputStream)
  332. else:
  333. fo = open(output, 'a')
  334. fo.write(self.outputStream)
  335. fo.close()
  336. if __name__ == '__main__':
  337. pass
  338. #compiler = SCCD_to_XML(XMLRules().rules)
  339. #compiler.compile()
  340. #compiler.outputTo()
  341. #shell = Shell()
  342. #shell.mvk = compiler.mvk
  343. #shell.setupCommandLine()