tcorecontext.py 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. '''This file is part of AToMPM - A Tool for Multi-Paradigm Modelling
  2. Copyright 2011 by the AToMPM team and licensed under the LGPL
  3. See COPYING.lesser and README.md in the root of this project for full details'''
  4. '''
  5. Transformation context for TCore
  6. Author: Huseyin Ergin (hergin)
  7. Purpose: Tcore integration to AtomPM
  8. '''
  9. import random
  10. from tconstants import TConstants as TC
  11. from utils import Utilities as utils
  12. from tcontext import TransformationContext
  13. from pytcore.tcore.messages import Pivots
  14. from pytcore.tcore.matcher import Matcher
  15. from pytcore.tcore.iterator import Iterator
  16. from pytcore.tcore.rewriter import Rewriter
  17. '''
  18. holds the execution context of a 'Transformation' construct
  19. fname the filename of the transformation model '''
  20. class TCoreContext(TransformationContext) :
  21. def __init__(self,fname,ptcal) :
  22. super(TCoreContext,self).__init__(ptcal._transfData[fname])
  23. self.fname = fname
  24. self.metamodel = TC.TCOREMM
  25. self.totalExecutionTime=0
  26. self.pivots = Pivots()
  27. self.sendAndApplyDeltaFunc=ptcal.sendAndApplyDelta
  28. self.nextInput = "packetIn"
  29. self.compiler = ptcal._compiler
  30. self.rules = {}
  31. self.startPacketInID = None
  32. self.startNextInID = None
  33. self.startCancelInID = None
  34. for id in self.t['nodes']:
  35. if self.t['nodes'][id]['$type'] == self.metamodel+"/Matcher":
  36. max = self.t['nodes'][id]['max']['value']
  37. ruleName = self.t['nodes'][id]['pattern']['value']
  38. compiledRule = self.compiler.compileRule(None,ruleName)
  39. matcher = Matcher(condition=compiledRule['lhs'],max=max)
  40. self.rules[id] = {'id':id,
  41. 'name':self.t['nodes'][id]['name']['value'],
  42. 'alias':self.t['nodes'][id]['alias']['value'],
  43. 'rule':matcher}
  44. elif self.t['nodes'][id]['$type'] == self.metamodel+"/Rewriter":
  45. ruleName = self.t['nodes'][id]['pattern']['value']
  46. compiledRule = self.compiler.compileRule(None,ruleName)
  47. rewriter = Rewriter(condition=compiledRule['rhs'],sendAndApplyDeltaFunc=self.sendAndApplyDeltaFunc)
  48. self.rules[id] = {'id':id,
  49. 'name':self.t['nodes'][id]['name']['value'],
  50. 'alias':self.t['nodes'][id]['alias']['value'],
  51. 'rule':rewriter}
  52. elif self.t['nodes'][id]['$type'] == self.metamodel+"/Iterator":
  53. maxIterations = self.t['nodes'][id]['maxIterations']['value']
  54. ruleName = self.t['nodes'][id]['pattern']['value']
  55. compiledRule = self.compiler.compileRule(None,ruleName)
  56. iterator = Iterator(condition=compiledRule['lhs'])
  57. self.rules[id] = {'id':id,
  58. 'name':self.t['nodes'][id]['name']['value'],
  59. 'alias':self.t['nodes'][id]['alias']['value'],
  60. 'rule':iterator}
  61. elif self.t['nodes'][id]['$type'] == self.metamodel+"/StartPacketIn":
  62. self.startPacketInID = id
  63. elif self.t['nodes'][id]['$type'] == self.metamodel+"/StartNextIn":
  64. self.startNextInID = id
  65. elif self.t['nodes'][id]['$type'] == self.metamodel+"/StartCancelIn":
  66. self.startCancelInID = id
  67. ''' TODO add other rules '''
  68. def setLastStepExecTime(self,a):
  69. self._lastStep['time'] = a
  70. self.totalExecutionTime += a
  71. '''
  72. returns the id of the current step in the transformation model '''
  73. def getCurrentStepId(self) :
  74. if self._lastStep == {} :
  75. assert False, \
  76. "this function shouldn't be called when there is no current step"
  77. else :
  78. return self._lastStep['id']
  79. '''
  80. Returns the initial step of transformation which is the step after start state
  81. '''
  82. def _getInitialStep(self) :
  83. if self.startPacketInID == None and self.startNextInID == None and self.startCancelInID == None:
  84. raise RuntimeError('There is no start state in loaded TCore instance!')
  85. ''' a regular Tcore trafo starts with an startPacketIn node '''
  86. if self.startPacketInID != None:
  87. startStateEdges = filter(lambda e:e['src']==self.startPacketInID,self.t['edges'])
  88. if len(startStateEdges) == 0 :
  89. raise RuntimeError('StartPacketIn is not connected to any other rule!')
  90. else:
  91. initialStepID=filter(lambda e:e['src']==startStateEdges[0]['dest'],self.t['edges'])[0]['dest']
  92. return self.rules[initialStepID]
  93. '''
  94. return the next step to run in this transformation... this is either
  95. the initial step OR a neighbour of the last step... which one of these
  96. neighbours is the next step is determined by the application information
  97. of the said last step
  98. 0. if self._expired is true (i.e., a race condition occurred causing this
  99. context to be called after it terminated but before ptcal.stop()
  100. removed it from ptcal._mtContexts), raise error
  101. 1. if there is no last step, return initial step
  102. 2. filter through edges to find appropriate edge out of last step
  103. a) if none is found, reset lastStep, set self._expired flag, and
  104. return the application information of this entire transformation
  105. context
  106. b) otherwise, return step on the other end of the said edge
  107. Next step structure
  108. lastStepID --> successID --> nextID
  109. --> failID --> nextID
  110. Steps to find next
  111. 1- Filter edges and get (lastStepID, successID) and (lastStepID,failID) edges
  112. 2- Select success or fail according to _lastStep['applicationInfo']
  113. 3- Find this edge (nextPath, nextStepID) where nextPath is one of the success or fail ids.
  114. '''
  115. def nextStep(self) :
  116. if self._expired == True :
  117. raise RuntimeError('can not step in expired mtContext')
  118. elif self._lastStep == {} :
  119. ns = self._getInitialStep()
  120. if ns == None :
  121. return {'$err':'could not find initial transformation step'}
  122. self._lastStep = ns
  123. return ns
  124. else :
  125. def f(e) :
  126. return e['src'] == self._lastStep['id']
  127. edgesFromLastStep = filter(f,self.t['edges'])
  128. if len(edgesFromLastStep) == 0 :
  129. ai = self._applicationInfo()
  130. self._lastStep = {}
  131. self._expired = True
  132. return ai
  133. else :
  134. targetLinkID=None
  135. resString = None
  136. if self._lastStep['applicationInfo'] == TC.SUCCEEDED :
  137. resString = "success"
  138. elif self._lastStep['applicationInfo'] == TC.FAILED:
  139. resString = "fail"
  140. else: #exception
  141. resString = "exception"
  142. for edgeLS in edgesFromLastStep:
  143. if 'output' in self.t['nodes'][edgeLS['dest']] and self.t['nodes'][edgeLS['dest']]['output']['value'] == resString:
  144. targetLinkID=edgeLS['dest']
  145. break
  146. elif 'output' not in self.t['nodes'][edgeLS['dest']]:
  147. if self.t['nodes'][edgeLS['dest']]['$type']==self.metamodel+"/endExceptionPort" and resString=='exception':
  148. targetLinkID=edgeLS['dest']
  149. break
  150. elif self.t['nodes'][edgeLS['dest']]['$type']==self.metamodel+"/endSuccessPort" and resString=='success':
  151. targetLinkID=edgeLS['dest']
  152. break
  153. elif self.t['nodes'][edgeLS['dest']]['$type']==self.metamodel+"/endFailPort" and resString=='fail':
  154. targetLinkID=edgeLS['dest']
  155. break
  156. if 'input' in self.t['nodes'][targetLinkID]:
  157. self.nextInput = self.t['nodes'][targetLinkID]['input']['value']
  158. def f(e) :
  159. return e['src'] == targetLinkID
  160. nodesAfterLastStep = filter(f,self.t['edges'])
  161. nextStepID = nodesAfterLastStep[0]['dest']
  162. if nextStepID in self.rules:
  163. self._lastStep = self.rules[nextStepID]
  164. else:
  165. if self.t['nodes'][nextStepID]['$type']==self.metamodel+"/EndSuccess":
  166. self._lastStep = {'trafoResult':TC.SUCCEEDED,
  167. 'feedbackReceived':'True'}
  168. elif self.t['nodes'][nextStepID]['$type']==self.metamodel+"/EndFail":
  169. self._lastStep = {'trafoResult':TC.FAILED,
  170. 'feedbackReceived':'True'}
  171. elif self.t['nodes'][nextStepID]['$type']==self.metamodel+"/EndException":
  172. self._lastStep = {'trafoResult':TC.EXCEPTION,
  173. 'feedbackReceived':'True'}
  174. return self._lastStep
  175. '''
  176. set the application information of the last step '''
  177. def setLastStepApplicationInfo(self,applicationInfo) :
  178. if applicationInfo == TC.SUCCEEDED :
  179. self._notApplicable = False
  180. self._lastStep['applicationInfo'] = applicationInfo
  181. def isLastStepFeedbackReceived(self) :
  182. return (not self._expired and self._lastStep=={}) or \
  183. 'feedbackReceived' in self._lastStep