Пример #1
0
        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) + ";");
                }
            }
        }