import "logging.eol"; import "common.eol"; import "helper.eol"; import "debug.eol"; pre { ("Transforming..").log(1); //TODO:export configuration //use data mapping var useDataMapping = false; //?? var transformAlt = true; //generate functions to simulate the SUT var simulateSUT = false; //generate testcases var createTestcase = true; //generate SimpleDataType subtype var generateSDT = true; //resolve Integer to integer, etc. var resolvePredefined = true; //generate qualified names var qualifiedNaming = false; //generate age timers var generateAgeTimers = true; var predefined = new Set(); predefined.add("String"); predefined.add("Integer"); predefined.add("Boolean"); predefined.add("Verdict"); var mpElapsedTime; var f = new TTCN!TTCN3File(); var stack = new Map(); } post { //Clean orphaned module defnition lists for (m in TTCN!TTCN3Module.allInstances()) { if (m.defs.isDefined() and m.defs.definitions.isEmpty()) { delete m.defs; } } ("Done!").log(1); } rule Package2Module transform p : TDL!Package to m : TTCN!TTCN3Module { //guard : true //TODO: to support annotations and test objectives // need to add contained comments as a feature // in modules //TODO: to support annotations and comments for elements // need to add contained comments as a feature // in module definitions (" "+p.name).log(1); m.name = p.TTCNname(); f.modules.add(m); if (p.packagedElement.notEmpty() or p.`import`.notEmpty()) { m.defs = new TTCN!ModuleDefinitionsList(); if (generateAgeTimers) { //default MP for component lifetime var md = new TTCN!ModuleDefinition(); md.def = new TTCN!ModuleParDef; md.def.param = new TTCN!ModulePar; md.def.param.type = new TTCN!Type(); md.def.param.type.`pre` = "float"; md.def.param.list = new TTCN!ModuleParList; var mp = new TTCN!ModuleParameter; mp.name = "mp_componentElapsedTimerMaxDuration"; md.def.param.list.params.add(mp); mpElapsedTime = mp; m.defs.definitions.add(md); } } } rule ElementImport2ImportDef transform ei : TDL!ElementImport to i : TTCN!ImportDef { i.name = ei.importedPackage.equivalent().name; //i.name = "mappings"; var md = new TTCN!ModuleDefinition(); md.def = i; var m = ei.eContainer.equivalent(); m.defs.definitions.add(md); if (ei.importedElement.notEmpty()) { i.importSpec = new TTCN!ImportSpec(); for (ie in ei.importedElement.select(x|x.equivalent().isDefined())) { var e = new TTCN!ImportElement(); //TODO: make reusable, extend to other types if (ie.isKindOf(TDL!DataType) or ie.isKindOf(TDL!GateType) or ie.isKindOf(TDL!ComponentType)) { e.type = new TTCN!ImportTypeDefSpec(); e.~kind = e.type; } else if (ie.isKindOf(TDL!DataInstance)) { //TODO: check if it is a constant instead if (ie.isValue()) { e.const = new TTCN!ImportConstSpec(); e.~kind = e.const; } else { e.template = new TTCN!ImportTemplateSpec(); e.~kind = e.template; } } else if (ie.isKindOf(TDL!Function)) { e.`function` = new TTCN!ImportFunctionSpec(); e.~kind = e.`function`; } else { //TODO: handle others ("Imports for " + ie.type.name + " are not supported yet!").log(1); delete e; continue; } e.~kind.idOrAll = new TTCN!IdentifierListOrAllWithExcept(); e.~kind.idOrAll.idList = new TTCN!IdentifierList(); //TODO: resolve if imported from mappings? //TODO: extract equivalent name resolution to an operation if (e.const.isDefined()) { e.~kind.idOrAll.idList.ids.add(ie.equivalent().defs.list.get(0).name); } else if (e.template.isDefined()) { e.~kind.idOrAll.idList.ids.add(ie.equivalent().base.name); } else { e.~kind.idOrAll.idList.ids.add(ie.equivalent().name); } i.importSpec.element.add(e); } } else { i.all = new TTCN!AllWithExcepts(); } } rule DRM2ImportDef transform drm : TDL!DataResourceMapping to i : TTCN!ImportDef { guard : useDataMapping i.name = drm.resourceURI.replaceAll("\"",""); //i.name = "mappings"; var md = new TTCN!ModuleDefinition(); md.def = i; var m = drm.eContainer.equivalent(); m.defs.definitions.add(md); i.importSpec = new TTCN!ImportSpec(); } rule DEM2ImportElement transform dem : TDL!DataElementMapping to e : TTCN!ImportElement { guard : useDataMapping var i = dem.dataResourceMapping.equivalent(); i.importSpec.element.add(e); if (dem.mappableDataElement.isKindOf(TDL!DataType)) { e.type = new TTCN!ImportTypeDefSpec(); e.type.idOrAll = new TTCN!IdentifierListOrAllWithExcept(); e.type.idOrAll.idList = new TTCN!IdentifierList(); e.type.idOrAll.idList.ids.add(dem.elementURI.replaceAll("\"","")); } else { if (dem.mappableDataElement.isKindOf(TDL!DataInstance)) { e.template = new TTCN!ImportTemplateSpec(); e.template.idOrAll = new TTCN!IdentifierListOrAllWithExcept(); e.template.idOrAll.idList = new TTCN!IdentifierList(); e.template.idOrAll.idList.ids.add(dem.elementURI.replaceAll("\"","")); } else { } //TODO: handle others } } //Generative, use mappings instead rule SimpleDT2R transform dt : TDL!SimpleDataType to s : TTCN!SubTypeDefNamed { guard : not useDataMapping and not (resolvePredefined and predefined.includes(dt.name)) s.name = dt.TTCNname(); s.type = new TTCN!Type(); //TODO: handle predefined data types var m = dt.eContainer.equivalent(); if (generateSDT) { //create default simple data type? s.type.ref = new TTCN!TypeReference(); s.type.ref.head = m.getSDT(); } else { s.type.`pre` = "charstring"; } var t = m.createTypeDefBody(); t.sub = s; } //Generative, use mappings instead rule StructuredDT2R transform dt : TDL!StructuredDataType to r : TTCN!RecordDefNamed { guard : not useDataMapping r.name = dt.TTCNname(); var module = dt.eContainer.equivalent(); var t = module.createTypeDefBody(); t.structured = new TTCN!StructuredTypeDef(); t.structured.record = r; r.body = new TTCN!StructDefBody(); } //Generative, use mappings instead rule CollectionDT2RoR transform dt : TDL!CollectionDataType to r : TTCN!RecordOfDefNamed { guard : not useDataMapping r.name = dt.TTCNname(); var module = dt.eContainer.equivalent(); var t = module.createTypeDefBody(); t.structured = new TTCN!StructuredTypeDef(); t.structured.recordOf = r; r.type = dt.itemType.getTTCNType(); } rule M2SFD transform m : TDL!Member to f : TTCN!StructFieldDef { guard : not useDataMapping f.name = m.TTCNname(); if (m.isOptional) { f.optional = "optional"; } f.type = m.dataType.getTTCNType(); var r = m.eContainer.equivalent(); r.body.defs.add(f); } //Generative, use mappings instead rule Action2FD transform a : TDL!Action to fd : TTCN!FunctionDef { guard : not useDataMapping fd.name = a.TTCNname(); var md = new TTCN!ModuleDefinition(); md.def = fd; var m = a.eContainer.equivalent(); m.defs.definitions.add(md); fd.statement = new TTCN!StatementBlock(); //TODO: fix formatting if (a.formalParameter.notEmpty()) { fd.parameterList = new TTCN!FunctionFormalParList(); for (p in a.formalParameter) { var fp = new TTCN!FunctionFormalPar(); //TODO: support for value parameters? // -> process annotation // -> extract into a rule to make use of equivalent? fp.template = new TTCN!FormalTemplatePar(); fp.~kind = fp.template; fp.~kind.name = p.TTCNname(); //TODO: direction support? fp.~kind.type = p.dataType.getTTCNType(); fd.parameterList.params.add(fp); } } //TODO: add support for body? } //Generative, use mappings instead rule Function2FD transform f : TDL!Function to fd : TTCN!FunctionDef { guard : not useDataMapping fd.name = f.TTCNname(); var md = new TTCN!ModuleDefinition(); md.def = fd; var m = f.eContainer.equivalent(); m.defs.definitions.add(md); fd.statement = new TTCN!StatementBlock(); //TODO: fix formatting if (f.formalParameter.notEmpty()) { fd.parameterList = new TTCN!FunctionFormalParList(); for (p in f.formalParameter) { var fp = new TTCN!FunctionFormalPar(); //TODO: support for value parameters? // -> process annotation // -> extract into a rule to make use of equivalent? fp.template = new TTCN!FormalTemplatePar(); fp.~kind = fp.template; fp.~kind.name = p.TTCNname(); //TODO: direction support? fp.~kind.type = p.dataType.getTTCNType(); fd.parameterList.params.add(fp); } } fd.returnType = new TTCN!ReturnType(); fd.returnType.type = f.returnType.getTTCNType(); //TODO: add support for body? //TODO: add distinction between value and template? } rule TC2FD transform tc : TDL!TestConfiguration to fd : TTCN!FunctionDef { fd.name = "setupTestConfiguration_"+tc.TTCNname(); var md = new TTCN!ModuleDefinition(); md.def = fd; var m = tc.eContainer.equivalent(); m.defs.definitions.add(md); //CREATE MTC TYPE var mtc = m.createTypeDefBody(); mtc.structured = new TTCN!StructuredTypeDef(); mtc.structured.component = new TTCN!ComponentDef(); mtc.structured.component.name = "MTC_"+tc.TTCNname(); //CREATE SYSTEM TYPE //TODO: Is this necessary? var sut = m.createTypeDefBody(); sut.structured = new TTCN!StructuredTypeDef(); sut.structured.component = new TTCN!ComponentDef(); sut.structured.component.name = "SYSTEM_"+tc.TTCNname(); fd.runsOn = new TTCN!RunsOnSpec(); fd.runsOn.component = mtc.structured.component; fd.statement = new TTCN!StatementBlock(); var sl = new TTCN!FunctionStatementList(); fd.statement.stat.add(sl); //create components for (ci in tc.componentInstance.select(c|simulateSUT or c.role = TDL!ComponentInstanceRole#Tester)) { var s = new TTCN!FunctionStatement(); s.basic = new TTCN!BasicStatements(); s.basic.assign = new TTCN!Assignment(); s.basic.assign.ref = new TTCN!VariableRef(); s.basic.assign.ref.ref = new TTCN!ReferencedValue(); s.basic.assign.ref.ref.head = new TTCN!Head(); s.basic.assign.ref.ref.head.target = ci.equivalent(); s.basic.assign.expression = new TTCN!OpCall(); s.basic.assign.expression.configuration = new TTCN!ConfigurationOps(); s.basic.assign.expression.configuration.create = new TTCN!CreateOp(); s.basic.assign.expression.configuration.create.type = ci.type.equivalent(); sl.statements.add(s); sl.sc.add(";"); } //merge ports of SUT components into sut if (not simulateSUT) { for (c in tc.connection) { if (c.endPoint.get(0).component.role = TDL!ComponentInstanceRole#SUT and c.endPoint.get(1).component.role = TDL!ComponentInstanceRole#Tester ) { c.endPoint.get(0).mergeIntoSUT(sut); } if (c.endPoint.get(1).component.role = TDL!ComponentInstanceRole#SUT and c.endPoint.get(0).component.role = TDL!ComponentInstanceRole#Tester ) { c.endPoint.get(1).mergeIntoSUT(sut); } } } //handle multiple connections to the same gate for (c in tc.connection) { if (//c.endPoint.get(0).component.role = TDL!ComponentInstanceRole#SUT and c.endPoint.get(1).component.role = TDL!ComponentInstanceRole#Tester ) { c.endPoint.get(1).createConnectionPort(); } if (//c.endPoint.get(1).component.role = TDL!ComponentInstanceRole#SUT and c.endPoint.get(0).component.role = TDL!ComponentInstanceRole#Tester ) { c.endPoint.get(0).createConnectionPort(); } } //create connections for (c in tc.connection) { if (simulateSUT or (c.endPoint.get(0).component.role = TDL!ComponentInstanceRole#Tester and c.endPoint.get(1).component.role = TDL!ComponentInstanceRole#Tester )) { var s = new TTCN!FunctionStatement(); s.configuration = new TTCN!ConfigurationStatements(); s.configuration.connect = new TTCN!ConnectStatement(); s.configuration.connect.spec = new TTCN!SingleConnectionSpec(); s.configuration.connect.spec.port1 = c.endPoint.get(0).equivalent(); s.configuration.connect.spec.port2 = c.endPoint.get(1).equivalent(); sl.statements.add(s); sl.sc.add(";"); } else if ((c.endPoint.get(0).component.role = TDL!ComponentInstanceRole#SUT and c.endPoint.get(1).component.role = TDL!ComponentInstanceRole#SUT )) { //skip } else { var s = new TTCN!FunctionStatement(); s.configuration = new TTCN!ConfigurationStatements(); s.configuration.map = new TTCN!MapStatement(); s.configuration.map.spec = new TTCN!SingleConnectionSpec(); s.configuration.map.spec.port1 = c.endPoint.get(0).equivalent(); s.configuration.map.spec.port2 = c.endPoint.get(1).equivalent(); sl.statements.add(s); sl.sc.add(";"); } } } rule TD2FD transform td : TDL!TestDescription to fd : TTCN!FunctionDef { fd.name = td.TTCNname(); var md = new TTCN!ModuleDefinition(); md.def = fd; var m = td.eContainer.equivalent(); m.defs.definitions.add(md); fd.runsOn = new TTCN!RunsOnSpec(); fd.runsOn.component = ("MTC_"+td.testConfiguration.TTCNname()).getComponent(); fd.statement = new TTCN!StatementBlock(); stack.put(fd.name,new OrderedSet()); stack.get(fd.name).add(fd.statement); var sl = new TTCN!FunctionStatementList(); fd.statement.stat.add(sl); if (not createTestcase) { var s = new TTCN!FunctionStatement(); s.behavior = new TTCN!BehaviourStatements(); s.behavior.`function` = new TTCN!FunctionInstance(); s.behavior.`function`.ref = td.testConfiguration.equivalent(); sl.statements.add(s); sl.sc.add(";"); } for (ci in td.testConfiguration.componentInstance.select(c|simulateSUT or c.role = TDL!ComponentInstanceRole#Tester)) { var cf = new TTCN!FunctionDef(); cf.name = td.TTCNname()+"_"+ci.TTCNname()+"_main"; var md = new TTCN!ModuleDefinition(); md.def = cf; var m = td.eContainer.equivalent(); m.defs.definitions.add(md); cf.runsOn = new TTCN!RunsOnSpec(); cf.runsOn.component = ci.type.equivalent(); cf.statement = new TTCN!StatementBlock(); stack.put(cf.name,new OrderedSet()); stack.get(cf.name).add(cf.statement); var fs = new TTCN!FunctionStatement(); fs.configuration = new TTCN!ConfigurationStatements(); fs.configuration.startTc = new TTCN!StartTCStatement(); fs.configuration.startTc.ref = new TTCN!ComponentOrDefaultReference(); fs.configuration.startTc.ref.variable = new TTCN!VariableRef(); fs.configuration.startTc.ref.variable.ref = new TTCN!ReferencedValue(); fs.configuration.startTc.ref.variable.ref.head = new TTCN!Head(); fs.configuration.startTc.ref.variable.ref.head.target = ci.equivalent(); fs.configuration.startTc.`function` = new TTCN!FunctionInstance(); fs.configuration.startTc.`function`.ref = cf; sl.statements.add(fs); sl.sc.add(";"); } if (td.behaviourDescription.isDefined()) { td.behaviourDescription.behaviour.execute(); } stack.clear(); if (createTestcase) { var tc = new TTCN!TestcaseDef(); tc.name = "tc_"+td.TTCNname(); var tmd = new TTCN!ModuleDefinition(); tmd.def = tc; m.defs.definitions.add(tmd); tc.spec = new TTCN!ConfigSpec(); tc.spec.runsOn = new TTCN!RunsOnSpec(); tc.spec.runsOn.component = ("MTC_"+td.testConfiguration.TTCNname()).getComponent(); tc.spec.systemSpec = new TTCN!SystemSpec(); tc.spec.systemSpec.component = ("SYSTEM_"+td.testConfiguration.TTCNname()).getComponent(); tc.statement = new TTCN!StatementBlock(); stack.put(tc.name,new OrderedSet()); stack.get(tc.name).add(tc.statement); var tsl = new TTCN!FunctionStatementList(); tc.statement.stat.add(tsl); //setup configuration var tsc = new TTCN!FunctionStatement(); tsc.behavior = new TTCN!BehaviourStatements(); tsc.behavior.`function` = new TTCN!FunctionInstance(); tsc.behavior.`function`.ref = td.testConfiguration.equivalent(); tsl.statements.add(tsc); tsl.sc.add(";"); //start behaviour var tsb = new TTCN!FunctionStatement(); tsb.behavior = new TTCN!BehaviourStatements(); tsb.behavior.`function` = new TTCN!FunctionInstance(); tsb.behavior.`function`.ref = fd; tsl.statements.add(tsb); tsl.sc.add(";"); //all done var tsd = new TTCN!FunctionStatement(); tsd.configuration = new TTCN!ConfigurationStatements(); tsd.configuration.done = new TTCN!DoneStatement(); tsd.configuration.done.component = new TTCN!ComponentOrAny(); tsd.configuration.done.component.all = "all"; tsl.statements.add(tsd); tsl.sc.add(";"); } } rule GR2PR transform gr : TDL!GateReference to pr : TTCN!PortRef { guard : simulateSUT or gr.checkGateReference() var cr = new TTCN!ComponentRef(); pr.component = cr; if (simulateSUT or gr.component.role = TDL!ComponentInstanceRole#Tester ) { cr.ref = new TTCN!ComponentOrDefaultReference(); cr.ref.variable = new TTCN!VariableRef(); cr.ref.variable.ref = new TTCN!ReferencedValue(); cr.ref.variable.ref.head = new TTCN!Head(); cr.ref.variable.ref.head.target = gr.component.equivalent(); pr.port = gr.gate.equivalent(); } else { cr.system = "system"; //will be replaced with system port in TC2FD pr.port = gr.gate.equivalent(); //TODO: is there a case for cr.mtc? } } rule CT2C transform ct : TDL!ComponentType to c : TTCN!ComponentDef { c.name = ct.TTCNname(); var m = ct.eContainer.equivalent(); var t = m.createTypeDefBody(); t.structured = new TTCN!StructuredTypeDef(); t.structured.component = c; if (generateAgeTimers) { var ti = new TTCN!SingleVarInstance(); ti.name = "T_elapsedTimeOfComponent"; ti.ac = ":="; //TODO: Why is this needed? ti.expr = new TTCN!Value(); ti.expr.ref = new TTCN!ReferencedValue(); ti.expr.ref.head = new TTCN!Head; ti.expr.ref.head.target = mpElapsedTime; var d = new TTCN!ComponentDefList(); c.defs.add(d); d.sc = ";"; d.element = new TTCN!ComponentElementDef(); d.element.timer = new TTCN!TimerInstance(); d.element.timer.list = new TTCN!VarList(); d.element.timer.list.variables.add(ti); } } rule CI2V transform ci : TDL!ComponentInstance to v : TTCN!SingleVarInstance { guard : simulateSUT or ci.role = TDL!ComponentInstanceRole#Tester v.name = ci.TTCNname(); var d = new TTCN!ComponentDefList(); d.sc = ";"; d.element = new TTCN!ComponentElementDef(); d.element.variable = new TTCN!VarInstance(); d.element.variable.listType = new TTCN!Type(); d.element.variable.listType.ref = new TTCN!TypeReference(); d.element.variable.listType.ref.head = ci.type.equivalent(); d.element.variable.list = new TTCN!VarList(); d.element.variable.list.variables.add(v); var mtc = ("MTC_"+ci.eContainer().TTCNname()).getComponent(); mtc.defs.add(d); } rule GT2P transform gt : TDL!GateType to p : TTCN!PortDef { //guard : true p.name = gt.TTCNname(); var m = gt.eContainer.equivalent(); var t = m.createTypeDefBody(); t.structured = new TTCN!StructuredTypeDef(); t.structured.port = p; p.body = new TTCN!PortDefBody(); p.body.attribs = new TTCN!PortDefAttribs(); if (gt.kind.name = "Message") { p.body.attribs.message = new TTCN!MessageAttribs(); //FIX var ml = new TTCN!MessageList(); ml.direction = "inout"; ml.allOrTypeList = new TTCN!AllOrTypeList(); ml.allOrTypeList.typeList = new TTCN!TypeList(); p.body.attribs.message.messages.add(ml); //ADAPT for (dt in gt.dataType) { var t = dt.getTTCNType(); ml.allOrTypeList.typeList.types.add(t); } } else { //TODO: handle procedure based gates.. } } rule GI2PE transform gi : TDL!GateInstance to pe : TTCN!PortElement { pe.name = gi.TTCNname(); var c = gi.eContainer.equivalent(); var d = new TTCN!ComponentDefList(); c.defs.add(d); d.sc = ";"; d.element = new TTCN!ComponentElementDef(); d.element.port = new TTCN!PortInstance(); d.element.port.ref = gi.type.equivalent(); d.element.port.instances.add(pe); } rule T2TI transform t : TDL!Timer to ti : TTCN!SingleVarInstance { ti.name = t.TTCNname(); var c = t.eContainer.equivalent(); var d = new TTCN!ComponentDefList(); c.defs.add(d); d.sc = ";"; d.element = new TTCN!ComponentElementDef(); d.element.timer = new TTCN!TimerInstance(); d.element.timer.list = new TTCN!VarList(); d.element.timer.list.variables.add(ti); } rule V2VI transform v : TDL!Variable to vi : TTCN!SingleVarInstance { vi.name = v.TTCNname(); var c = v.eContainer.equivalent(); var d = new TTCN!ComponentDefList(); c.defs.add(d); d.sc = ";"; d.element = new TTCN!ComponentElementDef(); d.element.variable = new TTCN!VarInstance(); d.element.variable.listType = v.dataType.getTTCNType(); d.element.variable.list = new TTCN!VarList(); d.element.variable.list.variables.add(vi); } rule SimpleDI2TD transform di : TDL!SimpleDataInstance to td : TTCN!TemplateDef { //guard : false guard : not useDataMapping and not di.isValue() and di.dataType.name <> "Verdict" var md = new TTCN!ModuleDefinition(); md.def = td; var m = di.eContainer.equivalent(); m.defs.definitions.add(md); td.base = new TTCN!BaseTemplate(); td.base.name = di.TTCNname(); td.base.type = di.dataType.getTTCNType(); var tb = new TTCN!TemplateBody(); td.body = tb; tb.simple = new TTCN!SimpleSpec(); tb.simple.expr = new TTCN!Value(); tb.simple.expr.predef = new TTCN!PredefinedValue(); tb.simple.expr.predef.charString = "\""+di.name+"\""; } rule SimpleDI2C transform di : TDL!SimpleDataInstance to cd : TTCN!ConstDef { //guard : false guard : not useDataMapping and di.isValue() var md = new TTCN!ModuleDefinition(); md.def = cd; var m = di.eContainer.equivalent(); m.defs.definitions.add(md); cd.type = di.dataType.getTTCNType(); cd.defs = new TTCN!ConstList(); var scd = new TTCN!SingleConstDef; scd.name = di.TTCNname(); scd.expr = new TTCN!Value(); scd.expr.predef = new TTCN!PredefinedValue(); scd.expr.predef.charString = "\""+di.name+"\""; scd.assign = ":="; //TODO: this shall not be necessary cd.defs.list.add(scd); } rule StructuredDI2TD transform di : TDL!StructuredDataInstance to td : TTCN!TemplateDef { //guard : false guard : not useDataMapping and not di.isValue() var md = new TTCN!ModuleDefinition(); md.def = td; var m = di.eContainer.equivalent(); m.defs.definitions.add(md); td.base = new TTCN!BaseTemplate(); td.base.name = di.TTCNname(); td.base.type = di.dataType.getTTCNType(); //TODO:unassigned fields //check if there is unassigned member handling //handle accordingly -> separate branch under .field var tb = new TTCN!TemplateBody(); td.body = tb; if ((di.unassignedMember.isDefined() and not di.dataType.member.forAll(m| di.memberAssignment.exists(ma|ma.member = m))) //does it need to be recursive? or di.memberAssignment.exists(ma| ma.memberSpec.isKindOf(TDL!AnyValue) or ma.memberSpec.isKindOf(TDL!AnyValueOrOmit)) ) { //NOTE: implementation treats unset unassigned member (and other enums) as if // they have been set to the first value by default. //TODO: add none / omit as default option? // ("Wildcard: "+di.name).log(1); // (" "+di.unassignedMember+ // " "+di.unassignedMember.isDefined()+ // " "+(not di.dataType.member.forAll(m|di.memberAssignment.exists(ma|ma.member = m)))+ // " "+di.memberAssignment.exists(ma|ma.memberSpec.isKindOf(TDL!AnyValue) // or ma.memberSpec.isKindOf(TDL!AnyValueOrOmit))).log(1); tb.field = di.transformWildcardMemberAssignment(); } else { ("Simple: "+di.name).log(1); tb.simple = new TTCN!SimpleSpec(); tb.simple.expr = di.transformMemberAssignment(); } } rule StructuredDI2C transform di : TDL!StructuredDataInstance to cd : TTCN!ConstDef { //guard : false guard : not useDataMapping and di.isValue() var md = new TTCN!ModuleDefinition(); md.def = cd; var m = di.eContainer.equivalent(); m.defs.definitions.add(md); cd.type = di.dataType.getTTCNType(); cd.defs = new TTCN!ConstList(); var scd = new TTCN!SingleConstDef; scd.name = di.TTCNname(); scd.expr = di.transformMemberAssignment(); scd.assign = ":="; //TODO: this shall not be necessary cd.defs.list.add(scd); } rule CollectionDI2TD //TODO: the specification in the standard is insufficient transform di : TDL!CollectionDataInstance to td : TTCN!TemplateDef { //guard : false guard : not useDataMapping and not di.isValue() var md = new TTCN!ModuleDefinition(); md.def = td; var m = di.eContainer.equivalent(); m.defs.definitions.add(md); td.base = new TTCN!BaseTemplate(); td.base.name = di.TTCNname(); td.base.type = di.dataType.getTTCNType(); //TODO:unassigned fields //check if there is unassigned member handling //handle accordingly -> separate branch under .field var tb = new TTCN!TemplateBody(); td.body = tb; tb.simple = new TTCN!SimpleSpec(); tb.simple.expr = new TTCN!ArrayExpression(); tb.simple.expr.list = new TTCN!ArrayElementExpressionList(); for (i in di.item) { if (i.isKindOf(TDL!DataInstanceUse) and i.dataInstance.isDefined()) { var v = new TTCN!Value(); v.ref = new TTCN!ReferencedValue(); v.ref.head = new TTCN!Head(); var e = i.dataInstance.equivalent(); if (e.isKindOf(TTCN!TemplateDef)) { v.ref.head.target = e.base; } else if (e.isKindOf(TTCN!ConstDef)) { v.ref.head.target = e.defs.list.get(0); } else { //what else can it be? } tb.simple.expr.list.expr.add(v); } } } rule CollectionDI2C //TODO: the specification in the standard is insufficient transform di : TDL!CollectionDataInstance to cd : TTCN!ConstDef { //guard : false guard : not useDataMapping and di.isValue() var md = new TTCN!ModuleDefinition(); md.def = cd; var m = di.eContainer.equivalent(); m.defs.definitions.add(md); cd.type = di.dataType.getTTCNType(); cd.defs = new TTCN!ConstList(); var scd = new TTCN!SingleConstDef; scd.name = di.TTCNname(); scd.expr = new TTCN!ArrayExpression(); scd.expr.list = new TTCN!ArrayElementExpressionList(); for (i in di.item) { if (i.isKindOf(TDL!DataInstanceUse) and i.dataInstance.isDefined()) { var v = new TTCN!Value(); v.ref = new TTCN!ReferencedValue(); v.ref.head = new TTCN!Head(); var e = i.dataInstance.equivalent(); if (e.isKindOf(TTCN!TemplateDef)) { v.ref.head.target = e.base; //TODO: is that even possible here? } else if (e.isKindOf(TTCN!ConstDef)) { v.ref.head.target = e.defs.list.get(0); } else { //what else can it be? } scd.expr.list.expr.add(v); } } scd.assign = ":="; //TODO: this shall not be necessary cd.defs.list.add(scd); } operation TTCN!TTCN3Module createTypeDefBody() : TTCN!TypeDefBody{ var md = new TTCN!ModuleDefinition(); md.def = new TTCN!TypeDef(); md.def.body = new TTCN!TypeDefBody(); self.defs.definitions.add(md); return md.def.body; } operation Any transformSingleMemberAssignment(m : TDL!Member, mad : TDL!DataUse) : TTCN!TemplateBody { var body = new TTCN!TemplateBody(); if (mad.isDefined() and mad.isKindOf(TDL!DataInstanceUse)) { if (mad.dataInstance.isDefined() and mad.argument.isEmpty()) { body.simple = new TTCN!SimpleSpec(); body.simple.expr = new TTCN!Value(); body.simple.expr.ref = new TTCN!ReferencedValue(); body.simple.expr.ref.head = new TTCN!Head(); //Template ->target = BaseTemplate reference //Constant ->target = SingleConstDef reference var e = mad.dataInstance.equivalent(); if (e.isKindOf(TTCN!TemplateDef)) { body.simple.expr.ref.head.target = e.base; } else if (e.isKindOf(TTCN!ConstDef)) { body.simple.expr.ref.head.target = e.defs.list.get(0); } else { //what else can it be? } //reduction //use extended field references var useEFR = mad.reduction.exists(mr|mr.collectionIndex.isDefined()); if (useEFR) { for (mr in mad.reduction) { if (mr.member.isDefined()) { var efr = new TTCN!ExtendedFieldReference(); efr.field = mr.member.equivalent(); body.simple.expr.ref.fields.add(efr); } if (mr.collectionIndex.isDefined() and mr.collectionIndex.dataInstance.isDefined()) { var efr = new TTCN!ExtendedFieldReference(); efr.array = new TTCN!Value(); efr.array.ref = new TTCN!ReferencedValue(); efr.array.ref.head = new TTCN!Head(); var ci = mr.collectionIndex.dataInstance.equivalent(); if (ci.isKindOf(TTCN!TemplateDef)) { efr.array.ref.head.target = ci.base; } else if (ci.isKindOf(TTCN!ConstDef)) { efr.array.ref.head.target = ci.defs.list.get(0); } else { //what else can it be? } body.simple.expr.ref.fields.add(efr); } } } else { var t = body.simple.expr.ref.head; for (mr in mad.reduction) { if (mr.member.isDefined()) { t.tail = new TTCN!RefValueTail(); t.tail.value = mr.member.equivalent(); } t = t.tail; } } } else { //nested anonymous definitions //or overriding body.field = mad.transformWildcardMemberAssignment(); } } else { body.simple = new TTCN!SimpleSpec(); body.simple.spec = new TTCN!SimpleTemplateSpec(); body.simple.spec.expr = new TTCN!SingleTemplateExpression(); body.simple.spec.expr.symbol = new TTCN!MatchingSymbol(); if (mad.isUndefined() and self.unassignedMember.isDefined() and self.unassignedMember.name = "AnyValueOrOmit") { if (m.isOptional) { body.simple.spec.expr.symbol.anyornone = "*"; } else { body.simple.spec.expr.symbol.any = "?"; } } else if (mad.isUndefined() and self.unassignedMember.isDefined() and self.unassignedMember.name = "AnyValue") { body.simple.spec.expr.symbol.any = "?"; } else if (mad.isDefined() and mad.isKindOf(TDL!AnyValue)) { body.simple.spec.expr.symbol.any = "?"; } else if (mad.isDefined() and mad.isKindOf(TDL!AnyValueOrOmit)) { body.simple.spec.expr.symbol.anyornone = "*"; } else if (mad.isDefined()) { ("TODO: Implement?").log(1); } } return body; } operation TDL!StaticDataUse transformWildcardMemberAssignment() : TTCN!FieldSpecList { //dataInstance? or inferred type //unassignedMember? //argument -> ParameterBinding (parameter:Member, dataUse:DataUse) //reduction? -> MemberReference var field = new TTCN!FieldSpecList(); var t; if (self.dataInstance.isDefined()) { t = self.dataInstance.dataType; ("DI:"+self.dataInstance.name).log(1); } else { if (self.eContainer.isKindOf(TDL!ParameterBinding)) { t = self.eContainer.parameter.dataType; } else if (self.eContainer.isKindOf(TDL!MemberAssignment)) { t = self.eContainer.member.dataType; } else { ("TODO: Context Not Implemented Yet").log(1); } } for (m in t.member) { var fs = new TTCN!FieldSpec(); fs.ref = m.equivalent(); var mad; var ma = self.argument.selectOne(a|a.parameter = m); //default: no wildcard, defined //in case not defined, check for inherited if (ma.isDefined()) { mad = ma.dataUse; } else if (ma.isUndefined() and self.isKindOf(TDL!DataInstanceUse) and self.dataInstance.isDefined()) { var mai = self.dataInstance.memberAssignment.selectOne(a|a.member = m); if (mai.isDefined()) { mad = mai.memberSpec; } } else { } fs.body = self.transformSingleMemberAssignment(m, mad); field.spec.add(fs); } return field; } operation TDL!StructuredDataInstance transformWildcardMemberAssignment() : TTCN!FieldSpecList { var field = new TTCN!FieldSpecList(); for (m in self.dataType.member) { var fs = new TTCN!FieldSpec(); fs.ref = m.equivalent(); var ma = self.memberAssignment.selectOne(ma|ma.member = m); var mad; if (ma.isDefined()) { mad = ma.memberSpec; } fs.body = new TTCN!TemplateBody(); fs.body = self.transformSingleMemberAssignment(m, mad); field.spec.add(fs); } return field; } //TODO: deprecated? operation TDL!StructuredDataInstance transformMemberAssignment() : TTCN!CompoundExpression { var expr; if (not self.memberAssignment.isEmpty()) { expr = new TTCN!FieldExpressionList(); for (ma in self.memberAssignment) { var fes = new TTCN!FieldExpressionSpec(); fes.fieldRef = ma.member.equivalent(); //ma.memberSpec fes.expr = new TTCN!Value(); if (ma.memberSpec.isKindOf(TDL!DataInstanceUse) and ma.memberSpec.dataInstance.isDefined()) { fes.expr.ref = new TTCN!ReferencedValue(); fes.expr.ref.head = new TTCN!Head(); //Template ->target = BaseTemplate reference //Constant ->target = SingleConstDef reference var e = ma.memberSpec.dataInstance.equivalent(); if (e.isKindOf(TTCN!TemplateDef)) { fes.expr.ref.head.target = e.base; } else if (e.isKindOf(TTCN!ConstDef)) { fes.expr.ref.head.target = e.defs.list.get(0); } else { //what else can it be? } //TODO: handle overriding parameters? } else { fes.expr.predef = new TTCN!PredefinedValue(); fes.expr.predef.charString = "\"TODO: Not Implemented Yet\""; } expr.specs.add(fes); } //TODO: handle unassigned members? -> add guards to corresponding rule //TODO: handle special characters var assigned = self.memberAssignment.collect(ma|ma.member); for (m in self.dataType.member.excludingAll(assigned)) { (self.name + ": Skipping unassigned member "+m.name).log(1); } } else { expr = new TTCN!ArrayExpression(); } return expr; } operation TDL!DataType getTTCNType() : TTCN!Type { var type = new TTCN!Type(); if (resolvePredefined and self.name == "String") { //TODO: add support for universal type.`pre` = "charstring"; } else if (resolvePredefined and self.name == "Integer") { type.`pre` = "integer"; } else if (resolvePredefined and self.name == "Boolean") { type.`pre` = "boolean"; } else if (resolvePredefined and self.name == "Verdict") { type.`pre` = "verdicttype"; } else { //TODO: use data mapping to overide predefined? if (useDataMapping) { //TODO: handle predefined types? //t.`pre` = "TODO_"+dt.name; //use mappings, simple approach var mapping = TDL!DataElementMapping.allInstances().select(m|m.mappableDataElement = self).first(); if (mapping.isDefined()) { //t.ref = new TTCN!TypeReference(); //TODO: check if defined //t.ref.head = mapping.elementURI; type.`pre` = mapping.elementURI.replaceAll("\"",""); } else { type.`pre` = "MAP_"+self.TTCNname(); } } else { type.ref = new TTCN!TypeReference(); //TODO: check if defined type.ref.head = self.equivalent(); } } return type; } @cached operation TTCN!TTCN3Module getSDT() : TTCN!SubTypeDefNamed { if (self.~sdt.isUndefined()) { var sdt = new TTCN!SubTypeDefNamed(); sdt.name = "SimpleDataType"; sdt.type = new TTCN!Type(); //TODO: make configurable? sdt.type.`pre` = "charstring"; var body = self.createTypeDefBody(); body.sub = sdt; self.~sdt = sdt; } return self.~sdt; } @cached operation String getComponent() : TTCN!ComponentDef { return TTCN!ComponentDef.allInstances().select(c|c.name = self).first(); } @cached operation String getFunction() : TTCN!FunctionDef { return TTCN!FunctionDef.allInstances().select(c|c.name = self).first(); } operation TDL!GateReference checkGateReference() : Boolean { var accepted = false; if (self.component.role = TDL!ComponentInstanceRole#Tester) { accepted = true; } if (self.component.role = TDL!ComponentInstanceRole#SUT) { if (self.eContainer.isKindOf(TDL!Connection)) { var opposite = self.eContainer.endPoint.select(e|e <> self).first(); if (opposite.component.role = TDL!ComponentInstanceRole#Tester) { accepted = true; } } } return accepted; } operation TDL!GateReference mergeIntoSUT(sut : TTCN!TypeDefBody) { var pe = new TTCN!PortElement(); pe.name = self.component.TTCNname()+"_"+self.gate.TTCNname(); var d = new TTCN!ComponentDefList(); sut.structured.component.defs.add(d); d.sc = ";"; d.element = new TTCN!ComponentElementDef(); d.element.port = new TTCN!PortInstance(); d.element.port.ref = self.gate.type.equivalent(); d.element.port.instances.add(pe); self.equivalent().port = pe; } //TODO: remove parameter? operation TDL!GateReference createConnectionPort() { if (self.eContainer.isKindOf(TDL!Connection)) { var opposite = self.eContainer.endPoint.select(e|e <> self).first(); var pe = new TTCN!PortElement(); pe.name = self.gate.TTCNname()+"_to_"+opposite.component.TTCNname()+"_"+opposite.gate.TTCNname(); var d = new TTCN!ComponentDefList(); self.component.type.equivalent().defs.add(d); d.sc = ";"; d.element = new TTCN!ComponentElementDef(); d.element.port = new TTCN!PortInstance(); d.element.port.ref = self.gate.type.equivalent(); d.element.port.instances.add(pe); //TODO: check this has no side effects self.equivalent().port = pe; } else { //TODO: handle? } } operation TDL!DataInstanceUse getTemplateBody() : TTCN!TemplateBody { var tb = new TTCN!TemplateBody(); tb.simple = new TTCN!SimpleSpec(); tb.simple.expr = new TTCN!Value(); if (useDataMapping) { var mapping = TDL!DataElementMapping.allInstances().select(m|m.mappableDataElement = self.dataInstance).first(); tb.simple.expr.predef = new TTCN!PredefinedValue(); if (mapping.isDefined()) { //t.ref = new TTCN!TypeReference(); //TODO: check if defined //t.ref.head = mapping.elementURI; tb.simple.expr.predef.charString = mapping.elementURI.replaceAll("\"",""); } else { tb.simple.expr.predef.charString = "MAP_"+self.dataInstance.name; } } else { tb.simple.expr.ref = new TTCN!ReferencedValue(); tb.simple.expr.ref.head = new TTCN!Head(); tb.simple.expr.ref.head.target = self.dataInstance.equivalent().base; } return tb; } operation TDL!Interaction executeSource() : TTCN!FunctionStatementList { var ssl = new TTCN!FunctionStatementList(); var sfs = new TTCN!FunctionStatement(); sfs.communication = new TTCN!CommunicationStatements(); sfs.communication.send = new TTCN!SendStatement(); //sfs.communication.send.port = self.sourceGate.gate.equivalent(); sfs.communication.send.port = self.sourceGate.equivalent().port; sfs.communication.send.send = new TTCN!PortSendOp(); sfs.communication.send.send.template = new TTCN!InLineTemplate(); sfs.communication.send.send.template.template = self.argument.getTemplateBody(); ssl.statements.add(sfs); ssl.sc.add(";"); return ssl; } operation TDL!Interaction executeTarget(t : TDL!Target) : TTCN!FunctionStatementList { var tsl = new TTCN!FunctionStatementList(); var tfs = new TTCN!FunctionStatement(); tfs.communication = new TTCN!CommunicationStatements(); tfs.communication.receive = new TTCN!ReceiveStatement(); tfs.communication.receive.any = new TTCN!PortOrAny(); //tfs.communication.receive.any.ref = t.targetGate.gate.equivalent(); tfs.communication.receive.any.ref = t.targetGate.equivalent().port; tfs.communication.receive.receive = new TTCN!PortReceiveOp(); tfs.communication.receive.receive.template = new TTCN!InLineTemplate(); tfs.communication.receive.receive.template.template = self.argument.getTemplateBody(); tsl.statements.add(tfs); tsl.sc.add(";"); return tsl; } operation TDL!Interaction execute() { //TODO: needs adapting to context // add a statement block stack for each component during transformation? //TODO: simplify //source behaviour if (simulateSUT or self.sourceGate.component.role = TDL!ComponentInstanceRole#Tester) { var sc = self.getMainContext(self.sourceGate.component); var sb = stack.get(sc).last(); var ssl = self.executeSource(); sb.stat.add(ssl); } //TODO: handle multicast? //target behaviour if (simulateSUT or self.target.first().targetGate.component.role = TDL!ComponentInstanceRole#Tester) { var tc = self.getMainContext(self.target.first().targetGate.component); var tb = stack.get(tc).last(); var t = self.target.first(); var tsl = self.executeTarget(t); tb.stat.add(tsl); } //inlined above //self.execute(sb, tb); } //TODO: remove? (inlined above) operation TDL!Interaction execute(sourceContext : TTCN!StatementBlock, targetContext : TTCN!StatementBlock) { //source behaviour var ssl = self.executeSource(); sourceContext.stat.add(ssl); //TODO: handle multicast? //target behaviour var t = self.target.first(); var tsl = self.executeTarget(t); targetContext.stat.add(tsl); } operation TDL!Behaviour getMainContext(component : TDL!ComponentInstance) : String { return self.getTestDescription().name+"_"+component.name+"_main"; } operation TDL!AlternativeBehaviour execute() { if (not transformAlt) return; var td = self.getTestDescription(); //TODO: naive simplified assumption var fb = self.block.first().behaviour.first(); if (fb.isKindOf(TDL!Interaction)) { if (simulateSUT or fb.sourceGate.component.role = TDL!ComponentInstanceRole#Tester) { var sc = self.getMainContext(fb.sourceGate.component); var sb = stack.get(sc).last(); self.executeSource(sb); } if (simulateSUT or fb.target.first().targetGate.component.role = TDL!ComponentInstanceRole#Tester) { var tc = self.getMainContext(fb.target.first().targetGate.component); var tb = stack.get(tc).last(); self.executeTarget(tb); } } } operation TDL!AlternativeBehaviour executeTarget(targetContext : TTCN!StatementBlock) { var tsl = self.executeTarget(); targetContext.stat.add(tsl); } operation TDL!AlternativeBehaviour executeSource(sourceContext : TTCN!StatementBlock) { //TODO: simple assumption - trigger first //TODO: needs to follow path, right now triggers first interactions in other branches as well var fb = self.block.first().behaviour.first(); if (fb.isKindOf(TDL!Interaction)) { var ssl = fb.executeSource(); sourceContext.stat.add(ssl); } } operation TDL!AlternativeBehaviour checkPath() : Boolean { var first = true; if (self.eContainer.isDefined()) { if (self.eContainer.isKindOf(TDL!Block)) { if (self.eContainer.eContainer.isKindOf(TDL!AlternativeBehaviour)) { if (self.eContainer.eContainer.block.indexOf(self.eContainer) <> 0) { first = false; } else { first = self.eContainer.eContainer.checkPath(); } } } } return first; } operation TDL!AlternativeBehaviour executeTarget() : TTCN!FunctionStatementList { if (not transformAlt) return; //TODO //target only so far.. //where should this be placed? in the receiving side? //how about source //TODO: add explicit scoping var tsl = new TTCN!FunctionStatementList(); var fs = new TTCN!FunctionStatement(); fs.behavior = new TTCN!BehaviourStatements(); fs.behavior.alt = new TTCN!AltConstruct(); fs.behavior.alt.agList = new TTCN!AltGuardList(); for (block in self.block) { var gs = block.executeAltBlock(); fs.behavior.alt.agList.guardList.add(gs); } tsl.statements.add(fs); //tsl.sc.add(";"); return tsl; } operation TDL!Block executeAltBlock() : TTCN!GuardStatement { var gs = new TTCN!GuardStatement(); gs.`guard` = new TTCN!AltGuardChar(); //TODO: expression gs.block = new TTCN!StatementBlock(); //naive assumption var cf = self.behaviour.first().getMainContext(self.behaviour.first().target.first().targetGate.component); stack.get(cf).add(gs.block); var i = 0; for (b in self.behaviour) { if (i==0) { if (b.isKindOf(TDL!Interaction)) { gs.op = b.getGuardOp(); } else { //TODO: handle other behaviours? } } else { b.execute(); } i = i+1; } stack.get(cf).remove(gs.block); //TODO: statement block return gs; } operation TDL!Interaction getGuardOp() : TTCN!GuardOp { var op = new TTCN!GuardOp(); op.receive = new TTCN!ReceiveStatement(); op.receive.any = new TTCN!PortOrAny(); //TODO: handle broadcast? //op.receive.any.ref = self.target.first().targetGate.gate.equivalent(); op.receive.any.ref = self.target.first().targetGate.equivalent().port; op.receive.receive = new TTCN!PortReceiveOp(); op.receive.receive.template = new TTCN!InLineTemplate(); op.receive.receive.template.template = self.argument.getTemplateBody(); return op; } operation TDL!BoundedLoopBehaviour execute() { //TODO for (b in self.block.behaviour) { b.execute(); } } operation TDL!UnboundedLoopBehaviour execute() { //TODO for (b in self.block.behaviour) { b.execute(); } } operation TDL!ActionReference execute() { //TODO } operation TDL!VerdictAssignment execute() { //TODO for (ci in self.getTestDescription().testConfiguration.componentInstance.select(c|simulateSUT or c.role = TDL!ComponentInstanceRole#Tester)) { var sc = self.getMainContext(ci); var sb = stack.get(sc).last(); var ssl = new TTCN!FunctionStatementList(); var sfs = new TTCN!FunctionStatement(); sfs.verdict = new TTCN!SetLocalVerdict(); sfs.verdict.expression = new TTCN!Value(); //TODO: handle corresponding verdict properly if (self.verdict.isKindOf(TDL!DataInstanceUse)) { sfs.verdict.expression.predef = new TTCN!PredefinedValue(); if (self.verdict.dataInstance.name = "pass") { sfs.verdict.expression.predef.verdictType = TTCN!VerdictTypeValue#pass; } else if (self.verdict.dataInstance.name = "fail") { sfs.verdict.expression.predef.verdictType = TTCN!VerdictTypeValue#fail; } else if (self.verdict.dataInstance.name = "inconclusive") { sfs.verdict.expression.predef.verdictType = TTCN!VerdictTypeValue#inconc; } else { //TODO } } else { //TODO } ssl.statements.add(sfs); ssl.sc.add(";"); sb.stat.add(ssl); } } operation TDL!CompoundBehaviour execute() { //TODO for (b in self.block.behaviour) { b.execute(); } } operation TDL!Behaviour execute() { (" Skipping " +self.type.name+" (not yet supported)").println(); if (self.type.name = "ParallelBehaviour" and false) { (indent+"group Parallel").printlno(); var i = 0; for (block in self.block) { for (b in block.behaviour) { b.execute(indent+" "); } if (i <= block.size()) { (indent+"else").printlno(); } i = i+1; } (indent+"end").printlno(); } }