public virtual Task <ReverseEngineerFiles> GenerateAsync(
            [NotNull] ReverseEngineeringConfiguration configuration,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            Check.NotNull(configuration, nameof(configuration));

            cancellationToken.ThrowIfCancellationRequested();

            configuration.CheckValidity();

            var metadataModel = GetMetadataModel(configuration);

            var outputPathsAndNamespace = ConstructNamespaceAndCanonicalizedPaths(
                configuration.ProjectRootNamespace,
                configuration.ProjectPath, configuration.OutputPath);

            var customConfiguration = _configurationFactory
                                      .CreateCustomConfiguration(
                configuration.ConnectionString, configuration.ContextClassName,
                outputPathsAndNamespace.Namespace, configuration.UseFluentApiOnly);
            var modelConfiguration = _configurationFactory
                                     .CreateModelConfiguration(metadataModel, customConfiguration);

            var dbContextClassName =
                string.IsNullOrWhiteSpace(customConfiguration.ContextClassName)
                    ? modelConfiguration.ClassName()
                    : customConfiguration.ContextClassName;

            CheckOutputFiles(outputPathsAndNamespace.CanonicalizedFullOutputPath,
                             dbContextClassName, metadataModel, configuration.OverwriteFiles);

            return(CodeWriter.WriteCodeAsync(
                       modelConfiguration, outputPathsAndNamespace.CanonicalizedFullOutputPath,
                       dbContextClassName, cancellationToken));
        }
        public void Throws_exceptions_for_incorrect_configuration()
        {
            var configuration = new ReverseEngineeringConfiguration
            {
                ConnectionString = null,
                ProjectPath      = null,
                OutputPath       = null
            };

            Assert.Equal(CommandsStrings.ConnectionStringRequired,
                         Assert.Throws <ArgumentException>(
                             () => configuration.CheckValidity()).Message);

            configuration.ConnectionString = "NonEmptyConnectionString";
            Assert.Equal(CommandsStrings.ProjectPathRequired,
                         Assert.Throws <ArgumentException>(
                             () => configuration.CheckValidity()).Message);

            configuration.ProjectPath = "NonEmptyProjectPath";
            Assert.Equal(CommandsStrings.RootNamespaceRequired,
                         Assert.Throws <ArgumentException>(
                             () => configuration.CheckValidity()).Message);

            configuration.ContextClassName = @"Invalid!CSharp*Class&Name";
            Assert.Equal(CommandsStrings.ContextClassNotValidCSharpIdentifier(@"Invalid!CSharp*Class&Name"),
                         Assert.Throws <ArgumentException>(
                             () => configuration.CheckValidity()).Message);

            configuration.ContextClassName = "1CSharpClassNameCannotStartWithNumber";
            Assert.Equal(CommandsStrings.ContextClassNotValidCSharpIdentifier("1CSharpClassNameCannotStartWithNumber"),
                         Assert.Throws <ArgumentException>(
                             () => configuration.CheckValidity()).Message);

            configuration.ContextClassName = "volatile";  // cannot be C# keyword
            Assert.Equal(CommandsStrings.ContextClassNotValidCSharpIdentifier("volatile"),
                         Assert.Throws <ArgumentException>(
                             () => configuration.CheckValidity()).Message);

            configuration.ContextClassName = "GoodClassName";
            configuration.OutputPath       = @"\AnAbsolutePath";
            Assert.Equal(CommandsStrings.RootNamespaceRequired,
                         Assert.Throws <ArgumentException>(
                             () => configuration.CheckValidity()).Message);

            configuration.OutputPath = @"A\Relative\Path";
            Assert.Equal(CommandsStrings.RootNamespaceRequired,
                         Assert.Throws <ArgumentException>(
                             () => configuration.CheckValidity()).Message);
        }
        public void Throws_exceptions_for_incorrect_configuration()
        {
            var configuration = new ReverseEngineeringConfiguration
            {
                ConnectionString = null,
                ProjectPath = null,
                OutputPath = null
            };

            Assert.Equal(DesignCoreStrings.ConnectionStringRequired,
                Assert.Throws<ArgumentException>(
                    () => configuration.CheckValidity()).Message);

            configuration.ConnectionString = "NonEmptyConnectionString";
            Assert.Equal(DesignCoreStrings.ProjectPathRequired,
                Assert.Throws<ArgumentException>(
                    () => configuration.CheckValidity()).Message);

            configuration.ProjectPath = "NonEmptyProjectPath";
            Assert.Equal(DesignCoreStrings.RootNamespaceRequired,
                Assert.Throws<ArgumentException>(
                    () => configuration.CheckValidity()).Message);

            configuration.ContextClassName = @"Invalid!CSharp*Class&Name";
            Assert.Equal(DesignCoreStrings.ContextClassNotValidCSharpIdentifier(@"Invalid!CSharp*Class&Name"),
                Assert.Throws<ArgumentException>(
                    () => configuration.CheckValidity()).Message);

            configuration.ContextClassName = "1CSharpClassNameCannotStartWithNumber";
            Assert.Equal(DesignCoreStrings.ContextClassNotValidCSharpIdentifier("1CSharpClassNameCannotStartWithNumber"),
                Assert.Throws<ArgumentException>(
                    () => configuration.CheckValidity()).Message);

            configuration.ContextClassName = "volatile"; // cannot be C# keyword
            Assert.Equal(DesignCoreStrings.ContextClassNotValidCSharpIdentifier("volatile"),
                Assert.Throws<ArgumentException>(
                    () => configuration.CheckValidity()).Message);

            configuration.ContextClassName = "GoodClassName";
            configuration.OutputPath = @"\AnAbsolutePath";
            Assert.Equal(DesignCoreStrings.RootNamespaceRequired,
                Assert.Throws<ArgumentException>(
                    () => configuration.CheckValidity()).Message);

            configuration.OutputPath = @"A\Relative\Path";
            Assert.Equal(DesignCoreStrings.RootNamespaceRequired,
                Assert.Throws<ArgumentException>(
                    () => configuration.CheckValidity()).Message);
        }