Exemplo n.º 1
0
 public static void AddUnions(OutputModel outputModel, OutputPlan outputPlan)
 {
     foreach (var databasePlan in outputPlan.DatabasePlansByName.Values)
     {
         foreach (var partitionPlan in databasePlan.PartitionPlansByName.Values)
         {
             foreach (var union in partitionPlan.Documents.GroupBy(x => x.GetIdPlan.FullMethodName).Where(x => x.Count() > 1))
             {
                 var idPlan       = union.First().GetIdPlan;
                 var fullTypeName = idPlan.FullMethodName.Substring(0, idPlan.FullMethodName.LastIndexOf('.'));
                 var commonName   = fullTypeName.Split('.').Last();
                 if (commonName.EndsWith("Base"))
                 {
                     commonName = commonName.Substring(0, commonName.Length - 4);
                 }
                 if (commonName.EndsWith("Doc"))
                 {
                     commonName = commonName.Substring(0, commonName.Length - 3);
                 }
                 partitionPlan.Unions.Add(new UnionPlan
                 {
                     GetIdPlan          = idPlan,
                     Documents          = union.ToList(),
                     FullCommonTypeName = fullTypeName,
                     CommonName         = commonName
                 });
             }
         }
     }
 }
Exemplo n.º 2
0
    public static OutputPlan Create(OutputModel outputModel)
    {
        outputModel.CancellationToken.ThrowIfCancellationRequested();

        var plan = new OutputPlan();

        DatabasePlanBuilder.Build(outputModel, plan);

        return(plan);
    }
Exemplo n.º 3
0
    public static void AddPartitions(OutputModel outputModel, OutputPlan outputPlan)
    {
        outputModel.CancellationToken.ThrowIfCancellationRequested();
        if (!outputModel.CanGenerate)
        {
            return;
        }

        AddPartitionClasses(outputModel, outputPlan);
        AddImplicitPartitions(outputModel, outputPlan);
    }
Exemplo n.º 4
0
    public static void Write(OutputModel outputModel, OutputPlan outputPlan)
    {
        outputModel.CancellationToken.ThrowIfCancellationRequested();
        if (!outputModel.CanGenerate)
        {
            return;
        }

        foreach (var databasePlan in outputPlan.DatabasePlansByName.Values)
        {
            DatabasePlanWriter.Write(outputModel, databasePlan);
        }
    }
Exemplo n.º 5
0
    public static void Build(OutputModel outputModel, OutputPlan outputPlan)
    {
        outputModel.CancellationToken.ThrowIfCancellationRequested();
        if (!outputModel.CanGenerate)
        {
            return;
        }

        var databasePlansByClass = new Dictionary <ClassModel, List <DatabasePlan> >();

        foreach (var dbAttribute in outputModel.DbAttributes)
        {
            Initialize(outputModel, null, outputPlan, dbAttribute);
        }
        foreach (var classModel in outputModel.Classes)
        {
            outputPlan.DatabasePlansByClass[classModel] = new();
            foreach (var dbAttribute in classModel.DbAttributes)
            {
                Initialize(outputModel, classModel, outputPlan, dbAttribute);
            }
        }
        var defaultDatabase = outputPlan.DatabasePlansByName.Count == 1 ? outputPlan.DatabasePlansByName.Values.Single() : null;

        if (defaultDatabase is not null)
        {
            foreach (var byClass in outputPlan.DatabasePlansByClass.Values.Where(x => x.Count == 0))
            {
                byClass.Add(defaultDatabase);
            }
        }
        foreach (var classModel in outputPlan.DatabasePlansByName.Values.GroupBy(x => x.Namespace).Where(x => x.Count() > 1).Select(x => x.First().ClassModel))
        {
            outputModel.Report(Diagnostics.Errors.DatabaseNamespaces, classModel?.ClassSymbol as ISymbol ?? outputModel.Compilation.Assembly);
        }

        PartitionPlanBuilder.AddPartitions(outputModel, outputPlan);
        DocumentPlanBuilder.AddDocuments(outputModel, outputPlan);
        PartitionPlanBuilder.RemoveEmptyPartitions(outputModel, outputPlan);
        UnionPlanBuilder.AddUnions(outputModel, outputPlan);

        foreach (var databasePlan in outputPlan.DatabasePlansByName.Values)
        {
            foreach (var documentPlan in databasePlan.PartitionPlansByName.Values.SelectMany(x => x.Documents).GroupBy(x => x.DocType).Where(x => x.Count() > 1).Select(x => x.First()))
            {
                outputModel.Report(Diagnostics.Errors.DuplicateDocType, documentPlan.ClassModel.ClassSymbol, documentPlan.DocType);
            }
        }
    }
Exemplo n.º 6
0
        /// <summary>
        /// Exports the plan under a XML format.
        /// </summary>
        /// <param name="planToExport"></param>
        /// <returns></returns>
        public static string ExportAsXML(Plan plan)
        {
            // Generates a settings plan and transforms it to an output plan
            var serial = plan.Export();
            var output = new OutputPlan {
                Name = serial.Name, Owner = serial.Owner, Revision = Settings.Revision
            };

            output.Entries.AddRange(serial.Entries);

            // Serializes to XML document and gets a string representation
            var doc = Util.SerializeToXmlDocument(typeof(OutputPlan), output);

            return(Util.GetXMLStringRepresentation(doc));
        }
Exemplo n.º 7
0
    public static void RemoveEmptyPartitions(OutputModel outputModel, OutputPlan outputPlan)
    {
        outputModel.CancellationToken.ThrowIfCancellationRequested();
        if (!outputModel.CanGenerate)
        {
            return;
        }

        foreach (var databasePlan in outputPlan.DatabasePlansByName.Values)
        {
            foreach (var partitionPlan in databasePlan.PartitionPlansByName.Values.Where(x => x.Documents.Count == 0).ToList())
            {
                databasePlan.PartitionPlansByName.Remove(partitionPlan.Name);
                outputModel.Report(Diagnostics.Warnings.EmptyPartition, partitionPlan.GetPkModel.MethodSymbol, partitionPlan.Name);
            }
        }
    }
Exemplo n.º 8
0
        /// <summary>
        /// Exports the plan under an XML format.
        /// </summary>
        /// <param name="plan">The plan.</param>
        /// <returns></returns>
        /// <exception cref="System.ArgumentNullException">plan</exception>
        public static string ExportAsXML(Plan plan)
        {
            plan.ThrowIfNull(nameof(plan));

            // Generates a settings plan and transforms it to an output plan
            SerializablePlan serial = plan.Export();
            OutputPlan       output = new OutputPlan {
                Name = serial.Name, Owner = serial.Owner, Revision = Settings.Revision
            };

            output.Entries.AddRange(serial.Entries);

            // Serializes to XML document and gets a string representation
            XmlDocument doc = (XmlDocument)Util.SerializeToXmlDocument(output);

            return(Util.GetXmlStringRepresentation(doc));
        }
Exemplo n.º 9
0
 static void AddPartitionClasses(OutputModel outputModel, OutputPlan outputPlan)
 {
     foreach (var kvp in outputPlan.DatabasePlansByClass)
     {
         var classModel    = kvp.Key;
         var databasePlans = kvp.Value;
         if (classModel.PartitionDefinitionAttribute is not null)
         {
             if (databasePlans.Count == 0)
             {
                 outputModel.Report(Diagnostics.Errors.NoDatabase, classModel.ClassSymbol);
             }
             foreach (var methodModel in classModel.Methods)
             {
                 var name = methodModel.MethodSymbol.Name;
                 foreach (var databasePlan in databasePlans)
                 {
                     AddPartitionDefinition(outputModel, databasePlan, methodModel, name);
                 }
             }
         }
     }
 }
Exemplo n.º 10
0
 static void AddImplicitPartitions(OutputModel outputModel, OutputPlan outputPlan)
 {
     foreach (var kvp in outputPlan.DatabasePlansByClass)
     {
         var classModel    = kvp.Key;
         var databasePlans = kvp.Value;
         if (classModel.PartitionAttribute is not null)
         {
             var name = classModel.PartitionAttribute.Name;
             foreach (var databasePlan in databasePlans)
             {
                 if (!databasePlan.PartitionPlansByName.ContainsKey(name))
                 {
                     var getPk = classModel.Methods
                                 .Where(x => x.MethodSymbol.Name == "GetPk")
                                 .Where(x => x.MethodSymbol.IsStatic)
                                 .Where(x => x.MethodSymbol.ReturnType.SpecialType == SpecialType.System_String)
                                 .Where(x => x.MethodSymbol.DeclaredAccessibility.IsAccessible())
                                 .ToList();
                     if (getPk.Count == 0)
                     {
                         outputModel.Report(Diagnostics.Errors.NoGetPk, classModel.ClassSymbol);
                     }
                     else if (getPk.Count > 1)
                     {
                         outputModel.Report(Diagnostics.Errors.MultipleGetPk, classModel.ClassSymbol);
                     }
                     else
                     {
                         AddPartitionDefinition(outputModel, databasePlan, getPk[0], name);
                     }
                 }
             }
         }
     }
 }
Exemplo n.º 11
0
    static void Initialize(OutputModel outputModel, ClassModel?classModel, OutputPlan outputPlan, DbAttributeModel dbAttribute)
    {
        var name   = dbAttribute.Name ?? "";
        var symbol = classModel?.ClassSymbol as ISymbol ?? outputModel.Compilation.Assembly;

        if (outputPlan.DatabasePlansByName.TryGetValue(name, out var plan))
        {
            if (dbAttribute.Namespace.NullIfEmpty() is not null &&
                dbAttribute.Namespace != plan.Namespace)
            {
                if (plan.IsDefaultNamespace)
                {
                    plan.IsDefaultNamespace = false;
                    plan.Namespace          = dbAttribute.Namespace !;
                    plan.ClassModel         = classModel;
                }
                else
                {
                    outputModel.Report(Diagnostics.Errors.DbMultipleNamespace, symbol);
                }
            }
        }
        else
        {
            plan = new DatabasePlan
            {
                Namespace                    = dbAttribute.Namespace.NullIfEmpty() !,
                Name                         = name,
                ClassModel                   = classModel,
                DbClassName                  = name.WithSuffix(Suffixes.Database),
                PartitionsClassName          = name.WithSuffix(Suffixes.Partitions),
                QueryBuilderClassName        = name.WithSuffix(Suffixes.QueryBuilder),
                QueryBuilderUnionsClassName  = name.WithSuffix(Suffixes.QueryBuilderUnions),
                QueryClassName               = name.WithSuffix(Suffixes.Query),
                QueryUnionsClassName         = name.WithSuffix(Suffixes.QueryUnions),
                ReadClassName                = name.WithSuffix(Suffixes.Read),
                SerializerClassName          = name.WithSuffix(Suffixes.Serializer),
                ConverterClassName           = name.WithSuffix(Suffixes.Converter),
                TypesClassName               = name.WithSuffix(Suffixes.Types),
                BatchHandlersClassName       = name.WithSuffix(Suffixes.BatchHandlers),
                ChangeFeedProcessorClassName = name.WithSuffix(Suffixes.ChangeFeedProcessor)
            };
            plan.BatchHandlersArgumentName = plan.BatchHandlersClassName.ToArgumentName();
            plan.IsDefaultNamespace        = plan.Namespace is null;
            plan.Namespace ??= classModel?.ClassSymbol.ContainingNamespace?.ToDisplayString() ?? outputModel.Compilation.Assembly.Name.NullIfEmpty() ?? "Cosmogenesis.Generated";
            plan.DbClassNameArgument           = plan.DbClassName.ToArgumentName();
            plan.QueryBuilderClassNameArgument = plan.QueryBuilderClassName.ToArgumentName();
            outputModel.ValidateNames(
                symbol,
                plan.Name,
                plan.DbClassName,
                plan.PartitionsClassName,
                plan.QueryBuilderClassName,
                plan.QueryClassName,
                plan.ReadClassName,
                plan.SerializerClassName,
                plan.ConverterClassName,
                plan.TypesClassName,
                plan.BatchHandlersClassName,
                plan.ChangeFeedProcessorClassName,
                plan.QueryBuilderUnionsClassName,
                plan.QueryUnionsClassName);
            outputModel.ValidateIdentifiers(
                symbol,
                plan.BatchHandlersArgumentName,
                plan.DbClassNameArgument,
                plan.QueryBuilderClassNameArgument);
            plan.Namespace.ValidateNamespace(outputModel, symbol);
            outputPlan.DatabasePlansByName[name] = plan;
        }
        if (classModel is not null)
        {
            outputPlan.DatabasePlansByClass[classModel].Add(plan);
        }
    }
}
Exemplo n.º 12
0
    public static void AddDocuments(OutputModel outputModel, OutputPlan outputPlan)
    {
        outputModel.CancellationToken.ThrowIfCancellationRequested();
        if (!outputModel.CanGenerate)
        {
            return;
        }

        foreach (var kvp in outputPlan.DatabasePlansByClass)
        {
            var classModel    = kvp.Key;
            var databasePlans = kvp.Value;
            if (classModel.IsDbDoc && !classModel.ClassSymbol.IsAbstract)
            {
                if (databasePlans.Count == 0)
                {
                    outputModel.Report(Diagnostics.Errors.NoDatabase, classModel.ClassSymbol);
                }
                else if (classModel.PartitionAttribute is null)
                {
                    outputModel.Report(Diagnostics.Warnings.DbDocWithoutPartition, classModel.ClassSymbol, classModel.ClassSymbol.Name);
                }
                else
                {
                    if (!classModel.ClassSymbol.Constructors.Any(x => x.Parameters.IsDefaultOrEmpty && x.DeclaredAccessibility.IsAccessible()))
                    {
                        outputModel.Report(Diagnostics.Errors.ParameterlessConstructor, classModel.ClassSymbol);
                    }
                    var implicitGetIds = classModel.Methods
                                         .Where(x => x.MethodSymbol.Name == "GetId")
                                         .Where(x => x.MethodSymbol.IsStatic)
                                         .Where(x => x.MethodSymbol.ReturnType.SpecialType == SpecialType.System_String)
                                         .Where(x => x.MethodSymbol.DeclaredAccessibility.IsAccessible())
                                         .ToList();
                    if (implicitGetIds.Count == 0)
                    {
                        outputModel.Report(Diagnostics.Errors.NoGetId, classModel.ClassSymbol);
                    }
                    else if (implicitGetIds.Count > 1)
                    {
                        outputModel.Report(Diagnostics.Errors.MultipleGetId, classModel.ClassSymbol);
                    }
                    else
                    {
                        var getId         = implicitGetIds[0];
                        var partitionName = classModel.PartitionAttribute.Name;
                        var name          = classModel.ClassSymbol.Name.WithoutSuffix(Suffixes.Doc).WithoutSuffix(Suffixes.Document);
                        var type          = classModel.DocTypeAttribute?.Name.NullIfEmpty() ?? name;
                        type.ValidateDocType(outputModel, classModel.ClassSymbol);
                        foreach (var databasePlan in databasePlans)
                        {
                            if (!databasePlan.PartitionPlansByName.TryGetValue(partitionName, out var partitionPlan))
                            {
                                outputModel.Report(Diagnostics.Errors.NoGetPk, classModel.ClassSymbol);
                            }
                            else
                            {
                                var documentPlan = new DocumentPlan
                                {
                                    DocType           = type,
                                    FullTypeName      = classModel.ClassSymbol.ToDisplayString(),
                                    ClassModel        = classModel,
                                    IsMutable         = classModel.MutableAttribute is not null,
                                    IsTransient       = classModel.TransientAttribute is not null,
                                    ClassName         = name,
                                    ClassNameArgument = name.ToArgumentName(),
                                    PluralName        = name.Pluralize(),
                                    ConstDocType      = $"{databasePlan.Namespace}.{databasePlan.TypesClassName}.{partitionPlan.ClassName}.{name}",
                                    GetIdPlan         = new GetPkIdPlan
                                    {
                                        FullMethodName = $"{getId.MethodSymbol.ContainingType.ToDisplayString()}.{getId.MethodSymbol.Name}",
                                        Arguments      = getId
                                                         .MethodSymbol
                                                         .Parameters
                                                         .Select(x => new GetPkIdPlan.Argument
                                        {
                                            ArgumentName = x.Name.ToArgumentName(),
                                            FullTypeName = x.Type.ToDisplayString()
                                        })
                                                         .ToList()
                                    }
                                };

                                partitionPlan.Documents.Add(documentPlan);

                                outputModel.ValidateNames(
                                    classModel.ClassSymbol,
                                    documentPlan.ClassName,
                                    documentPlan.PluralName);
                                outputModel.ValidateIdentifiers(
                                    classModel.ClassSymbol,
                                    documentPlan.ClassNameArgument);

                                PropertyPlanBuilder.AddProperties(outputModel, classModel, documentPlan);

                                documentPlan.GetIdPlan = GetPkIdPlanBuilder.Build(outputModel, getId.MethodSymbol, documentPlan.PropertiesByName, documentPlan.PropertiesByArgumentName);
                                if (partitionPlan.GetPkPlan is null)
                                {
                                    partitionPlan.GetPkPlan = GetPkIdPlanBuilder.Build(outputModel, partitionPlan.GetPkModel.MethodSymbol, documentPlan.PropertiesByName, documentPlan.PropertiesByArgumentName);
                                }
                                else
                                {
                                    foreach (var arg in partitionPlan.GetPkPlan.Arguments)
                                    {
                                        if (arg.PropertyName is not null && !documentPlan.PropertiesByName.ContainsKey(arg.PropertyName))
                                        {
                                            outputModel.Report(Diagnostics.Errors.PropertyResolvePkIdConsistency, partitionPlan.GetPkModel.MethodSymbol, arg.ArgumentName, arg.PropertyName);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}