diff --git a/.gitignore b/.gitignore index 8a30d25..85ef86d 100644 --- a/.gitignore +++ b/.gitignore @@ -262,9 +262,9 @@ ServiceFabricBackup/ *.rptproj.bak # SQL Server files -*.mdf -*.ldf -*.ndf +#*.mdf +#*.ldf +#*.ndf # Business Intelligence projects *.rdl.data diff --git a/src/Architecture/.gitignore b/src/Architecture/.gitignore new file mode 100644 index 0000000..d634df6 --- /dev/null +++ b/src/Architecture/.gitignore @@ -0,0 +1,401 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.tlog +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio 6 auto-generated project file (contains which files were open etc.) +*.vbp + +# Visual Studio 6 workspace and project file (working project files containing files to include in project) +*.dsw +*.dsp + +# Visual Studio 6 technical files +*.ncb +*.aps + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# Visual Studio History (VSHistory) files +.vshistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +# VS Code files for those working on multiple tools +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.code-workspace + +# Local History for Visual Studio Code +.history/ + +# Windows Installer files from build outputs +*.cab +*.msi +*.msix +*.msm +*.msp + +# JetBrains Rider +*.sln.iml + +# CodeFactory Working Directories +**/[Cc]ode[Ff]actory/* diff --git a/src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/AddMissingLogicMembers.cs b/src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/CSharpFile/AddMissingLogicMembers.cs similarity index 98% rename from src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/AddMissingLogicMembers.cs rename to src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/CSharpFile/AddMissingLogicMembers.cs index 595f5b0..b9c6ce3 100644 --- a/src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/AddMissingLogicMembers.cs +++ b/src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/CSharpFile/AddMissingLogicMembers.cs @@ -14,7 +14,7 @@ using System.Threading.Tasks; using System.Windows; -namespace CodeFactory.Architecture.AspNetCore.Service.Rest +namespace CodeFactory.Architecture.AspNetCore.Service.Rest.CSharpFile { /// /// Code factory command for automation of a C# document when selected from a project in solution explorer. @@ -210,14 +210,13 @@ public override async Task ExecuteCommandAsync(VsCSharpSource result) var boundChecks = new List { - - new BoundsCheckBlockNullNDFException(true,loggerBlock), - new BoundsCheckBlockStringNDFException(true,loggerBlock) + new BoundsCheckBlockStringNDFException(true,loggerBlock), + new BoundsCheckBlockNullNDFException(true,loggerBlock) }; var tryBlock = new TryBlockStandard(loggerBlock,catchBlocks); - var updatedlogicClass = await VisualStudioActions.AddClassMissingMembersAsync(result.SourceCode,logicClass,false,loggerBlock,Microsoft.Extensions.Logging.LogLevel.Information,boundChecks,tryBlock,missingMembers); + var updatedLogicClass = await VisualStudioActions.AddClassMissingMembersAsync(result.SourceCode,logicClass,false,loggerBlock,Microsoft.Extensions.Logging.LogLevel.Information,boundChecks,tryBlock,missingMembers); } catch (CodeFactoryException cfException) diff --git a/src/Architecture/CodeFactory.Architecture.Blazor.Server/AddMissingRepositoryMembers.cs b/src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/CSharpFile/AddMissingRepositoryMembers.cs similarity index 99% rename from src/Architecture/CodeFactory.Architecture.Blazor.Server/AddMissingRepositoryMembers.cs rename to src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/CSharpFile/AddMissingRepositoryMembers.cs index 183babc..9db81f5 100644 --- a/src/Architecture/CodeFactory.Architecture.Blazor.Server/AddMissingRepositoryMembers.cs +++ b/src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/CSharpFile/AddMissingRepositoryMembers.cs @@ -16,7 +16,7 @@ using System.Threading.Tasks; using System.Windows; -namespace CodeFactory.Architecture.Blazor.Server +namespace CodeFactory.Architecture.AspNetCore.Service.Rest.CSharpFile { /// /// Code factory command for automation of a C# document when selected from a project in solution explorer. diff --git a/src/Architecture/CodeFactory.Architecture.Blazor.Server/RefreshEFRepository.cs b/src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/CSharpFile/RefreshEFRepository.cs similarity index 68% rename from src/Architecture/CodeFactory.Architecture.Blazor.Server/RefreshEFRepository.cs rename to src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/CSharpFile/RefreshEFRepository.cs index a774736..96b5d8e 100644 --- a/src/Architecture/CodeFactory.Architecture.Blazor.Server/RefreshEFRepository.cs +++ b/src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/CSharpFile/RefreshEFRepository.cs @@ -15,8 +15,10 @@ using System.Text; using System.Threading.Tasks; using System.Windows; +using CodeFactory.Automation.NDF.Logic.Testing.MSTest; +using CodeFactory.Automation.NDF.Logic.General; -namespace CodeFactory.Architecture.Blazor.Server +namespace CodeFactory.Architecture.AspNetCore.Service.Rest.CSharpFile { /// /// Code factory command for automation of a C# document when selected from a project in solution explorer. @@ -92,27 +94,60 @@ public RefreshEFRepository(ILogger logger, IVsActions vsActions) : base(logger, /// public static string IntegrationTestFolder = "IntegrationTestFolder"; + /// + /// The name of the entity framework context class. + /// public static string EFContextClassName = "EFContextClassName"; /// - /// Comma seperated list of the prefixes to remove from the EF class name when generating the target application entity model. + /// Optional, list of prefixes seperated by comma to remove from the name of the entity framework entity. + /// + public static string EFEntityRemovePrefixes = "EFEntityRemovePrefixes"; + + /// + /// Optional, list of prefixes seperated by comma to remove from the name of the entity framework entity. + /// + public static string EFEntityRemoveSuffixes = "EFEntityRemoveSuffixes"; + + /// + /// Optional, prefix to assign to a repository when creating. + /// + public static string RepositoryPrefix = "RepositoryPrefix"; + + /// + /// Optional, suffix to assign to a repository when creating. + /// + public static string RepositorySuffix = "RepositorySuffix"; + + /// + /// Optional, prefix to assign to a application model when creating. + /// + public static string AppModelPrefix ="AppModelPrefix"; + + /// + /// Optional, suffix to assign to a application model when creating. /// - public static string RemoveNamePrefixesForEntityModel = "RemoveNamePrefixesForEntityModel"; + public static string AppModelSuffix ="AppModelSuffix"; /// - /// The repository and repository contract suffix to assign. + /// Optional, prefix to assign to a integration test when creating. /// - public static string RepositoryAndContractSuffix = "RepositoryAndContractSuffix"; + public static string TestPrefix ="TestPrefix"; /// - /// The prefix to assign to the name of a models validation class. + /// Optional, suffix to assign to a integration test when creating. /// - public static string ModelValidatorPrefix = "ModelValidatorPrefix"; + public static string TestSuffix ="TestSuffix"; /// - /// The suffix to assign to the name of a models validation class. + /// The prefix to assign to the name of a application models validation class. /// - public static string ModelValidatorSuffix = "ModelValidatorSuffix"; + public static string AppModelValidatorPrefix = "AppModelValidatorPrefix"; + + /// + /// The suffix to assign to the name of a application models validation class. + /// + public static string AppModelValidatorSuffix = "AppModelValidatorSuffix"; /// /// Loads the external configuration definition for this command. @@ -150,35 +185,18 @@ public override ConfigCommand LoadExternalConfigDefinition() ( new ConfigParameter { - Name = RemoveNamePrefixesForEntityModel, - Guidance = "Comma seperated value list of the prefixes in case sensititve format to be removed from the application entity name." - } - ) - .AddParameter - ( - new ConfigParameter - { - Name= RepositoryAndContractSuffix, - Guidance = "Suffix to be assigned to the name of the repository and the contract for the repository." + Name = EFEntityRemovePrefixes, + Guidance = "Comma seperated value list of the prefixes in case sensitive format to be removed from the entity framework entity name when creating new objects." } ) .AddParameter ( new ConfigParameter - { - Name= ModelValidatorPrefix, - Guidance = "The prefix to assign to the name of a models validation class." - } - ) - .AddParameter - ( - new ConfigParameter - { - Name= ModelValidatorSuffix, - Guidance = "The suffix to assign to the name of a models validation class." + { + Name = EFEntityRemoveSuffixes, + Guidance = "Comma seperated value list of the suffixes in case sensitive format to be removed from the entity framework entity name when creating new objects." } ) - ) .AddProject ( @@ -198,6 +216,41 @@ public override ConfigCommand LoadExternalConfigDefinition() "Optional, set the relative path from the root of the project. If it is more then one directory deep then use '/' instead of back slashes." } ) + .AddParameter + ( + new ConfigParameter + { + Name = AppModelPrefix, + Guidance = "Optional, prefix to assign to the application model entity when it is created." + } + ) + .AddParameter + ( + new ConfigParameter + { + Name = AppModelSuffix, + Guidance = "Optional, suffix to assign to the application model entity when it is created.", + Value = "AppModel" + } + ) + .AddParameter + ( + new ConfigParameter + { + Name = AppModelValidatorPrefix, + Guidance = "Optional, prefix to assign to the application model entity validator when it is created." + + } + ) + .AddParameter + ( + new ConfigParameter + { + Name = AppModelValidatorSuffix, + Guidance = "Optional, suffix to assign to the application model entity validator when it is created.", + Value = "Validator" + } + ) ) .AddProject ( @@ -217,6 +270,23 @@ public override ConfigCommand LoadExternalConfigDefinition() "Optional, set the relative path from the root of the project. If it is more then one directory deep then use '/' instead of back slashes." } ) + .AddParameter + ( + new ConfigParameter + { + Name = RepositoryPrefix, + Guidance = "Optional, prefix to assign to the repository when it is created." + } + ) + .AddParameter + ( + new ConfigParameter + { + Name = RepositorySuffix, + Guidance = "Optional, suffix to assign to the repository when it is created.", + Value = "Repository" + } + ) ) .AddProject ( @@ -255,6 +325,23 @@ public override ConfigCommand LoadExternalConfigDefinition() "Optional, set the relative path from the root of the project. If it is more then one directory deep then use '/' instead of back slashes." } ) + .AddParameter + ( + new ConfigParameter + { + Name = TestPrefix, + Guidance = "Optional, prefix to assign to the integration test when it is created." + } + ) + .AddParameter + ( + new ConfigParameter + { + Name = TestSuffix, + Guidance = "Optional, suffix to assign to the integration test when it is created.", + Value = "Test" + } + ) ); return command; @@ -307,18 +394,31 @@ public override async Task ExecuteCommandAsync(VsCSharpSource result) VsProjectFolder efModelFolder = await VisualStudioActions.GetProjectFolderFromConfigAsync(command.ExecutionProject, ExecutionModelFolder); + var contextClassName = command.ExecutionProject.ParameterValue(EFContextClassName); + var efEntityRemovePrefixs = command.ExecutionProject.ParameterValue(EFEntityRemovePrefixes); + var efEntityRemoveSuffixes = command.ExecutionProject.ParameterValue(EFEntityRemoveSuffixes); + VsProject appModelProject = await VisualStudioActions.GetProjectFromConfigAsync(command.Project(EntityProject)) ?? throw new CodeFactoryException("Could not load the entity model project, cannot refresh the EF repository."); VsProjectFolder appModelFolder = await VisualStudioActions.GetProjectFolderFromConfigAsync(command.Project(EntityProject), EntityFolder); + var appModelPrefix = command.Project(EntityProject).ParameterValue(AppModelPrefix); + var appModelSuffix = command.Project(EntityProject).ParameterValue(AppModelSuffix); + var appModelValidatorPrefix = command.Project(EntityProject).ParameterValue(AppModelValidatorPrefix); + var appModelValidatorSuffix = command.Project(EntityProject).ParameterValue(AppModelValidatorSuffix); + VsProject repoProject = await VisualStudioActions.GetProjectFromConfigAsync(command.Project(RepoProject)) ?? throw new CodeFactoryException("Could not load the repository project, cannot refresh the EF repository."); VsProjectFolder repoFolder = await VisualStudioActions.GetProjectFolderFromConfigAsync(command.Project(RepoProject), RepoFolder); + var repoPrefix = command.Project(RepoProject).ParameterValue(RepositoryPrefix); + + var repoSuffix = command.Project(RepoProject).ParameterValue(RepositorySuffix); + VsProject contractProject = await VisualStudioActions.GetProjectFromConfigAsync(command.Project(RepoContractProject)) ?? throw new CodeFactoryException( @@ -334,31 +434,9 @@ await VisualStudioActions.GetProjectFromConfigAsync(command.Project(RepoContract await VisualStudioActions.GetProjectFolderFromConfigAsync(command.Project(IntegrationTestProject), IntegrationTestFolder); - var contextClassName = command.ExecutionProject.ParameterValue(EFContextClassName); - - var appModelPrefixReplacements = command.ExecutionProject.ParameterValue(RemoveNamePrefixesForEntityModel); - - var modelValidatorPrefix = command.ExecutionProject.ParameterValue(ModelValidatorPrefix); - var modelValidatorSuffix = command.ExecutionProject.ParameterValue(ModelValidatorSuffix); + var testPrefix = testProject != null ? command.Project(IntegrationTestProject).ParameterValue(TestPrefix) : null; - NameManagement nameManagement = null; - - if(!string.IsNullOrEmpty(appModelPrefixReplacements)) - { - var prefixes = appModelPrefixReplacements.Split(','); - - var renamePrefixes = new List(); - foreach (var prefix in prefixes) - { - var formattedPrefix = prefix.Trim(); - - if(!string.IsNullOrEmpty(formattedPrefix)) renamePrefixes.Add(formattedPrefix); - } - - if(renamePrefixes.Any()) nameManagement = NameManagement.Init(renamePrefixes,null,null,null); - } - - string repositorySuffix = command.ExecutionProject.ParameterValue(RepositoryAndContractSuffix); + var testSuffix = testProject != null ? command.Project(IntegrationTestProject).ParameterValue(TestSuffix) : null; if (string.IsNullOrWhiteSpace(contextClassName)) throw new CodeFactoryException( @@ -377,25 +455,44 @@ await VisualStudioActions.GetProjectFolderFromConfigAsync(command.Project(Integr var efModel = result.SourceCode?.Classes?.FirstOrDefault() ?? throw new CodeFactoryException("The EF entity class could not be loaded, cannot refresh the EF repository."); - var appModel = (await VisualStudioActions.RefreshPOCOAsync(efModel, appModelProject, + var nameManagement = NameManagement.Init(efEntityRemovePrefixs,efEntityRemoveSuffixes,appModelPrefix,appModelSuffix); + + var appModel = (await VisualStudioActions.RefreshModelAsync(efModel, appModelProject, EntityModelNamespaces(),nameManagement, appModelFolder, $"Application data model that supports '{efModel.Name}'", true,useSourceProperty: RepositoryBuilder.UseSourceProperty)) ?? throw new CodeFactoryException($"Could not load the entity that supports the ef model '{efModel.Name}', cannot refresh the EF repository."); - NameManagement modelValidatorNameManagement = null; - if(!string.IsNullOrEmpty(modelValidatorSuffix) | !string.IsNullOrEmpty(modelValidatorPrefix)) modelValidatorNameManagement = NameManagement.Init(null,null,modelValidatorPrefix, modelValidatorSuffix); - + string noReplacePrefix = null; + string noReplaceSuffix = null; - var validation = (await VisualStudioActions.RefreshValidationAsync(appModel,appModelProject,appModelFolder,modelValidatorNameManagement)) + var modelValidatorNameManagement = NameManagement.Init(noReplacePrefix,noReplaceSuffix,appModelValidatorPrefix,appModelValidatorSuffix); + + var validation = (await VisualStudioActions.RefreshValidationClassAsync(appModel,appModelProject,appModelFolder,modelValidatorNameManagement)) ?? throw new CodeFactoryException($"Could not refresh the validation for the app model '{appModel.Name}', cannot refresh the EF repository."); await VisualStudioActions.RefreshFluentValidationAsync(efModel,appModel,validation); - await VisualStudioActions.RefreshEntityFrameworkEntityTransform(appModel, efModel, efModelProject, efModelFolder); - var repoClass = await VisualStudioActions.RefreshEFRepositoryAsync(efModel, repoProject, contractProject, appModel, - contextClass, supportsNDF, supportsLogging, repoFolder, contractFolder,nameSuffix:repositorySuffix); + var repositoryName = NameManagement.Init(efEntityRemovePrefixs,efEntityRemoveSuffixes,repoPrefix,repoSuffix).FormatName(efModel.Name); + + var repoClass = await VisualStudioActions.RefreshEFRepositoryAsync(repositoryName,efModel, repoProject, contractProject, appModel, + contextClass, supportsNDF, supportsLogging, repoFolder, contractFolder); + + + if(repoClass != null & testProject != null) + { + var contractName = $"I{repositoryName}"; + + CsInterface contractInterface = contractFolder != null ? (await contractFolder.FindCSharpSourceByInterfaceNameAsync(contractName))?.SourceCode?.Interfaces?.FirstOrDefault() + : (await contractProject.FindCSharpSourceByInterfaceNameAsync(contractName))?.SourceCode?.Interfaces?.FirstOrDefault(); + + if(contractInterface != null) + { + var testName = NameManagement.Init(noReplacePrefix,noReplaceSuffix,testPrefix,testSuffix).FormatName(repositoryName); + await VisualStudioActions.RefreshMSTestIntegrationTestAsync(testName, contractInterface,testProject); + } + } } catch (CodeFactoryException codeFactoryError) diff --git a/src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/RefreshFluentValidation.cs b/src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/CSharpFile/RefreshFluentValidation.cs similarity index 94% rename from src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/RefreshFluentValidation.cs rename to src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/CSharpFile/RefreshFluentValidation.cs index 0dd97d9..a84831c 100644 --- a/src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/RefreshFluentValidation.cs +++ b/src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/CSharpFile/RefreshFluentValidation.cs @@ -12,8 +12,9 @@ using System.Linq; using System.Text; using System.Threading.Tasks; +using System.Windows; -namespace CodeFactory.Architecture.AspNetCore.Service.Rest +namespace CodeFactory.Architecture.AspNetCore.Service.Rest.CSharpFile { /// /// Code factory command for automation of a C# document when selected from a project in solution explorer. @@ -168,12 +169,19 @@ await VisualStudioActions.GetProjectFromConfigAsync(command.ExecutionProject) var validatorSuffix = command.ExecutionProject.ParameterValue(ModelValidatorSuffix); + string removePrefixes = null; + string removeSuffixes = null; + NameManagement nameManagement = null; - if(!string.IsNullOrEmpty(validatorPrefix) | !string.IsNullOrEmpty(validatorSuffix)) nameManagement = NameManagement.Init(null,null, validatorPrefix, validatorSuffix); + if(!string.IsNullOrEmpty(validatorPrefix) | !string.IsNullOrEmpty(validatorSuffix)) nameManagement = NameManagement.Init(removePrefixes,removeSuffixes, validatorPrefix, validatorSuffix); var validationClass = VisualStudioActions.RefreshValidationAsync(sourceClass, sourceProject,sourceFolder,nameManagement); } + catch (CodeFactoryException codeFactoryError) + { + MessageBox.Show(codeFactoryError.Message, "Automation Error", MessageBoxButton.OK, MessageBoxImage.Error); + } catch (Exception unhandledError) { _logger.Error($"The following unhandled error occurred while executing the solution explorer C# document command {commandTitle}. ", diff --git a/src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/CSharpFile/RefreshLogic.cs b/src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/CSharpFile/RefreshLogic.cs new file mode 100644 index 0000000..347ac4f --- /dev/null +++ b/src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/CSharpFile/RefreshLogic.cs @@ -0,0 +1,305 @@ +using CodeFactory.Automation.NDF.Logic.General; +using CodeFactory.Automation.Standard.Logic; +using CodeFactory.WinVs; +using CodeFactory.WinVs.Commands; +using CodeFactory.WinVs.Commands.SolutionExplorer; +using CodeFactory.WinVs.Logging; +using CodeFactory.WinVs.Models.CSharp; +using CodeFactory.WinVs.Models.CSharp.Builder; +using CodeFactory.WinVs.Models.ProjectSystem; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; + +namespace CodeFactory.Architecture.AspNetCore.Service.Rest.CSharpFile +{ + /// + /// Code factory command for automation of a C# document when selected from a project in solution explorer. + /// + public class RefreshLogic : CSharpSourceCommandBase + { + private static readonly string commandTitle = "Refresh Logic"; + private static readonly string commandDescription = "Refreshes the logic implementation for the target logic interface."; + +#pragma warning disable CS1998 + + /// + public RefreshLogic(ILogger logger, IVsActions vsActions) : base(logger, vsActions, commandTitle, commandDescription) + { + //Intentionally blank + } + + #region External Configuration + + /// + /// The fully qualified name of the command to be used with configuration. + /// + public static string Type = typeof(RefreshLogic).FullName; + + /// + /// Exection project for the command. + /// + public static string ExecutionProject = "ExecutionProject"; + + /// + /// Execution folder for the command. + /// + public static string ExecutionFolder = "ExecutionFolder"; + + /// + /// The logic project that holds the logic class to be refreshed. + /// + public static string LogicProject = "LogicProject"; + + /// + /// Optional, folder where the logic class it be refreshed is located. + /// + public static string LogicFolder = "LogicFolder"; + + /// + /// Optional, comma seperated value list of prefixes to be removed from the logic contracts name. + /// + public static string RemovePrefixes = "RemovePrefixes"; + + /// + /// Optional, comma seperated value list of the suffixes to be removed from the logic contract name. + /// + public static string RemoveSuffixes = "RemoveSuffixes"; + + /// + /// Optional, the prefix to append to the logic class name. + /// + public static string LogicPrefix = "LogicPrefix"; + + /// + /// Optional, the suffix to append to the logic class name. + /// + public static string LogicSuffix = "LogicSuffix"; + + /// + /// Loads the external configuration definition for this command. + /// + /// Will return the command configuration or null if this command does not support external configurations. + public override ConfigCommand LoadExternalConfigDefinition() + { + return new ConfigCommand { Name = commandTitle, Category = "Logic", CommandType = Type, } + .UpdateExecutionProject + ( + new ConfigProject + { + Name = ExecutionProject, + Guidance = "Project that contains the interface that triggers the automation." + } + .AddFolder + ( + new ConfigFolder + { + Name = ExecutionFolder, + Required = false, + Guidance = "Optional, project folder that contains the interface that triggers the automation." + } + ) + .AddParameter + ( + new ConfigParameter + { + Name = RemovePrefixes, + Guidance = "Optional, comma seperated value list of prefix values to remove from the interface name." + } + ) + .AddParameter + ( + new ConfigParameter + { + Name = RemoveSuffixes, + Guidance = "Optional, comma seperated value list of suffix values to remove from the interface name." + } + ) + + ) + .AddProject + ( + new ConfigProject + { + Name = LogicProject, + Guidance = "Name of the project that hosts the logic class to be refreshed." + } + .AddFolder + ( + new ConfigFolder + { + Name = LogicFolder, + Required = false, + Guidance = "Optional, The project folder the logic class is hosted in." + } + ) + .AddParameter + ( + new ConfigParameter + { + Name = LogicPrefix, + Guidance = "Optional, the prefix to append to the logic class name." + + } + ) + .AddParameter + ( + new ConfigParameter + { + Name = LogicSuffix, + Guidance = "Optional, the suffix to append to the logic class name." + + } + ) + ); + + + } + #endregion + + #region Overrides of VsCommandBase + + /// + /// Validation logic that will determine if this command should be enabled for execution. + /// + /// The target model data that will be used to determine if this command should be enabled. + /// Boolean flag that will tell code factory to enable this command or disable it. + public override async Task EnableCommandAsync(VsCSharpSource result) + { + //Result that determines if the command is enabled and visible in the context menu for execution. + bool isEnabled = false; + + try + { + + var logicContract = result.SourceCode?.Interfaces.FirstOrDefault(); + + isEnabled = logicContract != null; + + ConfigCommand command = null; + + if( isEnabled ) + { + command = await ConfigManager.LoadCommandByFolderAsync(Type, ExecutionFolder, result) + ?? await ConfigManager.LoadCommandByProjectAsync(Type, result); + + isEnabled = command != null; + } + + if(isEnabled) isEnabled = await LogicNeedsUpdatesAsync(command,logicContract); + + } + catch (Exception unhandledError) + { + _logger.Error($"The following unhandled error occurred while checking if the solution explorer C# document command {commandTitle} is enabled. ", + unhandledError); + isEnabled = false; + } + + return isEnabled; + } + + /// + /// Code factory framework calls this method when the command has been executed. + /// + /// The code factory model that has generated and provided to the command to process. + public override async Task ExecuteCommandAsync(VsCSharpSource result) + { + try + { + var logicContract = result.SourceCode?.Interfaces.FirstOrDefault() + ?? throw new CodeFactoryException("Could not load the source interface cannot refresh the logic."); + + var commandConfig = await ConfigManager.LoadCommandByFolderAsync(Type, ExecutionFolder, result) + ?? await ConfigManager.LoadCommandByProjectAsync(Type, result) + ?? throw new CodeFactoryException("Could not load the configuratin, cannot refresh the logic"); + + var logicName = GenerateLogicClassName(commandConfig,logicContract) + ?? throw new CodeFactoryException("Could not determine the logic class name, cannot refresh the logic"); + + var contractProject = await VisualStudioActions.GetProjectFromConfigAsync(commandConfig.ExecutionProject) + ?? throw new CodeFactoryException("Cannot load the contract interface project, cannot refresh the logic"); + + var contractProjectFolder = await VisualStudioActions.GetProjectFolderFromConfigAsync(commandConfig.ExecutionProject,ExecutionFolder); + + var logicProject = await VisualStudioActions.GetProjectFromConfigAsync(commandConfig.Project(LogicProject)) + ?? throw new CodeFactoryException("Could not load the logic project, cannot refresh the logic."); + + var logicProjectFolder = await VisualStudioActions.GetProjectFolderFromConfigAsync(commandConfig.Project(LogicProject),LogicFolder); + + await VisualStudioActions.RefreshLogicAsync(logicName,logicContract.Name,logicProject,contractProject,logicFolder:logicProjectFolder,contractFolder: contractProjectFolder); + + } + catch (CodeFactoryException codeFactoryError) + { + MessageBox.Show(codeFactoryError.Message, "Automation Error", MessageBoxButton.OK, MessageBoxImage.Error); + } + catch (Exception unhandledError) + { + _logger.Error($"The following unhandled error occurred while executing the solution explorer C# document command {commandTitle}. ", + unhandledError); + + } + + } + + #endregion + + /// + /// Helper method that determines if the command should be activated. Checks to make sure all the conditions are met to refresh the logic. + /// + /// The commands configuration. + /// The source interface that is being used to refresh the logic. + /// True if the command should be enabled, false if not. + private async Task LogicNeedsUpdatesAsync(ConfigCommand command,CsInterface interfaceContract) + { + + var logicProject = await VisualStudioActions.GetProjectFromConfigAsync(command.Project(LogicProject)); + + if(logicProject == null) return false; + + var logicFolder = await VisualStudioActions.GetProjectFolderFromConfigAsync(command.Project(LogicProject),LogicFolder); + + var logicClassName = GenerateLogicClassName(command,interfaceContract); + + if(logicClassName == null) return false; + + var logicSource = logicFolder != null + ? await logicFolder.FindCSharpSourceByClassNameAsync(logicClassName,false) + : await logicProject.FindCSharpSourceByClassNameAsync(logicClassName,false); + + if(logicSource == null) return true; + + var logicClass = logicSource?.SourceCode?.Classes?.FirstOrDefault(); + + if(logicClass == null) return false; + + return logicClass.GetMissingInterfaceMembers().Any(); + + } + + /// + /// Generates the name of the logic class to be refreshed. + /// + /// The command configuration to use to generate the class name. + /// The interface that implements the logic class to refresh. + /// Formatted name or null if the name cannot be determined. + private string GenerateLogicClassName(ConfigCommand command,CsInterface interfaceContract) + { + if(command == null) return null; + + if(interfaceContract == null) return null; + + var removePrefixes = command.ExecutionProject.ParameterValue(RemovePrefixes); + var removeSuffixes = command.ExecutionProject.ParameterValue(RemoveSuffixes); + var logicPrefix = command.Project(LogicProject).ParameterValue(LogicPrefix); + var logicSuffix = command.Project(LogicProject).ParameterValue(LogicSuffix); + + return NameManagement.Init(removePrefixes,removeSuffixes, logicPrefix, logicSuffix).FormatName(interfaceContract.Name.GenerateCSharpFormattedClassName()); + + } + } +} diff --git a/src/Architecture/CodeFactory.Architecture.Blazor.Server/RefreshRestService.cs b/src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/CSharpFile/RefreshRestService.cs similarity index 76% rename from src/Architecture/CodeFactory.Architecture.Blazor.Server/RefreshRestService.cs rename to src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/CSharpFile/RefreshRestService.cs index 26a7a61..4bd6c02 100644 --- a/src/Architecture/CodeFactory.Architecture.Blazor.Server/RefreshRestService.cs +++ b/src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/CSharpFile/RefreshRestService.cs @@ -1,4 +1,5 @@ using CodeFactory.Automation.NDF.Logic.AspNetCore.Service.Rest.Json; +using CodeFactory.Automation.Standard.Logic; using CodeFactory.WinVs; using CodeFactory.WinVs.Commands; using CodeFactory.WinVs.Commands.SolutionExplorer; @@ -13,7 +14,7 @@ using System.Threading.Tasks; using System.Windows; -namespace CodeFactory.Architecture.Blazor.Server +namespace CodeFactory.Architecture.AspNetCore.Service.Rest.CSharpFile { /// /// Code factory command for automation of a C# document when selected from a project in solution explorer. @@ -69,25 +70,30 @@ public RefreshRestService(ILogger logger, IVsActions vsActions) : base(logger, v public static string ModelFolder = "ModelFolder"; /// - /// The target project that the abstraction logic will be hosted. + /// The target project where abstraction contracts will be created. /// - public static string AbstractionProject = "AbstractionProject"; + public static string ContractProject = "ContractProject"; /// - /// The target folder where abstraction logic will be hosted, this is optional. + /// The target folder where abstraction contracts will be created, this is optional /// - public static string AbstractionFolder = "AbstractionFolder"; + public static string ContractFolder = "ContractFolder"; /// - /// The target project where abstraction contracts will be created. + /// Comma separated list of prefixes to remove from the logc contract when creating the service name. /// - public static string ContractProject = "ContractProject"; + public static string ServiceNameRemovePrefixes = "ServiceNameRemovePrefixes"; /// - /// The target folder where abstraction contracts will be created, this is optional + /// Comma separated list of suffixes to remove from the logic contract when creating the service name. /// - public static string ContractFolder = "ContractFolder"; + public static string ServiceNameRemoveSuffixes = "ServiceNameRemoveSuffixes"; + /// + /// Prefix to start the service name with. + /// + public static string ServiceNameAppendPrefix = "ServiceNameAppendPrefix"; + /// /// Loads the external configuration definition for this command. /// @@ -104,7 +110,7 @@ public override ConfigCommand LoadExternalConfigDefinition() Guidance = "Enter the fully project name for the logic contracts project." } .AddFolder - ( + ( new ConfigFolder { Name = ExecutionFolder, @@ -113,6 +119,31 @@ public override ConfigCommand LoadExternalConfigDefinition() "Optional, set the relative path from the root of the project. If it is more then one directory deep then use forward slash instead of back slashes." } ) + .AddParameter + ( + new ConfigParameter + { + Name = ServiceNameRemovePrefixes, + Guidance = "Optional, provide a comma separated value of each prefix to check for to be removed from the logic contract name when creating a service name." + } + ) + .AddParameter + ( + new ConfigParameter + { + Name = ServiceNameRemoveSuffixes, + Guidance = "Optional, provide a comma separated value of each suffix to check for to be removed from the logic contract name when creating a service name.", + Value = "Logic" + } + ) + .AddParameter + ( + new ConfigParameter + { + Name = ServiceNameAppendPrefix, + Guidance = "Optional, provide the prefix to append to the service name." + } + ) ) .AddProject ( @@ -123,7 +154,7 @@ public override ConfigCommand LoadExternalConfigDefinition() "Enter the full project name for the project that hosts the WebAPI service implementation of the logic contract." } .AddFolder - ( + ( new ConfigFolder { Name = ServiceFolder, @@ -143,7 +174,7 @@ public override ConfigCommand LoadExternalConfigDefinition() "Enter the full project name for the project that hosts the rest service models used by the services." } .AddFolder - ( + ( new ConfigFolder { Name = ModelFolder, @@ -152,46 +183,8 @@ public override ConfigCommand LoadExternalConfigDefinition() "Optional, set the relative path from the root of the project. If it is more then one directory deep then use forward slash instead of back slashes." } ) - ) - .AddProject - ( - new ConfigProject - { - Name = AbstractionProject, - Guidance = - "Enter the full project name for the project that hosts the abstraction implementation of the service." - } - .AddFolder - ( - new ConfigFolder - { - Name = AbstractionFolder, - Required = false, - Guidance = - "Optional, set the relative path from the root of the project. If it is more then one directory deep then use forward slah instead of back slashes." - } - ) - ) - .AddProject - ( - new ConfigProject - { - Name = ContractProject, - Guidance = - "Enter the full project name for the project that hosts interface contracts for the abstraction implementation." - } - .AddFolder - ( - new ConfigFolder - { - Name = ContractFolder, - Required = false, - Guidance = - "Optional, set the relative path from the root of the project. If it is more then one directory deep then use '/' instead of back slashes." - } - ) ); - + return command; } #endregion @@ -256,31 +249,21 @@ await VisualStudioActions.GetProjectFromConfigAsync(command.Project(ModelProject var modelFolder = await VisualStudioActions.GetProjectFolderFromConfigAsync(command.Project(ModelProject), ModelFolder); - var abstractionProject = - await VisualStudioActions.GetProjectFromConfigAsync(command.Project(AbstractionProject)) - ?? throw new CodeFactoryException("Cannot load the abstraction project, cannot refresh the service."); - - var abstractionFolder = - await VisualStudioActions.GetProjectFolderFromConfigAsync(command.Project(AbstractionProject), AbstractionFolder); - - var contractProject = - await VisualStudioActions.GetProjectFromConfigAsync(command.Project(ContractProject)) - ?? throw new CodeFactoryException("Cannot load the abstraction contract project, cannot refresh the service."); - var contractFolder = await VisualStudioActions.GetProjectFolderFromConfigAsync(command.Project(ContractProject), ContractFolder); - var serviceClass = await VisualStudioActions.RefreshJsonRestService(logicContract, serviceProject, serviceFolder, - modelProject,modelFolder) - ?? throw new CodeFactoryException("Could not refresh the rest json service, cannot refresh the abstraction implementation."); + //Execution command parameters. + var serviceNameRemovePrefixes = command.ExecutionProject.ParameterValue(ServiceNameRemovePrefixes); + var serviceNameRemoveSuffixes = command.ExecutionProject.ParameterValue(ServiceNameRemoveSuffixes); + var serviceNameAppendPrefix = command.ExecutionProject.ParameterValue(ServiceNameAppendPrefix); + var serviceNameManagement = NameManagement.Init(serviceNameRemovePrefixes,serviceNameRemoveSuffixes,serviceNameAppendPrefix,null); - var abstractionContract = await VisualStudioActions.RefreshCSharpAbstractionContractAsync(logicContract, contractProject, contractFolder) - ?? throw new CodeFactoryException("Could not refresh the abstraction contract. The abstraction cannot be updated."); - - var abstractionClass = await VisualStudioActions.RefreshAbstractionClass(serviceClass,abstractionContract,serviceProject,abstractionProject,modelProject,abstractionFolder,modelFolder); - + var serviceName = serviceNameManagement.FormatName(logicContract.Name.GenerateCSharpFormattedClassName()); + var serviceClass = await VisualStudioActions.RefreshJsonRestService(serviceName,logicContract, serviceProject, serviceFolder, + modelProject,modelFolder) + ?? throw new CodeFactoryException("Could not refresh the rest json service."); } catch(CodeFactoryException cfException) { diff --git a/src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/RefreshTest.cs b/src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/CSharpFile/RefreshTest.cs similarity index 76% rename from src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/RefreshTest.cs rename to src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/CSharpFile/RefreshTest.cs index 1525f34..81513b7 100644 --- a/src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/RefreshTest.cs +++ b/src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/CSharpFile/RefreshTest.cs @@ -1,4 +1,5 @@ using CodeFactory.Automation.NDF.Logic.Testing.MSTest; +using CodeFactory.Automation.Standard.Logic; using CodeFactory.WinVs; using CodeFactory.WinVs.Commands; using CodeFactory.WinVs.Commands.SolutionExplorer; @@ -11,8 +12,9 @@ using System.Linq; using System.Text; using System.Threading.Tasks; +using System.Windows; -namespace CodeFactory.Architecture.AspNetCore.Service.Rest +namespace CodeFactory.Architecture.AspNetCore.Service.Rest.CSharpFile { /// /// Code factory command for automation of a C# document when selected from a project in solution explorer. @@ -47,6 +49,17 @@ public RefreshTest(ILogger logger, IVsActions vsActions) : base(logger, vsAction /// public static string TestProject = "TestProject"; + /// + /// Prefix to append to the name of the integration test being created. + /// + public static string TestPrefix = "TestPrefix"; + + /// + /// Suffix to append to the name of the integration test being created. + /// + public static string TestSuffix = "TestSuffix"; + + /// /// Loads the external configuration definition for this command. /// @@ -60,14 +73,32 @@ public override ConfigCommand LoadExternalConfigDefinition() Guidance="Automation command that generates integration tests from a provided interface." } .UpdateExecutionProject - ( + ( new ConfigProject { Name = ExecutionProject, Guidance = "Enter the name of the project the command will trigger from." } - ) + ) .AddProject - ( + ( new ConfigProject { Name = TestProject, Guidance = "Enter the name of the project that hosts the MSTest integration testings." } - ); + ) + .AddParameter + ( + new ConfigParameter + { + Name = TestPrefix, + Guidance = "Optional, prefix to append to the name of the integration test when being created." + } + ) + .AddParameter + ( + new ConfigParameter + { + Name = TestSuffix, + Guidance = "Optional, Suffix to append to the name of the integration test when being created.", + Value = "Test" + + } + ); return config; } @@ -129,12 +160,26 @@ public override async Task ExecuteCommandAsync(VsCSharpSource result) var testProject = (await VisualStudioActions.GetProjectFromConfigAsync(config.Project(TestProject))) ?? throw new CodeFactoryException("Could not locate the test project cannot refresh the test."); + + var targetInterface = result.SourceCode?.Interfaces?.FirstOrDefault() ?? throw new CodeFactoryException("Could not locate the interface to have tests created from."); - var test = VisualStudioActions.RefreshMSTestIntegrationTestAsync(targetInterface, testProject); + var testPrefix = config.Project(TestProject).ParameterValue(TestPrefix); + var testSuffix = config.Project(TestProject).ParameterValue(TestSuffix); + + string noRemove = null; + + var testName = NameManagement.Init(noRemove,noRemove,testPrefix,testSuffix).FormatName(targetInterface.Name.GenerateCSharpFormattedClassName()); + var test = VisualStudioActions.RefreshMSTestIntegrationTestAsync(testName,targetInterface, testProject); + + + } + catch (CodeFactoryException codeFactoryError) + { + MessageBox.Show(codeFactoryError.Message, "Automation Error", MessageBoxButton.OK, MessageBoxImage.Error); } catch (Exception unhandledError) { diff --git a/src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/UpdateLogicImplementation.cs b/src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/CSharpFile/UpdateLogicImplementation.cs similarity index 84% rename from src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/UpdateLogicImplementation.cs rename to src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/CSharpFile/UpdateLogicImplementation.cs index 076c187..e52b270 100644 --- a/src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/UpdateLogicImplementation.cs +++ b/src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/CSharpFile/UpdateLogicImplementation.cs @@ -1,4 +1,5 @@ -using CodeFactory.Automation.Standard.Logic; +using CodeFactory.Automation.NDF.Logic.General; +using CodeFactory.Automation.Standard.Logic; using CodeFactory.WinVs; using CodeFactory.WinVs.Commands; using CodeFactory.WinVs.Commands.SolutionExplorer; @@ -11,8 +12,9 @@ using System.Linq; using System.Text; using System.Threading.Tasks; +using System.Windows; -namespace CodeFactory.Architecture.AspNetCore.Service.Rest +namespace CodeFactory.Architecture.AspNetCore.Service.Rest.CSharpFile { /// /// Code factory command for automation of a C# document when selected from a project in solution explorer. @@ -50,12 +52,12 @@ public UpdateLogicImplementation(ILogger logger, IVsActions vsActions) : base(lo /// /// List of prefixes to be removed from the interface definition. /// - public static string RepoPrefix = "RepoPrefix"; + public static string RemoveRepoPrefix = "RemoveRepoPrefix"; /// /// List of suffixes to be removed from the interface definition. /// - public static string RepoSuffix = "RepoSuffix"; + public static string RemoveRepoSuffix = "RepoSuffix"; /// /// The project the logic contract can be found in. @@ -115,7 +117,7 @@ public override ConfigCommand LoadExternalConfigDefinition() ( new ConfigParameter { - Name = RepoPrefix, + Name = RemoveRepoPrefix, Guidance = "List of prefixes to be removed from the beginning of the contract name." } @@ -124,7 +126,7 @@ public override ConfigCommand LoadExternalConfigDefinition() ( new ConfigParameter { - Name = RepoSuffix, + Name = RemoveRepoSuffix, Guidance = "List of suffixes to be removed from the end of the contract name." } @@ -218,8 +220,8 @@ public override async Task EnableCommandAsync(VsCSharpSource result) if(isEnabled ) { - var repoPrefix = command.ExecutionProject.ParameterValue(RepoPrefix); - var repoSuffix = command.ExecutionProject.ParameterValue(RepoSuffix); + var repoPrefix = command.ExecutionProject.ParameterValue(RemoveRepoPrefix); + var repoSuffix = command.ExecutionProject.ParameterValue(RemoveRepoSuffix); isEnabled = IsRepositoryContract(repoInterface,repoPrefix,repoSuffix); } } @@ -248,24 +250,35 @@ public override async Task ExecuteCommandAsync(VsCSharpSource result) var repoContract = result.SourceCode?.Interfaces.FirstOrDefault() ?? throw new CodeFactoryException("Could not load the repository contract cannot update the logic implementation."); - var logicContractProject = await VisualStudioActions.GetProjectFromConfigAsync(command.Project(LogicContractProject)); + var logicContractProject = await VisualStudioActions.GetProjectFromConfigAsync(command.Project(LogicContractProject)) + ?? throw new CodeFactoryException("The logic contract project could not be loaded, cannot refresh the logic class."); var logicContractProjectFolder = await VisualStudioActions.GetProjectFolderFromConfigAsync(command.Project(LogicContractProject),LogicContractProjectFolder); - var repoPrefix = command.ExecutionProject.ParameterValue(RepoPrefix); - var repoSuffix = command.ExecutionProject.ParameterValue(RepoSuffix); + var logicProject = await VisualStudioActions.GetProjectFromConfigAsync(command.Project(LogicProject)) + ?? throw new CodeFactoryException("The logic project could not be loaded, cannot refresh the logic class."); + + var logicProjectFolder = await VisualStudioActions.GetProjectFolderFromConfigAsync(command.Project(LogicProject),LogicProjectFolder); + + var repoRemovePrefix = command.ExecutionProject.ParameterValue(RemoveRepoPrefix); + var repoRemoveSuffix = command.ExecutionProject.ParameterValue(RemoveRepoSuffix); var logicPrefix = command.Project(LogicContractProject)?.ParameterValue(LogicPrefix); var logicSuffix = command.Project(LogicContractProject)?.ParameterValue(LogicSuffix); - var removePrefixes = repoPrefix == null ? null: new List(repoPrefix.Split(',')); - var removeSuffixes = repoSuffix == null ? null: new List(repoSuffix.Split(',')); - var nameManagement = NameManagement.Init(removePrefixes,removeSuffixes,logicPrefix,logicSuffix); + + var logicName = NameManagement.Init(repoRemovePrefix,repoRemoveSuffix,logicPrefix,logicSuffix).FormatName(repoContract.Name.GenerateCSharpFormattedClassName()); - var logicContract = await VisualStudioActions.CloneInterfaceAsync(repoContract,false,logicContractProject, - logicContractProjectFolder,nameManagement,"Logic contract implementation."); + var logicContract = await VisualStudioActions.CloneInterfaceAsync($"I{logicName}", repoContract,false,logicContractProject, + logicContractProjectFolder,"Logic contract implementation."); + + var logicClass = await VisualStudioActions.RefreshLogicAsync(logicName,$"I{logicName}",logicProject,logicContractProject,logicFolder:logicProjectFolder,contractFolder:logicContractProjectFolder); } + catch (CodeFactoryException codeFactoryError) + { + MessageBox.Show(codeFactoryError.Message, "Automation Error", MessageBoxButton.OK, MessageBoxImage.Error); + } catch (Exception unhandledError) { _logger.Error($"The following unhandled error occurred while executing the solution explorer C# document command {commandTitle}. ", diff --git a/src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/CodeFactory.Architecture.AspNetCore.Service.Rest.csproj b/src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/CodeFactory.Architecture.AspNetCore.Service.Rest.csproj index 220fc60..1e4830a 100644 --- a/src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/CodeFactory.Architecture.AspNetCore.Service.Rest.csproj +++ b/src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/CodeFactory.Architecture.AspNetCore.Service.Rest.csproj @@ -48,18 +48,19 @@ - - - - + + + + + + + + + + - - - - - - - + + diff --git a/src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/LoadExternalConfiguration.cs b/src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/IDE/LoadExternalConfiguration.cs similarity index 90% rename from src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/LoadExternalConfiguration.cs rename to src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/IDE/LoadExternalConfiguration.cs index 6a4ba5e..dc58566 100644 --- a/src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/LoadExternalConfiguration.cs +++ b/src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/IDE/LoadExternalConfiguration.cs @@ -1,4 +1,5 @@ -using CodeFactory.WinVs; +using CodeFactory.Architecture.AspNetCore.Service.Rest.CSharpFile; +using CodeFactory.WinVs; using CodeFactory.WinVs.Commands; using CodeFactory.WinVs.Commands.IDE; using CodeFactory.WinVs.Logging; @@ -11,7 +12,7 @@ using System.Text; using System.Threading.Tasks; -namespace CodeFactory.Architecture.AspNetCore.Service.Rest +namespace CodeFactory.Architecture.AspNetCore.Service.Rest.IDE { /// /// Code factory command that is executed when the solution is loaded. This command only gets called one time on load of the solution. @@ -58,6 +59,9 @@ public override async Task ExecuteCommandAsync(VsSolution result) var addMissingLogicMembers = new AddMissingLogicMembers(null, null); addMissingLogicMembers.LoadExternalConfigDefinition().RegisterCommandWithDefaultConfiguration(); + var refreshLogic = new RefreshLogic(null, null); + refreshLogic.LoadExternalConfigDefinition().RegisterCommandWithDefaultConfiguration(); + ConfigManager.LoadConfiguration(result, "Automation", VisualStudioActions); } catch (Exception unhandledError) diff --git a/src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/RegisterTransientServices.cs b/src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/Project/RegisterTransientServices.cs similarity index 92% rename from src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/RegisterTransientServices.cs rename to src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/Project/RegisterTransientServices.cs index 12120d8..e1d8dbf 100644 --- a/src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/RegisterTransientServices.cs +++ b/src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/Project/RegisterTransientServices.cs @@ -11,9 +11,9 @@ using System.Linq; using System.Text; using System.Threading.Tasks; +using System.Windows; - -namespace CodeFactory.Architecture.AspNetCore.Service.Rest +namespace CodeFactory.Architecture.AspNetCore.Service.Rest.Project { /// /// Code factory command for automation of a project when selected from solution explorer. @@ -85,6 +85,10 @@ public override async Task ExecuteCommandAsync(VsProject result) { await VisualStudioActions.RegisterTransientClassesAsync(result); } + catch (CodeFactoryException codeFactoryError) + { + MessageBox.Show(codeFactoryError.Message, "Automation Error", MessageBoxButton.OK, MessageBoxImage.Error); + } catch (Exception unhandledError) { _logger.Error($"The following unhandled error occurred while executing the solution explorer project command {commandTitle}. ", diff --git a/src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/CreateAutomationConfiguration.cs b/src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/Solution/CreateAutomationConfiguration.cs similarity index 90% rename from src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/CreateAutomationConfiguration.cs rename to src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/Solution/CreateAutomationConfiguration.cs index 654534c..bcb078d 100644 --- a/src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/CreateAutomationConfiguration.cs +++ b/src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/Solution/CreateAutomationConfiguration.cs @@ -10,8 +10,9 @@ using System.Linq; using System.Text; using System.Threading.Tasks; +using System.Windows; -namespace CodeFactory.Architecture.AspNetCore.Service.Rest +namespace CodeFactory.Architecture.AspNetCore.Service.Rest.Solution { /// /// Code factory command for automation of the solution when selected from solution explorer. @@ -80,7 +81,11 @@ public override async Task ExecuteCommandAsync(VsSolution result) try { - await ConfigManager.CreateDefaultConfigurationAsync(result, "AspNetCore Rest Service Configuration", "Automation"); + await ConfigManager.CreateDefaultConfigurationAsync(result, "AspNetCore WebApi Json Configuration", "Automation"); + } + catch (CodeFactoryException codeFactoryError) + { + MessageBox.Show(codeFactoryError.Message, "Automation Error", MessageBoxButton.OK, MessageBoxImage.Error); } catch (Exception unhandledError) { diff --git a/src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/ReloadAutomationConfiguration.cs b/src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/Solution/ReloadAutomationConfiguration.cs similarity index 92% rename from src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/ReloadAutomationConfiguration.cs rename to src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/Solution/ReloadAutomationConfiguration.cs index 203b479..c2d9d6d 100644 --- a/src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/ReloadAutomationConfiguration.cs +++ b/src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/Solution/ReloadAutomationConfiguration.cs @@ -10,8 +10,9 @@ using System.Linq; using System.Text; using System.Threading.Tasks; +using System.Windows; -namespace CodeFactory.Architecture.AspNetCore.Service.Rest +namespace CodeFactory.Architecture.AspNetCore.Service.Rest.Solution { /// /// Code factory command for automation of the solution when selected from solution explorer. @@ -82,6 +83,10 @@ public override async Task ExecuteCommandAsync(VsSolution result) { ConfigManager.LoadConfiguration(result, "Automation", VisualStudioActions); } + catch (CodeFactoryException codeFactoryError) + { + MessageBox.Show(codeFactoryError.Message, "Automation Error", MessageBoxButton.OK, MessageBoxImage.Error); + } catch (Exception unhandledError) { _logger.Error($"The following unhandled error occurred while executing the solution explorer solution command {commandTitle}. ", diff --git a/src/Architecture/CodeFactory.Architecture.Blazor.Server/AddMissingControllerMembers.cs b/src/Architecture/CodeFactory.Architecture.Blazor.Server/CSharpFile/AddMissingControllerMembers.cs similarity index 99% rename from src/Architecture/CodeFactory.Architecture.Blazor.Server/AddMissingControllerMembers.cs rename to src/Architecture/CodeFactory.Architecture.Blazor.Server/CSharpFile/AddMissingControllerMembers.cs index 39d9714..c369f0f 100644 --- a/src/Architecture/CodeFactory.Architecture.Blazor.Server/AddMissingControllerMembers.cs +++ b/src/Architecture/CodeFactory.Architecture.Blazor.Server/CSharpFile/AddMissingControllerMembers.cs @@ -16,7 +16,7 @@ using System.Threading.Tasks; using System.Windows; -namespace CodeFactory.Architecture.Blazor.Server +namespace CodeFactory.Architecture.Blazor.Server.CSharpFile { /// /// Code factory command for automation of a C# document when selected from a project in solution explorer. diff --git a/src/Architecture/CodeFactory.Architecture.Blazor.Server/AddMissingLogicMembers.cs b/src/Architecture/CodeFactory.Architecture.Blazor.Server/CSharpFile/AddMissingLogicMembers.cs similarity index 99% rename from src/Architecture/CodeFactory.Architecture.Blazor.Server/AddMissingLogicMembers.cs rename to src/Architecture/CodeFactory.Architecture.Blazor.Server/CSharpFile/AddMissingLogicMembers.cs index 0061655..339002c 100644 --- a/src/Architecture/CodeFactory.Architecture.Blazor.Server/AddMissingLogicMembers.cs +++ b/src/Architecture/CodeFactory.Architecture.Blazor.Server/CSharpFile/AddMissingLogicMembers.cs @@ -14,7 +14,7 @@ using System.Threading.Tasks; using System.Windows; -namespace CodeFactory.Architecture.Blazor.Server +namespace CodeFactory.Architecture.Blazor.Server.CSharpFile { /// /// Code factory command for automation of a C# document when selected from a project in solution explorer. @@ -210,9 +210,8 @@ public override async Task ExecuteCommandAsync(VsCSharpSource result) var boundChecks = new List { - - new BoundsCheckBlockNullNDFException(true,loggerBlock), - new BoundsCheckBlockStringNDFException(true,loggerBlock) + new BoundsCheckBlockStringNDFException(true,loggerBlock), + new BoundsCheckBlockNullNDFException(true,loggerBlock) }; var tryBlock = new TryBlockStandard(loggerBlock,catchBlocks); diff --git a/src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/AddMissingRepositoryMembers.cs b/src/Architecture/CodeFactory.Architecture.Blazor.Server/CSharpFile/AddMissingRepositoryMembers.cs similarity index 99% rename from src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/AddMissingRepositoryMembers.cs rename to src/Architecture/CodeFactory.Architecture.Blazor.Server/CSharpFile/AddMissingRepositoryMembers.cs index 20e449c..90c59c1 100644 --- a/src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/AddMissingRepositoryMembers.cs +++ b/src/Architecture/CodeFactory.Architecture.Blazor.Server/CSharpFile/AddMissingRepositoryMembers.cs @@ -16,7 +16,7 @@ using System.Threading.Tasks; using System.Windows; -namespace CodeFactory.Architecture.AspNetCore.Service.Rest +namespace CodeFactory.Architecture.Blazor.Server.CSharpFile { /// /// Code factory command for automation of a C# document when selected from a project in solution explorer. diff --git a/src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/RefreshEFRepository.cs b/src/Architecture/CodeFactory.Architecture.Blazor.Server/CSharpFile/RefreshEFRepository.cs similarity index 68% rename from src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/RefreshEFRepository.cs rename to src/Architecture/CodeFactory.Architecture.Blazor.Server/CSharpFile/RefreshEFRepository.cs index cfbf216..86982ec 100644 --- a/src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/RefreshEFRepository.cs +++ b/src/Architecture/CodeFactory.Architecture.Blazor.Server/CSharpFile/RefreshEFRepository.cs @@ -15,8 +15,10 @@ using System.Text; using System.Threading.Tasks; using System.Windows; +using CodeFactory.Automation.NDF.Logic.Testing.MSTest; +using CodeFactory.Automation.NDF.Logic.General; -namespace CodeFactory.Architecture.AspNetCore.Service.Rest +namespace CodeFactory.Architecture.Blazor.Server.CSharpFile { /// /// Code factory command for automation of a C# document when selected from a project in solution explorer. @@ -92,27 +94,60 @@ public RefreshEFRepository(ILogger logger, IVsActions vsActions) : base(logger, /// public static string IntegrationTestFolder = "IntegrationTestFolder"; + /// + /// The name of the entity framework context class. + /// public static string EFContextClassName = "EFContextClassName"; /// - /// Comma seperated list of the prefixes to remove from the EF class name when generating the target application entity model. + /// Optional, list of prefixes seperated by comma to remove from the name of the entity framework entity. + /// + public static string EFEntityRemovePrefixes = "EFEntityRemovePrefixes"; + + /// + /// Optional, list of prefixes seperated by comma to remove from the name of the entity framework entity. + /// + public static string EFEntityRemoveSuffixes = "EFEntityRemoveSuffixes"; + + /// + /// Optional, prefix to assign to a repository when creating. + /// + public static string RepositoryPrefix = "RepositoryPrefix"; + + /// + /// Optional, suffix to assign to a repository when creating. + /// + public static string RepositorySuffix = "RepositorySuffix"; + + /// + /// Optional, prefix to assign to a application model when creating. + /// + public static string AppModelPrefix ="AppModelPrefix"; + + /// + /// Optional, suffix to assign to a application model when creating. /// - public static string RemoveNamePrefixesForEntityModel = "RemoveNamePrefixesForEntityModel"; + public static string AppModelSuffix ="AppModelSuffix"; /// - /// The repository and repository contract suffix to assign. + /// Optional, prefix to assign to a integration test when creating. /// - public static string RepositoryAndContractSuffix = "RepositoryAndContractSuffix"; + public static string TestPrefix ="TestPrefix"; /// - /// The prefix to assign to the name of a models validation class. + /// Optional, suffix to assign to a integration test when creating. /// - public static string ModelValidatorPrefix = "ModelValidatorPrefix"; + public static string TestSuffix ="TestSuffix"; /// - /// The suffix to assign to the name of a models validation class. + /// The prefix to assign to the name of a application models validation class. /// - public static string ModelValidatorSuffix = "ModelValidatorSuffix"; + public static string AppModelValidatorPrefix = "AppModelValidatorPrefix"; + + /// + /// The suffix to assign to the name of a application models validation class. + /// + public static string AppModelValidatorSuffix = "AppModelValidatorSuffix"; /// /// Loads the external configuration definition for this command. @@ -150,35 +185,18 @@ public override ConfigCommand LoadExternalConfigDefinition() ( new ConfigParameter { - Name = RemoveNamePrefixesForEntityModel, - Guidance = "Comma seperated value list of the prefixes in case sensititve format to be removed from the application entity name." - } - ) - .AddParameter - ( - new ConfigParameter - { - Name= RepositoryAndContractSuffix, - Guidance = "Suffix to be assigned to the name of the repository and the contract for the repository." + Name = EFEntityRemovePrefixes, + Guidance = "Comma seperated value list of the prefixes in case sensitive format to be removed from the entity framework entity name when creating new objects." } ) .AddParameter ( new ConfigParameter - { - Name= ModelValidatorPrefix, - Guidance = "The prefix to assign to the name of a models validation class." - } - ) - .AddParameter - ( - new ConfigParameter - { - Name= ModelValidatorSuffix, - Guidance = "The suffix to assign to the name of a models validation class." + { + Name = EFEntityRemoveSuffixes, + Guidance = "Comma seperated value list of the suffixes in case sensitive format to be removed from the entity framework entity name when creating new objects." } ) - ) .AddProject ( @@ -198,6 +216,41 @@ public override ConfigCommand LoadExternalConfigDefinition() "Optional, set the relative path from the root of the project. If it is more then one directory deep then use '/' instead of back slashes." } ) + .AddParameter + ( + new ConfigParameter + { + Name = AppModelPrefix, + Guidance = "Optional, prefix to assign to the application model entity when it is created." + } + ) + .AddParameter + ( + new ConfigParameter + { + Name = AppModelSuffix, + Guidance = "Optional, suffix to assign to the application model entity when it is created.", + Value = "AppModel" + } + ) + .AddParameter + ( + new ConfigParameter + { + Name = AppModelValidatorPrefix, + Guidance = "Optional, prefix to assign to the application model entity validator when it is created." + + } + ) + .AddParameter + ( + new ConfigParameter + { + Name = AppModelValidatorSuffix, + Guidance = "Optional, suffix to assign to the application model entity validator when it is created.", + Value = "Validator" + } + ) ) .AddProject ( @@ -217,6 +270,23 @@ public override ConfigCommand LoadExternalConfigDefinition() "Optional, set the relative path from the root of the project. If it is more then one directory deep then use '/' instead of back slashes." } ) + .AddParameter + ( + new ConfigParameter + { + Name = RepositoryPrefix, + Guidance = "Optional, prefix to assign to the repository when it is created." + } + ) + .AddParameter + ( + new ConfigParameter + { + Name = RepositorySuffix, + Guidance = "Optional, suffix to assign to the repository when it is created.", + Value = "Repository" + } + ) ) .AddProject ( @@ -255,6 +325,23 @@ public override ConfigCommand LoadExternalConfigDefinition() "Optional, set the relative path from the root of the project. If it is more then one directory deep then use '/' instead of back slashes." } ) + .AddParameter + ( + new ConfigParameter + { + Name = TestPrefix, + Guidance = "Optional, prefix to assign to the integration test when it is created." + } + ) + .AddParameter + ( + new ConfigParameter + { + Name = TestSuffix, + Guidance = "Optional, suffix to assign to the integration test when it is created.", + Value = "Test" + } + ) ); return command; @@ -307,18 +394,31 @@ public override async Task ExecuteCommandAsync(VsCSharpSource result) VsProjectFolder efModelFolder = await VisualStudioActions.GetProjectFolderFromConfigAsync(command.ExecutionProject, ExecutionModelFolder); + var contextClassName = command.ExecutionProject.ParameterValue(EFContextClassName); + var efEntityRemovePrefixs = command.ExecutionProject.ParameterValue(EFEntityRemovePrefixes); + var efEntityRemoveSuffixes = command.ExecutionProject.ParameterValue(EFEntityRemoveSuffixes); + VsProject appModelProject = await VisualStudioActions.GetProjectFromConfigAsync(command.Project(EntityProject)) ?? throw new CodeFactoryException("Could not load the entity model project, cannot refresh the EF repository."); VsProjectFolder appModelFolder = await VisualStudioActions.GetProjectFolderFromConfigAsync(command.Project(EntityProject), EntityFolder); + var appModelPrefix = command.Project(EntityProject).ParameterValue(AppModelPrefix); + var appModelSuffix = command.Project(EntityProject).ParameterValue(AppModelSuffix); + var appModelValidatorPrefix = command.Project(EntityProject).ParameterValue(AppModelValidatorPrefix); + var appModelValidatorSuffix = command.Project(EntityProject).ParameterValue(AppModelValidatorSuffix); + VsProject repoProject = await VisualStudioActions.GetProjectFromConfigAsync(command.Project(RepoProject)) ?? throw new CodeFactoryException("Could not load the repository project, cannot refresh the EF repository."); VsProjectFolder repoFolder = await VisualStudioActions.GetProjectFolderFromConfigAsync(command.Project(RepoProject), RepoFolder); + var repoPrefix = command.Project(RepoProject).ParameterValue(RepositoryPrefix); + + var repoSuffix = command.Project(RepoProject).ParameterValue(RepositorySuffix); + VsProject contractProject = await VisualStudioActions.GetProjectFromConfigAsync(command.Project(RepoContractProject)) ?? throw new CodeFactoryException( @@ -334,31 +434,9 @@ await VisualStudioActions.GetProjectFromConfigAsync(command.Project(RepoContract await VisualStudioActions.GetProjectFolderFromConfigAsync(command.Project(IntegrationTestProject), IntegrationTestFolder); - var contextClassName = command.ExecutionProject.ParameterValue(EFContextClassName); - - var appModelPrefixReplacements = command.ExecutionProject.ParameterValue(RemoveNamePrefixesForEntityModel); - - var modelValidatorPrefix = command.ExecutionProject.ParameterValue(ModelValidatorPrefix); - var modelValidatorSuffix = command.ExecutionProject.ParameterValue(ModelValidatorSuffix); + var testPrefix = testProject != null ? command.Project(IntegrationTestProject).ParameterValue(TestPrefix) : null; - NameManagement nameManagement = null; - - if(!string.IsNullOrEmpty(appModelPrefixReplacements)) - { - var prefixes = appModelPrefixReplacements.Split(','); - - var renamePrefixes = new List(); - foreach (var prefix in prefixes) - { - var formattedPrefix = prefix.Trim(); - - if(!string.IsNullOrEmpty(formattedPrefix)) renamePrefixes.Add(formattedPrefix); - } - - if(renamePrefixes.Any()) nameManagement = NameManagement.Init(renamePrefixes,null,null,null); - } - - string repositorySuffix = command.ExecutionProject.ParameterValue(RepositoryAndContractSuffix); + var testSuffix = testProject != null ? command.Project(IntegrationTestProject).ParameterValue(TestSuffix) : null; if (string.IsNullOrWhiteSpace(contextClassName)) throw new CodeFactoryException( @@ -377,25 +455,44 @@ await VisualStudioActions.GetProjectFolderFromConfigAsync(command.Project(Integr var efModel = result.SourceCode?.Classes?.FirstOrDefault() ?? throw new CodeFactoryException("The EF entity class could not be loaded, cannot refresh the EF repository."); - var appModel = (await VisualStudioActions.RefreshPOCOAsync(efModel, appModelProject, + var nameManagement = NameManagement.Init(efEntityRemovePrefixs,efEntityRemoveSuffixes,appModelPrefix,appModelSuffix); + + var appModel = (await VisualStudioActions.RefreshModelAsync(efModel, appModelProject, EntityModelNamespaces(),nameManagement, appModelFolder, $"Application data model that supports '{efModel.Name}'", true,useSourceProperty: RepositoryBuilder.UseSourceProperty)) ?? throw new CodeFactoryException($"Could not load the entity that supports the ef model '{efModel.Name}', cannot refresh the EF repository."); - NameManagement modelValidatorNameManagement = null; - if(!string.IsNullOrEmpty(modelValidatorSuffix) | !string.IsNullOrEmpty(modelValidatorPrefix)) modelValidatorNameManagement = NameManagement.Init(null,null,modelValidatorPrefix, modelValidatorSuffix); - + string noReplacePrefix = null; + string noReplaceSuffix = null; - var validation = (await VisualStudioActions.RefreshValidationAsync(appModel,appModelProject,appModelFolder,modelValidatorNameManagement)) + var modelValidatorNameManagement = NameManagement.Init(noReplacePrefix,noReplaceSuffix,appModelValidatorPrefix,appModelValidatorSuffix); + + var validation = (await VisualStudioActions.RefreshValidationClassAsync(appModel,appModelProject,appModelFolder,modelValidatorNameManagement)) ?? throw new CodeFactoryException($"Could not refresh the validation for the app model '{appModel.Name}', cannot refresh the EF repository."); await VisualStudioActions.RefreshFluentValidationAsync(efModel,appModel,validation); - await VisualStudioActions.RefreshEntityFrameworkEntityTransform(appModel, efModel, efModelProject, efModelFolder); - var repoClass = await VisualStudioActions.RefreshEFRepositoryAsync(efModel, repoProject, contractProject, appModel, - contextClass, supportsNDF, supportsLogging, repoFolder, contractFolder,nameSuffix:repositorySuffix); + var repositoryName = NameManagement.Init(efEntityRemovePrefixs,efEntityRemoveSuffixes,repoPrefix,repoSuffix).FormatName(efModel.Name); + + var repoClass = await VisualStudioActions.RefreshEFRepositoryAsync(repositoryName,efModel, repoProject, contractProject, appModel, + contextClass, supportsNDF, supportsLogging, repoFolder, contractFolder); + + + if(repoClass != null & testProject != null) + { + var contractName = $"I{repositoryName}"; + + CsInterface contractInterface = contractFolder != null ? (await contractFolder.FindCSharpSourceByInterfaceNameAsync(contractName))?.SourceCode?.Interfaces?.FirstOrDefault() + : (await contractProject.FindCSharpSourceByInterfaceNameAsync(contractName))?.SourceCode?.Interfaces?.FirstOrDefault(); + + if(contractInterface != null) + { + var testName = NameManagement.Init(noReplacePrefix,noReplaceSuffix,testPrefix,testSuffix).FormatName(repositoryName); + await VisualStudioActions.RefreshMSTestIntegrationTestAsync(testName, contractInterface,testProject); + } + } } catch (CodeFactoryException codeFactoryError) diff --git a/src/Architecture/CodeFactory.Architecture.Blazor.Server/RefreshFluentValidation.cs b/src/Architecture/CodeFactory.Architecture.Blazor.Server/CSharpFile/RefreshFluentValidation.cs similarity index 94% rename from src/Architecture/CodeFactory.Architecture.Blazor.Server/RefreshFluentValidation.cs rename to src/Architecture/CodeFactory.Architecture.Blazor.Server/CSharpFile/RefreshFluentValidation.cs index cc28a69..d6efd46 100644 --- a/src/Architecture/CodeFactory.Architecture.Blazor.Server/RefreshFluentValidation.cs +++ b/src/Architecture/CodeFactory.Architecture.Blazor.Server/CSharpFile/RefreshFluentValidation.cs @@ -12,8 +12,9 @@ using System.Linq; using System.Text; using System.Threading.Tasks; +using System.Windows; -namespace CodeFactory.Architecture.Blazor.Server +namespace CodeFactory.Architecture.Blazor.Server.CSharpFile { /// /// Code factory command for automation of a C# document when selected from a project in solution explorer. @@ -168,12 +169,19 @@ await VisualStudioActions.GetProjectFromConfigAsync(command.ExecutionProject) var validatorSuffix = command.ExecutionProject.ParameterValue(ModelValidatorSuffix); + string removePrefixes = null; + string removeSuffixes = null; + NameManagement nameManagement = null; - if(!string.IsNullOrEmpty(validatorPrefix) | !string.IsNullOrEmpty(validatorSuffix)) nameManagement = NameManagement.Init(null,null, validatorPrefix, validatorSuffix); + if(!string.IsNullOrEmpty(validatorPrefix) | !string.IsNullOrEmpty(validatorSuffix)) nameManagement = NameManagement.Init(removePrefixes,removeSuffixes, validatorPrefix, validatorSuffix); var validationClass = VisualStudioActions.RefreshValidationAsync(sourceClass, sourceProject,sourceFolder,nameManagement); } + catch (CodeFactoryException codeFactoryError) + { + MessageBox.Show(codeFactoryError.Message, "Automation Error", MessageBoxButton.OK, MessageBoxImage.Error); + } catch (Exception unhandledError) { _logger.Error($"The following unhandled error occurred while executing the solution explorer C# document command {commandTitle}. ", diff --git a/src/Architecture/CodeFactory.Architecture.Blazor.Server/CSharpFile/RefreshLogic.cs b/src/Architecture/CodeFactory.Architecture.Blazor.Server/CSharpFile/RefreshLogic.cs new file mode 100644 index 0000000..38820d1 --- /dev/null +++ b/src/Architecture/CodeFactory.Architecture.Blazor.Server/CSharpFile/RefreshLogic.cs @@ -0,0 +1,305 @@ +using CodeFactory.Automation.NDF.Logic.General; +using CodeFactory.Automation.Standard.Logic; +using CodeFactory.WinVs; +using CodeFactory.WinVs.Commands; +using CodeFactory.WinVs.Commands.SolutionExplorer; +using CodeFactory.WinVs.Logging; +using CodeFactory.WinVs.Models.CSharp; +using CodeFactory.WinVs.Models.CSharp.Builder; +using CodeFactory.WinVs.Models.ProjectSystem; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; + +namespace CodeFactory.Architecture.Blazor.Server.CSharpFile +{ + /// + /// Code factory command for automation of a C# document when selected from a project in solution explorer. + /// + public class RefreshLogic : CSharpSourceCommandBase + { + private static readonly string commandTitle = "Refresh Logic"; + private static readonly string commandDescription = "Refreshes the logic implementation for the target logic interface."; + +#pragma warning disable CS1998 + + /// + public RefreshLogic(ILogger logger, IVsActions vsActions) : base(logger, vsActions, commandTitle, commandDescription) + { + //Intentionally blank + } + + #region External Configuration + + /// + /// The fully qualified name of the command to be used with configuration. + /// + public static string Type = typeof(RefreshLogic).FullName; + + /// + /// Exection project for the command. + /// + public static string ExecutionProject = "ExecutionProject"; + + /// + /// Execution folder for the command. + /// + public static string ExecutionFolder = "ExecutionFolder"; + + /// + /// The logic project that holds the logic class to be refreshed. + /// + public static string LogicProject = "LogicProject"; + + /// + /// Optional, folder where the logic class it be refreshed is located. + /// + public static string LogicFolder = "LogicFolder"; + + /// + /// Optional, comma seperated value list of prefixes to be removed from the logic contracts name. + /// + public static string RemovePrefixes = "RemovePrefixes"; + + /// + /// Optional, comma seperated value list of the suffixes to be removed from the logic contract name. + /// + public static string RemoveSuffixes = "RemoveSuffixes"; + + /// + /// Optional, the prefix to append to the logic class name. + /// + public static string LogicPrefix = "LogicPrefix"; + + /// + /// Optional, the suffix to append to the logic class name. + /// + public static string LogicSuffix = "LogicSuffix"; + + /// + /// Loads the external configuration definition for this command. + /// + /// Will return the command configuration or null if this command does not support external configurations. + public override ConfigCommand LoadExternalConfigDefinition() + { + return new ConfigCommand { Name = commandTitle, Category = "Logic", CommandType = Type, } + .UpdateExecutionProject + ( + new ConfigProject + { + Name = ExecutionProject, + Guidance = "Project that contains the interface that triggers the automation." + } + .AddFolder + ( + new ConfigFolder + { + Name = ExecutionFolder, + Required = false, + Guidance = "Optional, project folder that contains the interface that triggers the automation." + } + ) + .AddParameter + ( + new ConfigParameter + { + Name = RemovePrefixes, + Guidance = "Optional, comma seperated value list of prefix values to remove from the interface name." + } + ) + .AddParameter + ( + new ConfigParameter + { + Name = RemoveSuffixes, + Guidance = "Optional, comma seperated value list of suffix values to remove from the interface name." + } + ) + + ) + .AddProject + ( + new ConfigProject + { + Name = LogicProject, + Guidance = "Name of the project that hosts the logic class to be refreshed." + } + .AddFolder + ( + new ConfigFolder + { + Name = LogicFolder, + Required = false, + Guidance = "Optional, The project folder the logic class is hosted in." + } + ) + .AddParameter + ( + new ConfigParameter + { + Name = LogicPrefix, + Guidance = "Optional, the prefix to append to the logic class name." + + } + ) + .AddParameter + ( + new ConfigParameter + { + Name = LogicSuffix, + Guidance = "Optional, the suffix to append to the logic class name." + + } + ) + ); + + + } + #endregion + + #region Overrides of VsCommandBase + + /// + /// Validation logic that will determine if this command should be enabled for execution. + /// + /// The target model data that will be used to determine if this command should be enabled. + /// Boolean flag that will tell code factory to enable this command or disable it. + public override async Task EnableCommandAsync(VsCSharpSource result) + { + //Result that determines if the command is enabled and visible in the context menu for execution. + bool isEnabled = false; + + try + { + + var logicContract = result.SourceCode?.Interfaces.FirstOrDefault(); + + isEnabled = logicContract != null; + + ConfigCommand command = null; + + if( isEnabled ) + { + command = await ConfigManager.LoadCommandByFolderAsync(Type, ExecutionFolder, result) + ?? await ConfigManager.LoadCommandByProjectAsync(Type, result); + + isEnabled = command != null; + } + + if(isEnabled) isEnabled = await LogicNeedsUpdatesAsync(command,logicContract); + + } + catch (Exception unhandledError) + { + _logger.Error($"The following unhandled error occurred while checking if the solution explorer C# document command {commandTitle} is enabled. ", + unhandledError); + isEnabled = false; + } + + return isEnabled; + } + + /// + /// Code factory framework calls this method when the command has been executed. + /// + /// The code factory model that has generated and provided to the command to process. + public override async Task ExecuteCommandAsync(VsCSharpSource result) + { + try + { + var logicContract = result.SourceCode?.Interfaces.FirstOrDefault() + ?? throw new CodeFactoryException("Could not load the source interface cannot refresh the logic."); + + var commandConfig = await ConfigManager.LoadCommandByFolderAsync(Type, ExecutionFolder, result) + ?? await ConfigManager.LoadCommandByProjectAsync(Type, result) + ?? throw new CodeFactoryException("Could not load the configuratin, cannot refresh the logic"); + + var logicName = GenerateLogicClassName(commandConfig,logicContract) + ?? throw new CodeFactoryException("Could not determine the logic class name, cannot refresh the logic"); + + var contractProject = await VisualStudioActions.GetProjectFromConfigAsync(commandConfig.ExecutionProject) + ?? throw new CodeFactoryException("Cannot load the contract interface project, cannot refresh the logic"); + + var contractProjectFolder = await VisualStudioActions.GetProjectFolderFromConfigAsync(commandConfig.ExecutionProject,ExecutionFolder); + + var logicProject = await VisualStudioActions.GetProjectFromConfigAsync(commandConfig.Project(LogicProject)) + ?? throw new CodeFactoryException("Could not load the logic project, cannot refresh the logic."); + + var logicProjectFolder = await VisualStudioActions.GetProjectFolderFromConfigAsync(commandConfig.Project(LogicProject),LogicFolder); + + await VisualStudioActions.RefreshLogicAsync(logicName,logicContract.Name,logicProject,contractProject,logicFolder:logicProjectFolder,contractFolder: contractProjectFolder); + + } + catch (CodeFactoryException codeFactoryError) + { + MessageBox.Show(codeFactoryError.Message, "Automation Error", MessageBoxButton.OK, MessageBoxImage.Error); + } + catch (Exception unhandledError) + { + _logger.Error($"The following unhandled error occurred while executing the solution explorer C# document command {commandTitle}. ", + unhandledError); + + } + + } + + #endregion + + /// + /// Helper method that determines if the command should be activated. Checks to make sure all the conditions are met to refresh the logic. + /// + /// The commands configuration. + /// The source interface that is being used to refresh the logic. + /// True if the command should be enabled, false if not. + private async Task LogicNeedsUpdatesAsync(ConfigCommand command,CsInterface interfaceContract) + { + + var logicProject = await VisualStudioActions.GetProjectFromConfigAsync(command.Project(LogicProject)); + + if(logicProject == null) return false; + + var logicFolder = await VisualStudioActions.GetProjectFolderFromConfigAsync(command.Project(LogicProject),LogicFolder); + + var logicClassName = GenerateLogicClassName(command,interfaceContract); + + if(logicClassName == null) return false; + + var logicSource = logicFolder != null + ? await logicFolder.FindCSharpSourceByClassNameAsync(logicClassName,false) + : await logicProject.FindCSharpSourceByClassNameAsync(logicClassName,false); + + if(logicSource == null) return true; + + var logicClass = logicSource?.SourceCode?.Classes?.FirstOrDefault(); + + if(logicClass == null) return false; + + return logicClass.GetMissingInterfaceMembers().Any(); + + } + + /// + /// Generates the name of the logic class to be refreshed. + /// + /// The command configuration to use to generate the class name. + /// The interface that implements the logic class to refresh. + /// Formatted name or null if the name cannot be determined. + private string GenerateLogicClassName(ConfigCommand command,CsInterface interfaceContract) + { + if(command == null) return null; + + if(interfaceContract == null) return null; + + var removePrefixes = command.ExecutionProject.ParameterValue(RemovePrefixes); + var removeSuffixes = command.ExecutionProject.ParameterValue(RemoveSuffixes); + var logicPrefix = command.Project(LogicProject).ParameterValue(LogicPrefix); + var logicSuffix = command.Project(LogicProject).ParameterValue(LogicSuffix); + + return NameManagement.Init(removePrefixes,removeSuffixes, logicPrefix, logicSuffix).FormatName(interfaceContract.Name.GenerateCSharpFormattedClassName()); + + } + } +} diff --git a/src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/RefreshRestService.cs b/src/Architecture/CodeFactory.Architecture.Blazor.Server/CSharpFile/RefreshRestService.cs similarity index 50% rename from src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/RefreshRestService.cs rename to src/Architecture/CodeFactory.Architecture.Blazor.Server/CSharpFile/RefreshRestService.cs index 52c5d23..c273e8b 100644 --- a/src/Architecture/CodeFactory.Architecture.AspNetCore.Service.Rest/RefreshRestService.cs +++ b/src/Architecture/CodeFactory.Architecture.Blazor.Server/CSharpFile/RefreshRestService.cs @@ -1,4 +1,5 @@ using CodeFactory.Automation.NDF.Logic.AspNetCore.Service.Rest.Json; +using CodeFactory.Automation.Standard.Logic; using CodeFactory.WinVs; using CodeFactory.WinVs.Commands; using CodeFactory.WinVs.Commands.SolutionExplorer; @@ -11,8 +12,9 @@ using System.Linq; using System.Text; using System.Threading.Tasks; +using System.Windows; -namespace CodeFactory.Architecture.AspNetCore.Service.Rest +namespace CodeFactory.Architecture.Blazor.Server.CSharpFile { /// /// Code factory command for automation of a C# document when selected from a project in solution explorer. @@ -67,25 +69,51 @@ public RefreshRestService(ILogger logger, IVsActions vsActions) : base(logger, v /// public static string ModelFolder = "ModelFolder"; - ///// - ///// The target project that the abstraction logic will be hosted. - ///// - //public static string AbstractionProject = "AbstractionProject"; + /// + /// The target project that the abstraction logic will be hosted. + /// + public static string AbstractionProject = "AbstractionProject"; + + /// + /// The target folder where abstraction logic will be hosted, this is optional. + /// + public static string AbstractionFolder = "AbstractionFolder"; - ///// - ///// The target folder where abstraction logic will be hosted, this is optional. - ///// - //public static string AbstractionFolder = "AbstractionFolder"; + /// + /// The target project where abstraction contracts will be created. + /// + public static string ContractProject = "ContractProject"; + + /// + /// The target folder where abstraction contracts will be created, this is optional + /// + public static string ContractFolder = "ContractFolder"; - ///// - ///// The target project where abstraction contracts will be created. - ///// - //public static string ContractProject = "ContractProject"; + /// + /// Comma seperated list of prefixes to remove from the logc contract when creating the service name. + /// + public static string ServiceNameRemovePrefixes = "ServiceNameRemovePrefixes"; + + /// + /// Comma sperated list of suffixes to remove from the logic contract when creating the service name. + /// + public static string ServiceNameRemoveSuffixes = "ServiceNameRemoveSuffixes"; + + /// + /// Prefix to start the service name with. + /// + public static string ServiceNameAppendPrefix = "ServiceNameAppendPrefix"; + + /// + /// Prefix to start the service client name with. + /// + public static string ServiceClientNameAppendPrefix = "ServiceClientNameAppendPrefix"; - ///// - ///// The target folder where abstraction contracts will be created, this is optional - ///// - //public static string ContractFolder = "ContractFolder"; + /// + /// Suffix to append to the service client name. + /// + public static string ServiceClientNameAppendSuffix = "ServiceClientNameAppendSuffix"; + /// /// Loads the external configuration definition for this command. @@ -103,7 +131,7 @@ public override ConfigCommand LoadExternalConfigDefinition() Guidance = "Enter the fully project name for the logic contracts project." } .AddFolder - ( + ( new ConfigFolder { Name = ExecutionFolder, @@ -112,6 +140,49 @@ public override ConfigCommand LoadExternalConfigDefinition() "Optional, set the relative path from the root of the project. If it is more then one directory deep then use forward slash instead of back slashes." } ) + .AddParameter + ( + new ConfigParameter + { + Name = ServiceNameRemovePrefixes, + Guidance = "Optional, provide a comma seperated value of each prefix to check for to be removed from the logic contract name when creating a service name." + } + ) + .AddParameter + ( + new ConfigParameter + { + Name = ServiceNameRemoveSuffixes, + Guidance = "Optional, provide a comma seperated value of each suffix to check for to be removed from the logic contract name when creating a service name.", + Value = "Logic" + } + ) + .AddParameter + ( + new ConfigParameter + { + Name = ServiceNameAppendPrefix, + Guidance = "Optional, provide the prefix to append to the service name." + } + ) + .AddParameter + ( + new ConfigParameter + { + Name = ServiceClientNameAppendPrefix, + Guidance = "Optional, provide the prefix to append to the service client name." + } + ) + .AddParameter + ( + new ConfigParameter + { + Name = ServiceClientNameAppendSuffix, + Guidance = "Optional, provide the suffix to append to the service client name.", + Value = "Client" + } + ) + ) .AddProject ( @@ -151,6 +222,44 @@ public override ConfigCommand LoadExternalConfigDefinition() "Optional, set the relative path from the root of the project. If it is more then one directory deep then use forward slash instead of back slashes." } ) + ) + .AddProject + ( + new ConfigProject + { + Name = AbstractionProject, + Guidance = + "Enter the full project name for the project that hosts the abstraction implementation of the service." + } + .AddFolder + ( + new ConfigFolder + { + Name = AbstractionFolder, + Required = false, + Guidance = + "Optional, set the relative path from the root of the project. If it is more then one directory deep then use forward slah instead of back slashes." + } + ) + ) + .AddProject + ( + new ConfigProject + { + Name = ContractProject, + Guidance = + "Enter the full project name for the project that hosts interface contracts for the abstraction implementation." + } + .AddFolder + ( + new ConfigFolder + { + Name = ContractFolder, + Required = false, + Guidance = + "Optional, set the relative path from the root of the project. If it is more then one directory deep then use '/' instead of back slashes." + } + ) ); return command; @@ -217,11 +326,51 @@ await VisualStudioActions.GetProjectFromConfigAsync(command.Project(ModelProject var modelFolder = await VisualStudioActions.GetProjectFolderFromConfigAsync(command.Project(ModelProject), ModelFolder); + var abstractionProject = + await VisualStudioActions.GetProjectFromConfigAsync(command.Project(AbstractionProject)) + ?? throw new CodeFactoryException("Cannot load the abstraction project, cannot refresh the service."); + + var abstractionFolder = + await VisualStudioActions.GetProjectFolderFromConfigAsync(command.Project(AbstractionProject), AbstractionFolder); + + var contractProject = + await VisualStudioActions.GetProjectFromConfigAsync(command.Project(ContractProject)) + ?? throw new CodeFactoryException("Cannot load the abstraction contract project, cannot refresh the service."); + + var contractFolder = + await VisualStudioActions.GetProjectFolderFromConfigAsync(command.Project(ContractProject), ContractFolder); + + //Execution command parameters. + var serviceNameRemovePrefixes = command.ExecutionProject.ParameterValue(ServiceNameRemovePrefixes); + var serviceNameRemoveSuffixes = command.ExecutionProject.ParameterValue(ServiceNameRemoveSuffixes); + var serviceNameAppendPrefix = command.ExecutionProject.ParameterValue(ServiceNameAppendPrefix); + var serviceClientNameAppendPrefix = command.ExecutionProject.ParameterValue(ServiceClientNameAppendPrefix); + var serviceClientNameAppendSuffix = command.ExecutionProject.ParameterValue(ServiceClientNameAppendSuffix); - var serviceClass = await VisualStudioActions.RefreshJsonRestService(logicContract, serviceProject, serviceFolder, - modelProject,modelFolder); + var serviceNameManagement = NameManagement.Init(serviceNameRemovePrefixes,serviceNameRemoveSuffixes,serviceNameAppendPrefix,null); + var serviceName = serviceNameManagement.FormatName(logicContract.Name.GenerateCSharpFormattedClassName()); + + var serviceClass = await VisualStudioActions.RefreshJsonRestService(serviceName,logicContract, serviceProject, serviceFolder, + modelProject,modelFolder) + ?? throw new CodeFactoryException("Could not refresh the rest json service, cannot refresh the abstraction implementation."); + + + var serviceClientNameManagement = NameManagement.Init(serviceNameRemovePrefixes,serviceNameRemoveSuffixes,serviceClientNameAppendPrefix,serviceClientNameAppendSuffix); + + var serviceClientName = serviceClientNameManagement.FormatName(logicContract.Name.GenerateCSharpFormattedClassName()); + + var abstractionContract = await VisualStudioActions.RefreshCSharpAbstractionContractAsync($"I{serviceClientName}", logicContract, contractProject, contractFolder) + ?? throw new CodeFactoryException("Could not refresh the abstraction contract. The abstraction cannot be updated."); + + var abstractionClass = await VisualStudioActions.RefreshAbstractionClass(serviceClientName, serviceClass,abstractionContract,serviceProject,abstractionProject,modelProject,abstractionFolder,modelFolder); + + + } + catch(CodeFactoryException cfException) + { + MessageBox.Show(cfException.Message, "Automation Error", MessageBoxButton.OK, MessageBoxImage.Error); } catch (Exception unhandledError) { diff --git a/src/Architecture/CodeFactory.Architecture.Blazor.Server/RefreshTest.cs b/src/Architecture/CodeFactory.Architecture.Blazor.Server/CSharpFile/RefreshTest.cs similarity index 76% rename from src/Architecture/CodeFactory.Architecture.Blazor.Server/RefreshTest.cs rename to src/Architecture/CodeFactory.Architecture.Blazor.Server/CSharpFile/RefreshTest.cs index 723b29b..93e9500 100644 --- a/src/Architecture/CodeFactory.Architecture.Blazor.Server/RefreshTest.cs +++ b/src/Architecture/CodeFactory.Architecture.Blazor.Server/CSharpFile/RefreshTest.cs @@ -1,4 +1,5 @@ using CodeFactory.Automation.NDF.Logic.Testing.MSTest; +using CodeFactory.Automation.Standard.Logic; using CodeFactory.WinVs; using CodeFactory.WinVs.Commands; using CodeFactory.WinVs.Commands.SolutionExplorer; @@ -11,8 +12,9 @@ using System.Linq; using System.Text; using System.Threading.Tasks; +using System.Windows; -namespace CodeFactory.Architecture.Blazor.Server +namespace CodeFactory.Architecture.Blazor.Server.CSharpFile { /// /// Code factory command for automation of a C# document when selected from a project in solution explorer. @@ -47,6 +49,17 @@ public RefreshTest(ILogger logger, IVsActions vsActions) : base(logger, vsAction /// public static string TestProject = "TestProject"; + /// + /// Prefix to append to the name of the integration test being created. + /// + public static string TestPrefix = "TestPrefix"; + + /// + /// Suffix to append to the name of the integration test being created. + /// + public static string TestSuffix = "TestSuffix"; + + /// /// Loads the external configuration definition for this command. /// @@ -60,14 +73,32 @@ public override ConfigCommand LoadExternalConfigDefinition() Guidance="Automation command that generates integration tests from a provided interface." } .UpdateExecutionProject - ( + ( new ConfigProject { Name = ExecutionProject, Guidance = "Enter the name of the project the command will trigger from." } - ) + ) .AddProject - ( + ( new ConfigProject { Name = TestProject, Guidance = "Enter the name of the project that hosts the MSTest integration testings." } - ); + ) + .AddParameter + ( + new ConfigParameter + { + Name = TestPrefix, + Guidance = "Optional, prefix to append to the name of the integration test when being created." + } + ) + .AddParameter + ( + new ConfigParameter + { + Name = TestSuffix, + Guidance = "Optional, Suffix to append to the name of the integration test when being created.", + Value = "Test" + + } + ); return config; } @@ -129,12 +160,26 @@ public override async Task ExecuteCommandAsync(VsCSharpSource result) var testProject = (await VisualStudioActions.GetProjectFromConfigAsync(config.Project(TestProject))) ?? throw new CodeFactoryException("Could not locate the test project cannot refresh the test."); + + var targetInterface = result.SourceCode?.Interfaces?.FirstOrDefault() ?? throw new CodeFactoryException("Could not locate the interface to have tests created from."); - var test = VisualStudioActions.RefreshMSTestIntegrationTestAsync(targetInterface, testProject); + var testPrefix = config.Project(TestProject).ParameterValue(TestPrefix); + var testSuffix = config.Project(TestProject).ParameterValue(TestSuffix); + + string noRemove = null; + + var testName = NameManagement.Init(noRemove,noRemove,testPrefix,testSuffix).FormatName(targetInterface.Name.GenerateCSharpFormattedClassName()); + var test = VisualStudioActions.RefreshMSTestIntegrationTestAsync(testName,targetInterface, testProject); + + + } + catch (CodeFactoryException codeFactoryError) + { + MessageBox.Show(codeFactoryError.Message, "Automation Error", MessageBoxButton.OK, MessageBoxImage.Error); } catch (Exception unhandledError) { diff --git a/src/Architecture/CodeFactory.Architecture.Blazor.Server/UpdateLogicImplementation.cs b/src/Architecture/CodeFactory.Architecture.Blazor.Server/CSharpFile/UpdateLogicImplementation.cs similarity index 85% rename from src/Architecture/CodeFactory.Architecture.Blazor.Server/UpdateLogicImplementation.cs rename to src/Architecture/CodeFactory.Architecture.Blazor.Server/CSharpFile/UpdateLogicImplementation.cs index 8e0663f..60e57c4 100644 --- a/src/Architecture/CodeFactory.Architecture.Blazor.Server/UpdateLogicImplementation.cs +++ b/src/Architecture/CodeFactory.Architecture.Blazor.Server/CSharpFile/UpdateLogicImplementation.cs @@ -1,4 +1,5 @@ -using CodeFactory.Automation.Standard.Logic; +using CodeFactory.Automation.NDF.Logic.General; +using CodeFactory.Automation.Standard.Logic; using CodeFactory.WinVs; using CodeFactory.WinVs.Commands; using CodeFactory.WinVs.Commands.SolutionExplorer; @@ -11,8 +12,9 @@ using System.Linq; using System.Text; using System.Threading.Tasks; +using System.Windows; -namespace CodeFactory.Architecture.Blazor.Server +namespace CodeFactory.Architecture.Blazor.Server.CSharpFile { /// /// Code factory command for automation of a C# document when selected from a project in solution explorer. @@ -50,12 +52,12 @@ public UpdateLogicImplementation(ILogger logger, IVsActions vsActions) : base(lo /// /// List of prefixes to be removed from the interface definition. /// - public static string RepoPrefix = "RepoPrefix"; + public static string RemoveRepoPrefix = "RemoveRepoPrefix"; /// /// List of suffixes to be removed from the interface definition. /// - public static string RepoSuffix = "RepoSuffix"; + public static string RemoveRepoSuffix = "RepoSuffix"; /// /// The project the logic contract can be found in. @@ -115,7 +117,7 @@ public override ConfigCommand LoadExternalConfigDefinition() ( new ConfigParameter { - Name = RepoPrefix, + Name = RemoveRepoPrefix, Guidance = "List of prefixes to be removed from the beginning of the contract name." } @@ -124,7 +126,7 @@ public override ConfigCommand LoadExternalConfigDefinition() ( new ConfigParameter { - Name = RepoSuffix, + Name = RemoveRepoSuffix, Guidance = "List of suffixes to be removed from the end of the contract name." } @@ -218,8 +220,8 @@ public override async Task EnableCommandAsync(VsCSharpSource result) if(isEnabled ) { - var repoPrefix = command.ExecutionProject.ParameterValue(RepoPrefix); - var repoSuffix = command.ExecutionProject.ParameterValue(RepoSuffix); + var repoPrefix = command.ExecutionProject.ParameterValue(RemoveRepoPrefix); + var repoSuffix = command.ExecutionProject.ParameterValue(RemoveRepoSuffix); isEnabled = IsRepositoryContract(repoInterface,repoPrefix,repoSuffix); } } @@ -248,24 +250,35 @@ public override async Task ExecuteCommandAsync(VsCSharpSource result) var repoContract = result.SourceCode?.Interfaces.FirstOrDefault() ?? throw new CodeFactoryException("Could not load the repository contract cannot update the logic implementation."); - var logicContractProject = await VisualStudioActions.GetProjectFromConfigAsync(command.Project(LogicContractProject)); + var logicContractProject = await VisualStudioActions.GetProjectFromConfigAsync(command.Project(LogicContractProject)) + ?? throw new CodeFactoryException("The logic contract project could not be loaded, cannot refresh the logic class."); var logicContractProjectFolder = await VisualStudioActions.GetProjectFolderFromConfigAsync(command.Project(LogicContractProject),LogicContractProjectFolder); - var repoPrefix = command.ExecutionProject.ParameterValue(RepoPrefix); - var repoSuffix = command.ExecutionProject.ParameterValue(RepoSuffix); + var logicProject = await VisualStudioActions.GetProjectFromConfigAsync(command.Project(LogicProject)) + ?? throw new CodeFactoryException("The logic project could not be loaded, cannot refresh the logic class."); + + var logicProjectFolder = await VisualStudioActions.GetProjectFolderFromConfigAsync(command.Project(LogicProject),LogicProjectFolder); + + var repoRemovePrefix = command.ExecutionProject.ParameterValue(RemoveRepoPrefix); + var repoRemoveSuffix = command.ExecutionProject.ParameterValue(RemoveRepoSuffix); var logicPrefix = command.Project(LogicContractProject)?.ParameterValue(LogicPrefix); var logicSuffix = command.Project(LogicContractProject)?.ParameterValue(LogicSuffix); - var removePrefixes = repoPrefix == null ? null: new List(repoPrefix.Split(',')); - var removeSuffixes = repoSuffix == null ? null: new List(repoSuffix.Split(',')); - var nameManagement = NameManagement.Init(removePrefixes,removeSuffixes,logicPrefix,logicSuffix); + + var logicName = NameManagement.Init(repoRemovePrefix,repoRemoveSuffix,logicPrefix,logicSuffix).FormatName(repoContract.Name.GenerateCSharpFormattedClassName()); - var logicContract = await VisualStudioActions.CloneInterfaceAsync(repoContract,false,logicContractProject, - logicContractProjectFolder,nameManagement,"Logic contract implementation."); + var logicContract = await VisualStudioActions.CloneInterfaceAsync($"I{logicName}", repoContract,false,logicContractProject, + logicContractProjectFolder,"Logic contract implementation."); + + var logicClass = await VisualStudioActions.RefreshLogicAsync(logicName,$"I{logicName}",logicProject,logicContractProject,logicFolder:logicProjectFolder,contractFolder:logicContractProjectFolder); } + catch (CodeFactoryException codeFactoryError) + { + MessageBox.Show(codeFactoryError.Message, "Automation Error", MessageBoxButton.OK, MessageBoxImage.Error); + } catch (Exception unhandledError) { _logger.Error($"The following unhandled error occurred while executing the solution explorer C# document command {commandTitle}. ", diff --git a/src/Architecture/CodeFactory.Architecture.Blazor.Server/CodeFactory.Architecture.Blazor.Server.csproj b/src/Architecture/CodeFactory.Architecture.Blazor.Server/CodeFactory.Architecture.Blazor.Server.csproj index 1b674cd..4d9f31f 100644 --- a/src/Architecture/CodeFactory.Architecture.Blazor.Server/CodeFactory.Architecture.Blazor.Server.csproj +++ b/src/Architecture/CodeFactory.Architecture.Blazor.Server/CodeFactory.Architecture.Blazor.Server.csproj @@ -48,19 +48,20 @@ - - - - - + + + + + + - - - - - - - + + + + + + + @@ -72,6 +73,7 @@ CodeFactory.Automation.Standard.Logic +