public void Execute(Processor processor, ProcessorParameters parameters)
        {
            if (processor.CancelToken.IsCancellationRequested)
            {
                return;
            }

            processor.PublishProcessMessage("Loading T4 Template Definitions...");

            IList <ITemplateDefinition> definitions = null;

            try
            {
                definitions = TemplateDefinitionHelper.GetDefinitions();
            }
            catch (Exception x)
            {
                processor.PublishErrorMessage("Failed while loading T4 Template Definitions -> {0}", x.Message);

                return;
            }

            processor.PublishMessage("{0} T4 Template Definitions loaded.", definitions.Count);

            #region [ Computing the number of files to create ]

            int totalFileNumber   = 0;
            int currentFileNumber = 0;

            foreach (var definition in definitions.Where(i => i.Type == TemplateDefinitionType.OneByTable))
            {
                foreach (var table in processor.ModelDescriptor.Schema.Tables.Where(
                             i => parameters.TableNames.Contains(i.Name, new StringIgnoreCaseEqualityComparer())))
                {
                    totalFileNumber++;
                }
            }

            foreach (var definition in definitions.Where(i => i.Type == TemplateDefinitionType.OneByBusiness))
            {
                foreach (var bcInfo in processor.BusinessContext.BusinessClasses)
                {
                    totalFileNumber++;
                }
            }

            foreach (var definition in definitions.Where(i => i.Type == TemplateDefinitionType.Normal))
            {
                totalFileNumber++;
            }

            #endregion

            processor.PublishProcessMessage("Executing T4 Templates...");

            #region [ OneByTable Section ]

            foreach (var definition in definitions.Where(i => i.Type == TemplateDefinitionType.OneByTable))
            {
                foreach (var table in processor.ModelDescriptor.Schema.Tables.Where(
                             i => parameters.TableNames.Contains(i.Name, new StringIgnoreCaseEqualityComparer())))
                {
                    if (processor.CancelToken.IsCancellationRequested)
                    {
                        return;
                    }

                    processor.PublishProcessPercentage(++currentFileNumber, totalFileNumber);

                    if (definition.CanBeExecuted(processor.Context, table))
                    {
                        string t4Template     = processor.GetTemplateFilePathToProcess(definition);
                        string outputFilePath = processor.GetOutputFilePathToCreate(definition, table.Name);

                        if (!definition.OverrideFileIfExists && File.Exists(outputFilePath))
                        {
                            continue;
                        }

                        processor.PublishProcessMessage("Processing {0} (Table = {1})...", definition.TemplatePath, table.Name);

                        var p = new Dictionary <string, object>();

                        p.Add("Context", new TextTemplatingProcessContext
                        {
                            ProcessorContext = processor.Context,
                            Schema           = processor.ModelDescriptor.Schema,
                            Table            = table,
                            BusinessClass    = processor.BusinessContext.GetBusinessClass(table.Name)
                        });

                        definition.AddParameters(processor.Context, p);
                        processor.TextTemplatingEngine.SetParameters(p);

                        processor.Process(t4Template, outputFilePath, definition, parameters);
                    }
                }
            }

            #endregion

            #region [ OneByBusiness Section ]

            foreach (var definition in definitions.Where(i => i.Type == TemplateDefinitionType.OneByBusiness))
            {
                foreach (BusinessClassInfo bcInfo in processor.BusinessContext.BusinessClasses)
                {
                    if (processor.CancelToken.IsCancellationRequested)
                    {
                        return;
                    }

                    processor.PublishProcessPercentage(++currentFileNumber, totalFileNumber);

                    if (definition.CanBeExecuted(processor.Context, new object[] { processor.ModelDescriptor, bcInfo.Name }))
                    {
                        string t4Template     = processor.GetTemplateFilePathToProcess(definition);
                        string outputFilePath = processor.GetOutputFilePathToCreate(definition, bcInfo.Name);

                        if (!definition.OverrideFileIfExists && File.Exists(outputFilePath))
                        {
                            continue;
                        }

                        processor.PublishProcessMessage("Processing {0} (Business = {1})...", definition.TemplatePath, bcInfo.Name);

                        var p = new Dictionary <string, object>();

                        p.Add("Context", new TextTemplatingProcessContext
                        {
                            ProcessorContext = processor.Context,
                            Schema           = processor.ModelDescriptor.Schema,
                            Table            = new ModelDescriptorSchemaTable {
                                Name = bcInfo.Name
                            },
                            BusinessClass = processor.BusinessContext.GetBusinessClass(bcInfo.Name)
                        });

                        definition.AddParameters(processor.Context, p);
                        processor.TextTemplatingEngine.SetParameters(p);

                        processor.Process(t4Template, outputFilePath, definition, parameters);
                    }
                }
            }

            #endregion

            #region [ Normal Section ]

            foreach (var definition in definitions.Where(i => i.Type == TemplateDefinitionType.Normal))
            {
                if (processor.CancelToken.IsCancellationRequested)
                {
                    return;
                }

                processor.PublishProcessPercentage(++currentFileNumber, totalFileNumber);

                if (definition.CanBeExecuted(processor.Context))
                {
                    string t4Template     = processor.GetTemplateFilePathToProcess(definition);
                    string outputFilePath = processor.GetOutputFilePathToCreate(definition);

                    if (!definition.OverrideFileIfExists && File.Exists(outputFilePath))
                    {
                        continue;
                    }

                    processor.PublishProcessMessage("Processing {0}...", definition.TemplatePath);

                    var p = new Dictionary <string, object>();

                    p.Add("Context", new TextTemplatingProcessContext
                    {
                        ProcessorContext = processor.Context,
                        SmoContext       = processor.SmoContext,
                        Schema           = processor.ModelDescriptor.Schema,
                        BusinessClasses  = processor.BusinessContext.BusinessClasses
                    });

                    definition.AddParameters(processor.Context, p);
                    processor.TextTemplatingEngine.SetParameters(p);

                    processor.Process(t4Template, outputFilePath, definition, parameters);
                }
            }

            #endregion
        }
        public void Execute(Processor processor, ProcessorParameters parameters)
        {
            IList <ITemplateDefinition> definitions = new List <ITemplateDefinition>
            {
                new TemplateDefinitions.Models.EntityGeneratedCsTemplateDefinition(),
            };

            #region [ Computing the number of files to create ]

            int totalFileNumber   = 0;
            int currentFileNumber = 0;

            foreach (var definition in definitions.Where(i => i.Type == TemplateDefinitionType.OneByTable))
            {
                foreach (var table in processor.ModelDescriptor.Schema.Tables /* All tables */)
                {
                    totalFileNumber++;
                }
            }

            #endregion

            foreach (var definition in definitions.Where(i => i.Type == TemplateDefinitionType.OneByTable))
            {
                foreach (var table in processor.ModelDescriptor.Schema.Tables /* All tables */)
                {
                    if (processor.CancelToken.IsCancellationRequested)
                    {
                        return;
                    }

                    processor.PublishProcessPercentage(++currentFileNumber, totalFileNumber);

                    if (definition.CanBeExecuted(processor.Context, table))
                    {
                        string t4Template     = processor.GetTemplateFilePathToProcess(definition);
                        string outputFilePath = processor.GetOutputFilePathToCreate(definition, table.Name);

                        if (!definition.OverrideFileIfExists && File.Exists(outputFilePath))
                        {
                            continue;
                        }

                        processor.PublishProcessMessage("Processing {0} (Table = {1})...", definition.TemplatePath, table.Name);

                        var p = new Dictionary <string, object>();

                        p.Add("Context", new TextTemplatingProcessContext
                        {
                            ProcessorContext = processor.Context,
                            Schema           = processor.ModelDescriptor.Schema,
                            Table            = table
                        });

                        definition.AddParameters(processor.Context, p);
                        processor.TextTemplatingEngine.SetParameters(p);

                        processor.Process(t4Template, outputFilePath, definition, parameters);
                    }
                }
            }
        }
Exemple #3
0
        internal void Process(string t4Template, string outputFilePath, ITemplateDefinition definition, ProcessorParameters parameters)
        {
            var ttParams = new TextTemplatingParameters(
                t4Template,
                outputFilePath,
                definition.OverrideFileIfExists,
                definition.AddToProject);

            string tmpOutputFilePath;

            try
            {
                var state = this.TextTemplatingEngine.Process(ttParams, out tmpOutputFilePath);

                if (state == ProcessStateEnum.Processed)
                {
                    // SQL scripts...

                    if (definition.ExecuteSqlScript)
                    {
                        bool canExecuted = true;
                        if (definition is TemplateDefinitions.Database.InsertAllStoredProceduresGeneratedSqlTemplateDefinition && !parameters.WithSqlProcedureIntegration)
                        {
                            canExecuted = false;
                        }

                        if (canExecuted)
                        {
                            this.PublishProcessMessage("Executing {0}...", Path.GetFileName(tmpOutputFilePath));

                            try
                            {
                                SmoHelper.RunSqlScript(tmpOutputFilePath, this.SmoContext);
                            }
                            catch
                            {
                                // Create a copy of the tmpOutputFilePath file (for debug) because it will be deleted at the end of the whole process...
                                FileHelper.TryCopy(tmpOutputFilePath, string.Concat(tmpOutputFilePath, ".err"), withOverwrite: true);

                                throw;
                            }
                        }
                    }
                }

                this.HasErrors |= state == ProcessStateEnum.Failed;
            }
            catch (Exception x)
            {
                this.PublishErrorMessage("Failed while processing {0} -> {1}", Path.GetFileName(t4Template), x.Message);
            }

            foreach (CompilerError error in this.TextTemplatingEngine.Errors)
            {
                this.PublishErrorMessage(
                    "Template error: {0}({1},{2}): error {3}: {4}",
                    Path.GetFileName(this.TextTemplatingEngine.Errors.First().FileName), error.Line, error.Column, error.ErrorNumber, error.ErrorText);
            }
        }
        public void Execute(Processor processor, ProcessorParameters parameters)
        {
            IList <ITemplateDefinition> definitions = new List <ITemplateDefinition>
            {
                new TemplateDefinitions.Database.TranslationInitializationGeneratedSqlTemplateDefinition(),                 // Must be the first one!
                new TemplateDefinitions.Core.TranslationEnumGeneratedCsTemplateDefinition()
            };

            #region [ Computing the number of files to create ]

            int totalFileNumber   = 0;
            int currentFileNumber = 0;

            foreach (var definition in definitions)
            {
                totalFileNumber++;
            }

            #endregion

            foreach (var definition in definitions)
            {
                if (processor.CancelToken.IsCancellationRequested)
                {
                    return;
                }

                processor.PublishProcessPercentage(++currentFileNumber, totalFileNumber);

                if (definition.CanBeExecuted(processor.Context))
                {
                    string t4Template     = processor.GetTemplateFilePathToProcess(definition);
                    string outputFilePath = processor.GetOutputFilePathToCreate(definition);

                    if (!definition.OverrideFileIfExists && File.Exists(outputFilePath))
                    {
                        continue;
                    }

                    processor.PublishProcessMessage("Processing {0}...", definition.TemplatePath);

                    var p = new Dictionary <string, object>();

                    p.Add("Context", new TextTemplatingProcessContext
                    {
                        ProcessorContext = processor.Context,
                        SmoContext       = processor.SmoContext,
                        Schema           = processor.ModelDescriptor.Schema
                    });

                    definition.AddParameters(processor.Context, p);
                    processor.TextTemplatingEngine.SetParameters(p);

                    processor.Process(t4Template, outputFilePath, definition, new ProcessorParameters
                    {
                        WithSqlProcedureIntegration = true,                         // Always execute *.generated.sql files,
                        CompilationMode             = parameters.CompilationMode
                    });
                }
            }
        }
Exemple #5
0
        public void Execute(IProcessorBehavior behavior, ProcessorParameters parameters)
        {
            if (this.IsRunning)
            {
                ThrowException.Throw("The processor is already running");
            }

            do
            {
                #region [ Begin ]

                this.IsRunning = true;

                _stopwatch = new Stopwatch();
                _stopwatch.Start();

                if (this.CancelToken != null)
                {
                    this.CancelToken.Dispose();
                }

                this.CancelToken       = new CancellationTokenSource();
                this.GeneratedServices = new List <string>();

                this.HasErrors = false;

                this.PublishProcessMessage("Running Process ({0} mode)...", parameters.CompilationMode);

                #endregion

                #region [ Checking Assemblies Dependencies ]

                if (this.CancelToken.IsCancellationRequested)
                {
                    break;
                }

                this.PublishProcessMessage("Checking Assemblies Dependencies...");

                bool bOk = true;

                string modelAssemblyPath = Path.Combine(this.Context.SrcDirectory,
                                                        string.Format(@"{0}.Models", this.Context.ProjectName),
                                                        string.Format(@"bin\{0}", parameters.CompilationMode),
                                                        string.Format(@"{0}.Models.dll", this.Context.ProjectName));

                if (!File.Exists(modelAssemblyPath))
                {
                    bOk = false;
                }

                if (bOk)
                {
                    string businessAssemblyPath = Path.Combine(this.Context.SrcDirectory,
                                                               string.Format(@"{0}.Business", this.Context.ProjectName),
                                                               string.Format(@"bin\{0}", parameters.CompilationMode),
                                                               string.Format(@"{0}.Business.dll", this.Context.ProjectName));

                    if (!File.Exists(businessAssemblyPath))
                    {
                        bOk = false;
                    }
                }

                if (!bOk)
                {
                    this.PublishErrorMessage(
                        "The whole solution must be compiled ({0} mode) before running the proccess.",
                        parameters.CompilationMode);

                    break;
                }

                #endregion

                #region [ Checking and Loading Culture Context ]

                if (this.CancelToken.IsCancellationRequested)
                {
                    break;
                }

                this.PublishProcessMessage("Checking and Loading Culture Context...");

                string[] supportedCultures = DatabaseHelper.GetCultures(this.SmoContext);
                this.Context.Culture.SupportedCultures = supportedCultures;

                if (this.Context.Culture.SupportedCultures.Length == 0)
                {
                    this.PublishErrorMessage("The 'Translation' table must define at least one culture!");

                    break;
                }

                foreach (string culture in supportedCultures.Where(c => c.Length != 2))
                {
                    this.PublishErrorMessage(
                        "The '{0}' culture column from the 'Translation' table is not correct! Culture columns must be 2 characters long.",
                        culture);

                    break;
                }

                if (!supportedCultures.Contains(this.Context.Culture.Default))
                {
                    this.PublishErrorMessage(
                        "The default culture '{0}' is not supported ({1}).",
                        this.Context.Culture.Default, string.Join(", ", supportedCultures));

                    break;
                }

                #endregion

                #region [ Checking and Loading Database Structure ]

                if (this.CancelToken.IsCancellationRequested)
                {
                    break;
                }

                this.PublishProcessMessage("Checking and Loading Database Structure...");

                this.ModelDescriptor = new ModelDescriptor(this.SmoContext, this.Context);

                string mdFile = null;

                try
                {
                    mdFile = this.ModelDescriptor.Load(this.CancelToken.Token);
                }
                catch (Exception x)
                {
                    this.PublishErrorMessage(
                        "Failed while loading Database Structure (Table: '{1}' - Column: '{2}') -> {0}",
                        x, this.ModelDescriptor.CurrentTable.Name, this.ModelDescriptor.CurrentColumn.Name);

                    break;
                }

                if (this.CancelToken.IsCancellationRequested)
                {
                    break;
                }

                if (this.ModelDescriptor.Errors.Count != 0)
                {
                    foreach (var error in this.ModelDescriptor.Errors)
                    {
                        this.PublishErrorMessage(error.GetError());
                    }

                    break;
                }

                #endregion

                #region [ Checking Authentication Support ]

                if (this.CancelToken.IsCancellationRequested)
                {
                    break;
                }

                var userTable = this.ModelDescriptor.Schema.Tables.FirstOrDefault(t => t.Name == this.Context.AuthenticationSupport.UserTableName);
                if (userTable == null)
                {
                    this.PublishErrorMessage(
                        "The '{0}' table declared in Context.AuthenticationSupport.UserTableName cannot be found in the database!",
                        this.Context.AuthenticationSupport.UserTableName);

                    break;
                }
                else
                {
                    if (userTable.Columns.Count(c => c.Name == this.Context.AuthenticationSupport.UserTableIdentifiedColumnName) == 0)
                    {
                        this.PublishErrorMessage(
                            "The '{0}' table must have a column named '{1}'!",
                            this.Context.AuthenticationSupport.UserTableName,
                            this.Context.AuthenticationSupport.UserTableIdentifiedColumnName);

                        break;
                    }

                    // UserTableIdentifiedColumnName must have an UNIQUE constraint...
                    if (userTable.Constraints == null || userTable.Constraints.Count(c => c.Columns.Any(i => i.Name == this.Context.AuthenticationSupport.UserTableIdentifiedColumnName)) == 0)
                    {
                        this.PublishErrorMessage(
                            "The '{0}' column from the '{1}' table must have an UNIQUE constraint in order to be used as identifier column!",
                            this.Context.AuthenticationSupport.UserTableIdentifiedColumnName,
                            this.Context.AuthenticationSupport.UserTableName);


                        break;
                    }

                    // UserTableName must define Password & Culture columns
                    if (userTable.Columns.Count(c => c.CSharpPropertyName == "Password") == 0 || userTable.Columns.Count(c => c.CSharpPropertyName == "Culture") == 0)
                    {
                        this.PublishErrorMessage(
                            "The '{0}' table must have '{0}_Password' and '{0}_Culture' columns!",
                            this.Context.AuthenticationSupport.UserTableName);

                        break;
                    }
                }

                #endregion

                #region [ Loading Assemblies Dependencies ]

                if (this.CancelToken.IsCancellationRequested)
                {
                    break;
                }

                this.PublishProcessMessage("Loading Assemblies Dependencies...");

                Assembly businessAssembly = null;

                try
                {
                    string tmpDir = Path.Combine(Path.GetTempPath(), "LayerCake Generator", this.Context.ProjectName);
                    if (!Directory.Exists(tmpDir))
                    {
                        Directory.CreateDirectory(tmpDir);
                    }

                    foreach (FileInfo file in new DirectoryInfo(tmpDir).GetFiles())
                    {
                        string extension = file.Extension.ToLowerInvariant();
                        if (extension == ".dll" || extension == ".pdb")
                        {
                            try
                            {
                                file.Delete();
                            }
                            catch (UnauthorizedAccessException)
                            {
                                // Occurred when the assembly is already loaded in the AppDomain.CurrentDomain
                            }
                            catch (Exception)
                            {
                            }
                        }
                    }

                    string guid = Guid.NewGuid().ToString();

                    string assemblyPath = Path.GetDirectoryName(
                        this.Context.GetAssemblyPath("Business", parameters.CompilationMode));

                    if (!Directory.Exists(assemblyPath))
                    {
                        this.PublishErrorMessage("Cannot locate the path {0}", assemblyPath);

                        break;
                    }

                    string      businessAssemblyPath = null;
                    ProxyDomain proxyDomain          = new ProxyDomain();

                    // Copy all DLL/PDB files from the Business\bin\Debug to the Temp...

                    foreach (FileInfo file in new DirectoryInfo(assemblyPath).GetFiles())
                    {
                        string extension = file.Extension.ToLowerInvariant();
                        if (extension == ".dll" || extension == ".pdb")
                        {
                            string copiedDllPath = Path.Combine(tmpDir, string.Format("{0}.{1}{2}", Path.GetFileNameWithoutExtension(file.Name), guid, extension));
                            File.Copy(file.FullName, copiedDllPath);

                            if (copiedDllPath.Contains(".Business") && Path.GetExtension(copiedDllPath).ToLowerInvariant() == ".dll")
                            {
                                businessAssemblyPath = copiedDllPath;
                            }
                        }
                    }

                    // Must be at the end once all the DLLs have been copied.
                    // (cf. AppDomain Assembly Resolving (Program.cs, CurrentDomain_AssemblyResolve))...
                    businessAssembly = proxyDomain.LoadAssembly(businessAssemblyPath);
                }
                catch (Exception x)
                {
                    this.PublishErrorMessage(
                        "Cannot load Assemblies Dependencies -> {0}",
                        x.GetFullMessage(withExceptionType: true));

                    break;
                }

                #endregion

                #region [ Loading Business Context ]

                if (this.CancelToken.IsCancellationRequested)
                {
                    break;
                }

                this.PublishProcessMessage("Loading Business Context...");

                IList <string> errors;
                this.BusinessContext = new BusinessContext(businessAssembly);

                try
                {
                    this.BusinessContext.Load(out errors);
                }
                catch (Exception x)
                {
                    this.PublishErrorMessage("Cannot load the Business Context -> {0}", x.Message);

                    break;
                }

                if (errors.Count != 0)
                {
                    foreach (string error in errors)
                    {
                        this.PublishErrorMessage(error);
                    }

                    break;
                }

                #endregion

                #region [ Creating TextTemplating TextTemplatingEngine ]

                if (this.CancelToken.IsCancellationRequested)
                {
                    break;
                }

                this.PublishProcessMessage("Creating TextTemplating Engine...");

                this.TextTemplatingEngine = new TextTemplatingEngine(
                    this.Context.SolutionDirectory,
                    this.Context.TemplateDirectory);

                this.TextTemplatingEngine.OnGeneratedFile += OnFileGenerated;

                #endregion

                #region [ Executing... ]

                behavior.Execute(this, parameters);

                #endregion
            }while (false);

            #region [ End ]

            _stopwatch.Stop();

            int nbFiles = this.TextTemplatingEngine != null?this.TextTemplatingEngine.GeneratedFiles.Count() : 0;

            string summary = string.Format("Process Duration -> {0}secs ({1} files)", (int)_stopwatch.Elapsed.TotalSeconds, nbFiles);

            if (this.HasErrors)
            {
                this.PublishErrorMessage("Undo code modifications");
                this.PublishErrorMessage(summary);
            }
            else
            {
                if (this.CancelToken.IsCancellationRequested)                 // the process has been stopped -> do not commit (-> do not call LinkGeneratedFiles())
                {
                    this.PublishErrorMessage("Undo code modifications");      // cancel user action
                }
                else
                {
                    this.LinkGeneratedFiles();
                }

                this.PublishProcessMessage(summary);
            }

            this.Clear();

            this.IsRunning = false;

            #endregion
        }