123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226 |
- '''This file is part of AToMPM - A Tool for Multi-Paradigm Modelling
- Copyright 2011 by the AToMPM team and licensed under the LGPL
- See COPYING.lesser and README.md in the root of this project for full details'''
- '''
- Transformation context for TCore
- Author: Huseyin Ergin (hergin)
- Purpose: Tcore integration to AtomPM
- '''
- import random
- from tconstants import TConstants as TC
- from utils import Utilities as utils
- from tcontext import TransformationContext
- from pytcore.tcore.messages import Pivots
- from pytcore.tcore.matcher import Matcher
- from pytcore.tcore.iterator import Iterator
- from pytcore.tcore.rewriter import Rewriter
-
- '''
- holds the execution context of a 'Transformation' construct
- fname the filename of the transformation model '''
-
- class TCoreContext(TransformationContext) :
- def __init__(self,fname,ptcal) :
- super(TCoreContext,self).__init__(ptcal._transfData[fname])
- self.fname = fname
- self.metamodel = TC.TCOREMM
- self.totalExecutionTime=0
- self.pivots = Pivots()
- self.sendAndApplyDeltaFunc=ptcal.sendAndApplyDelta
- self.nextInput = "packetIn"
-
- self.compiler = ptcal._compiler
- self.rules = {}
-
- self.startPacketInID = None
- self.startNextInID = None
- self.startCancelInID = None
-
- for id in self.t['nodes']:
-
- if self.t['nodes'][id]['$type'] == self.metamodel+"/Matcher":
- max = self.t['nodes'][id]['max']['value']
- ruleName = self.t['nodes'][id]['pattern']['value']
- compiledRule = self.compiler.compileRule(None,ruleName)
- matcher = Matcher(condition=compiledRule['lhs'],max=max)
- self.rules[id] = {'id':id,
- 'name':self.t['nodes'][id]['name']['value'],
- 'alias':self.t['nodes'][id]['alias']['value'],
- 'rule':matcher}
-
- elif self.t['nodes'][id]['$type'] == self.metamodel+"/Rewriter":
- ruleName = self.t['nodes'][id]['pattern']['value']
- compiledRule = self.compiler.compileRule(None,ruleName)
- rewriter = Rewriter(condition=compiledRule['rhs'],sendAndApplyDeltaFunc=self.sendAndApplyDeltaFunc)
- self.rules[id] = {'id':id,
- 'name':self.t['nodes'][id]['name']['value'],
- 'alias':self.t['nodes'][id]['alias']['value'],
- 'rule':rewriter}
-
- elif self.t['nodes'][id]['$type'] == self.metamodel+"/Iterator":
- maxIterations = self.t['nodes'][id]['maxIterations']['value']
- ruleName = self.t['nodes'][id]['pattern']['value']
- compiledRule = self.compiler.compileRule(None,ruleName)
- iterator = Iterator(condition=compiledRule['lhs'])
- self.rules[id] = {'id':id,
- 'name':self.t['nodes'][id]['name']['value'],
- 'alias':self.t['nodes'][id]['alias']['value'],
- 'rule':iterator}
-
- elif self.t['nodes'][id]['$type'] == self.metamodel+"/StartPacketIn":
- self.startPacketInID = id
- elif self.t['nodes'][id]['$type'] == self.metamodel+"/StartNextIn":
- self.startNextInID = id
- elif self.t['nodes'][id]['$type'] == self.metamodel+"/StartCancelIn":
- self.startCancelInID = id
-
- ''' TODO add other rules '''
-
- def setLastStepExecTime(self,a):
- self._lastStep['time'] = a
- self.totalExecutionTime += a
- '''
- returns the id of the current step in the transformation model '''
- def getCurrentStepId(self) :
- if self._lastStep == {} :
- assert False, \
- "this function shouldn't be called when there is no current step"
- else :
- return self._lastStep['id']
- '''
- Returns the initial step of transformation which is the step after start state
- '''
- def _getInitialStep(self) :
-
- if self.startPacketInID == None and self.startNextInID == None and self.startCancelInID == None:
- raise RuntimeError('There is no start state in loaded TCore instance!')
- ''' a regular Tcore trafo starts with an startPacketIn node '''
- if self.startPacketInID != None:
- startStateEdges = filter(lambda e:e['src']==self.startPacketInID,self.t['edges'])
-
- if len(startStateEdges) == 0 :
- raise RuntimeError('StartPacketIn is not connected to any other rule!')
- else:
- initialStepID=filter(lambda e:e['src']==startStateEdges[0]['dest'],self.t['edges'])[0]['dest']
-
- return self.rules[initialStepID]
- '''
- return the next step to run in this transformation... this is either
- the initial step OR a neighbour of the last step... which one of these
- neighbours is the next step is determined by the application information
- of the said last step
-
- 0. if self._expired is true (i.e., a race condition occurred causing this
- context to be called after it terminated but before ptcal.stop()
- removed it from ptcal._mtContexts), raise error
- 1. if there is no last step, return initial step
- 2. filter through edges to find appropriate edge out of last step
- a) if none is found, reset lastStep, set self._expired flag, and
- return the application information of this entire transformation
- context
- b) otherwise, return step on the other end of the said edge
-
- Next step structure
- lastStepID --> successID --> nextID
- --> failID --> nextID
-
-
- Steps to find next
- 1- Filter edges and get (lastStepID, successID) and (lastStepID,failID) edges
- 2- Select success or fail according to _lastStep['applicationInfo']
- 3- Find this edge (nextPath, nextStepID) where nextPath is one of the success or fail ids.
-
-
- '''
- def nextStep(self) :
- if self._expired == True :
- raise RuntimeError('can not step in expired mtContext')
- elif self._lastStep == {} :
- ns = self._getInitialStep()
- if ns == None :
- return {'$err':'could not find initial transformation step'}
- self._lastStep = ns
- return ns
- else :
-
- def f(e) :
- return e['src'] == self._lastStep['id']
-
- edgesFromLastStep = filter(f,self.t['edges'])
-
- if len(edgesFromLastStep) == 0 :
- ai = self._applicationInfo()
- self._lastStep = {}
- self._expired = True
- return ai
- else :
-
- targetLinkID=None
- resString = None
- if self._lastStep['applicationInfo'] == TC.SUCCEEDED :
- resString = "success"
- elif self._lastStep['applicationInfo'] == TC.FAILED:
- resString = "fail"
- else: #exception
- resString = "exception"
-
- for edgeLS in edgesFromLastStep:
- if 'output' in self.t['nodes'][edgeLS['dest']] and self.t['nodes'][edgeLS['dest']]['output']['value'] == resString:
- targetLinkID=edgeLS['dest']
- break
- elif 'output' not in self.t['nodes'][edgeLS['dest']]:
- if self.t['nodes'][edgeLS['dest']]['$type']==self.metamodel+"/endExceptionPort" and resString=='exception':
- targetLinkID=edgeLS['dest']
- break
- elif self.t['nodes'][edgeLS['dest']]['$type']==self.metamodel+"/endSuccessPort" and resString=='success':
- targetLinkID=edgeLS['dest']
- break
- elif self.t['nodes'][edgeLS['dest']]['$type']==self.metamodel+"/endFailPort" and resString=='fail':
- targetLinkID=edgeLS['dest']
- break
- if 'input' in self.t['nodes'][targetLinkID]:
- self.nextInput = self.t['nodes'][targetLinkID]['input']['value']
-
- def f(e) :
- return e['src'] == targetLinkID
- nodesAfterLastStep = filter(f,self.t['edges'])
-
- nextStepID = nodesAfterLastStep[0]['dest']
-
- if nextStepID in self.rules:
- self._lastStep = self.rules[nextStepID]
- else:
- if self.t['nodes'][nextStepID]['$type']==self.metamodel+"/EndSuccess":
- self._lastStep = {'trafoResult':TC.SUCCEEDED,
- 'feedbackReceived':'True'}
- elif self.t['nodes'][nextStepID]['$type']==self.metamodel+"/EndFail":
- self._lastStep = {'trafoResult':TC.FAILED,
- 'feedbackReceived':'True'}
- elif self.t['nodes'][nextStepID]['$type']==self.metamodel+"/EndException":
- self._lastStep = {'trafoResult':TC.EXCEPTION,
- 'feedbackReceived':'True'}
-
- return self._lastStep
-
-
- '''
- set the application information of the last step '''
- def setLastStepApplicationInfo(self,applicationInfo) :
- if applicationInfo == TC.SUCCEEDED :
- self._notApplicable = False
- self._lastStep['applicationInfo'] = applicationInfo
- def isLastStepFeedbackReceived(self) :
- return (not self._expired and self._lastStep=={}) or \
- 'feedbackReceived' in self._lastStep
|