private EMOF.IPackage ConstructPackage(EnAr.Package metamodelPackage) { if (elementToPackage.ContainsKey(metamodelPackage)) { return(elementToPackage[metamodelPackage]); } else { // We create the Package EMOF.IPackage package = new EMOF.Package() { Name = metamodelPackage.Name }; elementToPackage.Add(metamodelPackage, package); // We create its owned Types foreach (EnAr.Element classChild in explorer.GetChildrenElementsWithType(metamodelPackage, "class")) { EMOF.IType type = ConstructType(classChild); package.OwnedType.Add(type); type.Package = package; } // We create its nested Packages foreach (EnAr.Package metamodelChild in explorer.GetChildrenPackages(metamodelPackage)) { EMOF.IPackage nestedPackage = ConstructPackage(metamodelChild); package.NestedPackage.Add(nestedPackage); nestedPackage.NestingPackage = package; } return(package); } }
private QVTTemplate.IObjectTemplateExp ConstructObjectTemplateExp(QVTRelations.IRelation relation, QVTRelations.IDomainPattern domainPattern, EnAr.Element objectElement, ISet <EnAr.Connector> visitedConnectors = null) { EssentialOCL.IVariable variable = null; EMOF.IType type = emofImporter.ConstructTypeOfTyped(objectElement); // TODO manage the not ? if (objectElement.Name != "{not}") { variable = ConstructVariable(relation, objectElement); domainPattern?.BindsTo.Add(variable); } QVTTemplate.IObjectTemplateExp objectTemplateExp = new QVTTemplate.ObjectTemplateExp() { BindsTo = variable, ReferredClass = type as EMOF.IClass, Where = null // TODO }; objectTemplateExp.SetAntiTemplate(variable == null); objectElementToObjectTemplate.Add(objectElement, objectTemplateExp); foreach (RunStateField runStateField in EnArExplorer.GetRunState(objectElement)) { ConstructPropertyTemplateItem(relation, domainPattern, objectTemplateExp, runStateField); } foreach (EnAr.Connector connector in explorer.GetConnectorsLinkedTo(objectElement).FindAll(c => c.Stereotype != "qvtTransformationLink")) { Tuple <EnAr.ConnectorEnd, EnAr.Element> linked = explorer.GetElementOppositeTo(objectElement, connector); EnAr.ConnectorEnd connectorEnd = linked.Item1; EnAr.Element linkedElement = linked.Item2; //if (!string.IsNullOrWhiteSpace(connectorEnd.Role)) //{ ConstructPropertyTemplateItem(relation, domainPattern, objectTemplateExp, connector, connectorEnd, linkedElement, visitedConnectors); //} } return(objectTemplateExp); }
private EssentialOCL.IOclExpression ConstructOCLExpression(QVTRelations.IRelation relation, ExpressionSyntax parsedExpression, QVTBase.IPattern pattern, EMOF.IType type = null) { // Case single identifier => OCL VariableExp if (parsedExpression is IdentifierNameSyntax) { EssentialOCL.IVariable variable = ConstructVariable(relation, parsedExpression.ToString(), type); pattern?.BindsTo.Add(variable); return(new EssentialOCL.VariableExp() { ReferredVariable = variable }); } // Case method call => QVT RelationCallExp (if the relation exists) of function call (if the function exists) if (parsedExpression is InvocationExpressionSyntax) { InvocationExpressionSyntax invocationExpressionSyntax = (InvocationExpressionSyntax)parsedExpression; // We are only interested in direct calls if (invocationExpressionSyntax.Expression is IdentifierNameSyntax) { IdentifierNameSyntax methodIdentifier = (IdentifierNameSyntax)invocationExpressionSyntax.Expression; ArgumentListSyntax argumentList = invocationExpressionSyntax.ArgumentList; QVTRelations.IRelation calledRelation = FindRelation((QVTRelations.IRelationalTransformation)(relation.Transformation), methodIdentifier.ToString()); QVTBase.IFunction calledFunction = FindFunction((QVTRelations.IRelationalTransformation)(relation.Transformation), methodIdentifier.ToString()); if (calledRelation != null) { QVTRelations.RelationCallExp call = new QVTRelations.RelationCallExp { ReferredRelation = calledRelation }; if (argumentList.Arguments.Count != calledRelation.Domain.Count) { throw new InvalidQVTRelationsModelException("Relation " + relation.Name + ": wrong number of arguments in relation call " + calledRelation.Name); } foreach (ArgumentSyntax argumentSyntax in argumentList.Arguments) { QVTRelations.IRelationDomain correspondingDomain = (QVTRelations.IRelationDomain)calledRelation.Domain[argumentList.Arguments.IndexOf(argumentSyntax)]; ExpressionSyntax argumentExpression = argumentSyntax.Expression; EssentialOCL.IOclExpression argumentOCLExpression = ConstructOCLExpression(relation, argumentExpression, pattern, correspondingDomain.RootVariable.Type); call.Argument.Add(argumentOCLExpression); } return(call); } else if (calledFunction != null) { string methodname = methodIdentifier.ToString(); EssentialOCL.IOperationCallExp call = new EssentialOCL.OperationCallExp() { Type = calledFunction.Type, ReferredOperation = calledFunction, Name = calledFunction.Name, }; foreach (ArgumentSyntax argumentSyntax in argumentList.Arguments) { ExpressionSyntax argumentExpression = argumentSyntax.Expression; EssentialOCL.IOclExpression argumentOCLExpression = ConstructOCLExpression(relation, argumentExpression, pattern, calledFunction.Type); call.Argument.Add(argumentOCLExpression); } return(call); } } } // Case assignment => Custom Assignment //TODO replace by OCL '=='? Meaning having to provide basic parts of OCL standard lib if (parsedExpression is AssignmentExpressionSyntax) { AssignmentExpressionSyntax assignmentExpressionSyntax = (AssignmentExpressionSyntax)parsedExpression; IdentifierNameSyntax leftIdentifier = (IdentifierNameSyntax)assignmentExpressionSyntax.Left; ExpressionSyntax right = assignmentExpressionSyntax.Right; EssentialOCL.IVariable variable = ConstructVariable(relation, leftIdentifier.ToString()); pattern?.BindsTo.Add(variable); return(new EssentialOCL.Assignment() { AssignedVariable = variable, Value = ConstructOCLExpression(relation, right, pattern) }); } // Any other case => Custom CSharpOpaqueExpression // TODO replace by QVT "Function" with a black box implementation? EssentialOCL.CSharpOpaqueExpression cSharpOpaqueExpression = new EssentialOCL.CSharpOpaqueExpression() { Code = parsedExpression.ToString() }; SetBindings(relation, pattern, cSharpOpaqueExpression, parsedExpression); return(cSharpOpaqueExpression); }
/// <summary> /// Construct the OCLExpression corresponding to some CSharp expression included in the model. /// Try to create pure OCL, fallback to custom CSharpExpression object if not handled. /// </summary> /// <param name="relation">The relation containing the expression.</param> /// <param name="domainPattern">(optional) The domainPattern containing the expression.</param> /// <param name="expressionString">The expression string to parse.</param> /// <returns></returns> private EssentialOCL.IOclExpression ConstructOCLExpression(QVTRelations.IRelation relation, string expressionString, QVTBase.IPattern pattern, EMOF.IType type) { // To be able to reuse existing transfos: we consider strings with single quotes as well string expressionWithOnlyDoubleQuotes = expressionString.Replace("\'", "\""); // We parse using Roslyn ExpressionSyntax parsedExpression = CSharpParser.ParseExpression(expressionWithOnlyDoubleQuotes); // And we use the expression analysis overload variant return(ConstructOCLExpression(relation, parsedExpression, pattern, type)); }
private EssentialOCL.IVariable ConstructVariable(QVTRelations.IRelation relation, string name, EMOF.IType type = null) { EssentialOCL.IVariable variable = relation.Variable.FirstOrDefault(v => v.Name == name); if (variable == null) { variable = new EssentialOCL.Variable() { Name = name, Type = type, InitExpression = null, // Not taken into account }; relation.Variable.Add(variable); } // If there was an existing variable, but with no type yet, we give it the input type else if (variable.Type == null && type != null) { variable.Type = type; } return(variable); }