public static ISet <IKey> Run(IRelation relation) { // We prepare the result ISet <IKey> result = new HashSet <IKey>(); // We get all keys ISet <IKey> allKeys = new HashSet <IKey>(); allKeys.UnionWith(relation.Keys()); allKeys.UnionWith(((IRelationalTransformation)relation.Transformation).OwnedKey); // We copy each key in the result if no equal key is present foreach (IKey key in allKeys) { IKey existingKey = result.FirstOrDefault(k => AreEqual(k, key)); if (existingKey == null) { result.Add(key); } } return(result); }
private static string GenerateSetValue(IPropertyTemplateItem propertyTemplateItem, string resultContainer, IRelation relation, bool useMetamodelInterface) { StringBuilder sb = new StringBuilder(); IObjectTemplateExp objectTemplateExpression = propertyTemplateItem.Value as IObjectTemplateExp; // Case ref value if (objectTemplateExpression != null) { IKey transformationKey = ((IRelationalTransformation)relation.Transformation).OwnedKey.FirstOrDefault(k => k.Identifies == objectTemplateExpression.ReferredClass); IList <IList <IPropertyTemplateItem> > propertyPathsTransformationKey = transformationKey != null?FindKeyApplicablePropertyPaths(objectTemplateExpression, transformationKey) : null; IKey relationKey = relation.Keys().FirstOrDefault(k => k.Identifies == objectTemplateExpression.ReferredClass); IList <IList <IPropertyTemplateItem> > propertyPathsRelationKey = relationKey != null?FindKeyApplicablePropertyPaths(objectTemplateExpression, relationKey) : null; // We always start by creating the empty variable that will contain the object sb.AppendLine(objectTemplateExpression.BindsTo.Type.GetRealTypeName() + " " + objectTemplateExpression.BindsTo.Name + " = null;"); int nbBracketsOpened = 0; // If any part of a key applies, then we must generate a test to find a potential existing object if (propertyPathsTransformationKey != null || propertyPathsRelationKey != null) { // We try to resolve globally and locally, if a global key applies here if (propertyPathsTransformationKey != null) { sb.AppendLine(); sb.AppendLine("// Trying to resolve the object\'" + objectTemplateExpression.BindsTo.Name + "\' globally using the transformation key"); IList <string> tupleTypes = propertyPathsTransformationKey.Select(pp => pp.Last().ReferredProperty.Type.GetRealTypeName()).Select(name => name + (cSharpPrimitiveTypes.Contains(name) ? "?" : "")).ToList(); IList <string> tupleValues = propertyPathsTransformationKey.Select(pp => GenerateAccess(objectTemplateExpression.BindsTo.Name, pp)).ToList(); IList <string> tupleValuesRead = propertyPathsTransformationKey.Select(pp => GenerateExpression(pp.Last().Value, useMetamodelInterface)).ToList(); string tupleTypesCombined = string.Join(",", tupleTypes); string tupleValuesCombined = string.Join(",", tupleValues); string tupleValuesCombinedRead = string.Join(",", tupleValuesRead); string accessDictionnaryReadSafe = "transformation." + QvtCodeGeneratorStrings.KeyDictionnaryName(transformationKey) + ".TryGetValue(new Tuple<" + tupleTypesCombined + ">(" + tupleValuesCombinedRead + "), out " + objectTemplateExpression.BindsTo.Name + ")"; string accessDictionnaryWrite = "transformation." + QvtCodeGeneratorStrings.KeyDictionnaryName(transformationKey) + "[new Tuple<" + tupleTypesCombined + ">(" + tupleValuesCombined + ")]"; sb.AppendLine(accessDictionnaryReadSafe + ";"); // If not found globally with global key, we try to find locally with global key sb.AppendLine("// If the object wasn't found globally, we try to find it locally"); sb.AppendLine("if (" + objectTemplateExpression.BindsTo.Name + "== null) {"); sb.AppendLine(GenerateFindValueWithKey(propertyTemplateItem, objectTemplateExpression, resultContainer, propertyPathsTransformationKey, useMetamodelInterface)); nbBracketsOpened++; // If we found locally with global key, we add to the dictionnary sb.AppendLine("// If the object was found locally, we add it to the global cache"); sb.AppendLine("if (" + objectTemplateExpression.BindsTo.Name + "!= null) {"); sb.AppendLine(accessDictionnaryWrite + " = " + objectTemplateExpression.BindsTo.Name + ";"); // Else we continue with other attempts (local key or object creation) sb.AppendLine("}"); } if (propertyPathsRelationKey != null) { sb.AppendLine("// Trying to resolve the object locally using the relation key"); if (propertyPathsTransformationKey != null) { sb.AppendLine("else {"); nbBracketsOpened++; } sb.AppendLine(GenerateFindValueWithKey(propertyTemplateItem, objectTemplateExpression, resultContainer, propertyPathsRelationKey, useMetamodelInterface)); // If we found something locally, once again we check in the dictionnary and try to update sb.AppendLine("// If the object was found locally, we add it to the global cache"); sb.AppendLine("if (" + objectTemplateExpression.BindsTo.Name + "!= null) {"); sb.AppendLine(GenerateCheckAndAddDictionnary(propertyPathsTransformationKey, objectTemplateExpression.BindsTo.Name, transformationKey)); sb.AppendLine("}"); } // In the end we generate a test if we found a candidate sb.AppendLine("// If the object still doesn't exist, we create it"); sb.AppendLine("else {"); nbBracketsOpened++; } // In any case, we generate the code to create the object, even if it might end in the conditional due to the keys test string beginningCreation = objectTemplateExpression.BindsTo.Name + " = "; if (useMetamodelInterface) { sb.AppendLine(beginningCreation + " (" + objectTemplateExpression.BindsTo.Type.GetRealTypeName() + ") editor." + nameof(IMetaModelInterface.CreateNewObjectInField) + "(" + resultContainer + ", \"" + propertyTemplateItem.ReferredProperty.Name + "\");"); } else { string res = beginningCreation; res += "new " + objectTemplateExpression.BindsTo.Type.GetRealTypeName() + "();\n"; if (!propertyTemplateItem.ReferredProperty.isMany()) { res += resultContainer + "." + propertyTemplateItem.ReferredProperty.Name + " = " + objectTemplateExpression.BindsTo.Name + ";"; } else { res += resultContainer + "." + propertyTemplateItem.ReferredProperty.Name + ".Add(" + objectTemplateExpression.BindsTo.Name + ");"; } sb.AppendLine(res); } if (propertyPathsTransformationKey != null) { // TODO generate this all the time? sb.AppendLine("// We add the created object to the global cache"); sb.AppendLine(GenerateCheckAndAddDictionnary(propertyPathsTransformationKey, objectTemplateExpression.BindsTo.Name, transformationKey)); } // If we generated a conditional for the keys test, we close it now if (propertyPathsTransformationKey != null || propertyPathsRelationKey != null) { sb.AppendLine("}"); } for (int i = 0; i < nbBracketsOpened - 1; i++) { sb.AppendLine("}"); } return(sb.ToString()); } // Case primitive value (variable use or c sharp expression) else { if (useMetamodelInterface) { return("editor." + nameof(IMetaModelInterface.AddOrSetInField) + "(" + resultContainer + ", \"" + propertyTemplateItem.ReferredProperty.Name + "\", " + GenerateExpression(propertyTemplateItem.Value, true) + " );"); } else { return(resultContainer + "." + propertyTemplateItem.ReferredProperty.Name + "=" + GenerateExpression(propertyTemplateItem.Value, false) + ";"); } } }