Skip to content

Commit d242d99

Browse files
authored
Merge pull request #14 from CodeFactoryLLC/ServiceRestJson
Service Rest Json Architecture Project
2 parents 7557b7f + 0a3a9df commit d242d99

16 files changed

+2369
-11
lines changed
Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,259 @@
1+
using CodeFactory.Automation.NDF.Logic;
2+
using CodeFactory.Automation.Standard.Logic;
3+
using CodeFactory.WinVs;
4+
using CodeFactory.WinVs.Commands;
5+
using CodeFactory.WinVs.Commands.SolutionExplorer;
6+
using CodeFactory.WinVs.Logging;
7+
using CodeFactory.WinVs.Models.CSharp;
8+
using CodeFactory.WinVs.Models.CSharp.Builder;
9+
using CodeFactory.WinVs.Models.ProjectSystem;
10+
using System;
11+
using System.Collections.Generic;
12+
using System.Linq;
13+
using System.Text;
14+
using System.Threading.Tasks;
15+
using System.Windows;
16+
17+
namespace CodeFactory.Architecture.AspNetCore.Service.Rest
18+
{
19+
/// <summary>
20+
/// Code factory command for automation of a C# document when selected from a project in solution explorer.
21+
/// </summary>
22+
public class AddMissingLogicMembers : CSharpSourceCommandBase
23+
{
24+
private static readonly string commandTitle = "Add Missing Logic Members";
25+
private static readonly string commandDescription = "Adds missing contract interface members to the Logic implementation.";
26+
27+
#pragma warning disable CS1998
28+
29+
/// <inheritdoc />
30+
public AddMissingLogicMembers(ILogger logger, IVsActions vsActions) : base(logger, vsActions, commandTitle, commandDescription)
31+
{
32+
//Intentionally blank
33+
}
34+
35+
#region External Configuration
36+
37+
/// <summary>
38+
/// The fully qualified name of the command to be used with configuration.
39+
/// </summary>
40+
public static string Type = typeof(AddMissingLogicMembers).FullName;
41+
42+
43+
/// <summary>
44+
/// Exection project for the command.
45+
/// </summary>
46+
public static string ExecutionProject = "ExecutionProject";
47+
48+
/// <summary>
49+
/// Execution folder for the command.
50+
/// </summary>
51+
public static string ExecutionFolder = "ExecutionFolder";
52+
53+
/// <summary>
54+
/// Repositories name prefix
55+
/// </summary>
56+
public static string LogicPrefix = "LogicPrefix";
57+
58+
59+
/// <summary>
60+
/// Repositories name suffix.
61+
/// </summary>
62+
public static string LogicSuffix = "LogicSuffix";
63+
64+
/// <summary>
65+
/// Loads the external configuration definition for this command.
66+
/// </summary>
67+
/// <returns>Will return the command configuration or null if this command does not support external configurations.</returns>
68+
public override ConfigCommand LoadExternalConfigDefinition()
69+
{
70+
var config = new ConfigCommand{ CommandType = Type, Name = commandTitle, Category = "Logic",Guidance = "Command is used when updating missing members from a logic implementation." }
71+
.UpdateExecutionProject
72+
(
73+
new ConfigProject
74+
{
75+
Name = ExecutionProject,
76+
Guidance = "The project where the logic class file resides in."
77+
}
78+
.AddFolder
79+
(
80+
new ConfigFolder
81+
{
82+
Name = ExecutionFolder,
83+
Required = false,
84+
Guidance = "The target folder the logic class will be found in."
85+
}
86+
)
87+
.AddParameter
88+
(
89+
new ConfigParameter
90+
{
91+
Name = LogicPrefix,
92+
Guidance = "Optional, checks to makes sure the class starts with the provided prefix before considering it a logic."
93+
}
94+
)
95+
.AddParameter
96+
(
97+
new ConfigParameter
98+
{
99+
Name = LogicSuffix,
100+
Guidance = "Optional, checks to makes sure the class starts with the provided suffix before considering it a logic."
101+
}
102+
)
103+
104+
);
105+
106+
return config;
107+
}
108+
#endregion
109+
110+
#region Overrides of VsCommandBase<IVsCSharpDocument>
111+
112+
/// <summary>
113+
/// Validation logic that will determine if this command should be enabled for execution.
114+
/// </summary>
115+
/// <param name="result">The target model data that will be used to determine if this command should be enabled.</param>
116+
/// <returns>Boolean flag that will tell code factory to enable this command or disable it.</returns>
117+
public override async Task<bool> EnableCommandAsync(VsCSharpSource result)
118+
{
119+
//Result that determines if the command is enabled and visible in the context menu for execution.
120+
bool isEnabled = false;
121+
122+
try
123+
{
124+
var logicClass = result?.SourceCode?.Classes.FirstOrDefault();
125+
126+
isEnabled = logicClass != null;
127+
128+
ConfigCommand command = null;
129+
130+
if( isEnabled )
131+
{
132+
command = await ConfigManager.LoadCommandByFolderAsync(Type, ExecutionFolder, result)
133+
?? await ConfigManager.LoadCommandByProjectAsync(Type, result);
134+
135+
isEnabled = command != null;
136+
}
137+
138+
if(isEnabled )
139+
{
140+
var logicPrefix = command.ExecutionProject.ParameterValue(LogicPrefix);
141+
var logicSuffix = command.ExecutionProject.ParameterValue(LogicSuffix);
142+
isEnabled = IsLogicClass(logicClass,logicPrefix,logicSuffix);
143+
}
144+
145+
if(isEnabled ) isEnabled = logicClass.GetMissingInterfaceMembers().Any();
146+
}
147+
catch (Exception unhandledError)
148+
{
149+
_logger.Error($"The following unhandled error occurred while checking if the solution explorer C# document command {commandTitle} is enabled. ",
150+
unhandledError);
151+
isEnabled = false;
152+
}
153+
154+
return isEnabled;
155+
}
156+
157+
/// <summary>
158+
/// Code factory framework calls this method when the command has been executed.
159+
/// </summary>
160+
/// <param name="result">The code factory model that has generated and provided to the command to process.</param>
161+
public override async Task ExecuteCommandAsync(VsCSharpSource result)
162+
{
163+
try
164+
{
165+
166+
var logicSource = result.SourceCode;
167+
168+
if (logicSource == null) return;
169+
170+
logicSource = await logicSource.AddUsingStatementAsync("Microsoft.Extensions.Logging");
171+
logicSource = await logicSource.AddUsingStatementAsync("CodeFactory.NDF");
172+
173+
var logicClass = logicSource.Classes.FirstOrDefault();
174+
if(logicClass == null) return;
175+
176+
var missingMembers = logicClass.GetMissingInterfaceMembers();
177+
178+
if( !missingMembers.Any() ) return;
179+
180+
181+
string loggerFieldName = "_logger";
182+
183+
if (!logicClass.Fields.Any(f=>f.Name == loggerFieldName))
184+
{
185+
SourceFormatter formatter = new SourceFormatter();
186+
187+
formatter.AppendCodeLine(2,"/// <summary>");
188+
formatter.AppendCodeLine(2,"/// Logger for the class");
189+
formatter.AppendCodeLine(2,"/// </summary>");
190+
formatter.AppendCodeLine(2,$"private readonly ILogger {loggerFieldName};");
191+
formatter.AppendCodeLine(2);
192+
logicSource = await logicClass.AddToBeginningAsync(formatter.ReturnSource());
193+
logicClass = logicSource.Classes.FirstOrDefault();
194+
}
195+
196+
197+
var command = await ConfigManager.LoadCommandByFolderAsync(Type, ExecutionFolder, result)
198+
?? await ConfigManager.LoadCommandByProjectAsync(Type, result);
199+
200+
if(command == null)return;
201+
202+
203+
var loggerBlock = new LoggerBlockNDFLogger(loggerFieldName);
204+
205+
var catchBlocks = new List<ICatchBlock>
206+
{
207+
new CatchBlockManagedExceptionNDFException(loggerBlock),
208+
new CatchBlockExceptionNDFException(loggerBlock)
209+
};
210+
211+
var boundChecks = new List<IBoundsCheckBlock>
212+
{
213+
214+
new BoundsCheckBlockNullNDFException(true,loggerBlock),
215+
new BoundsCheckBlockStringNDFException(true,loggerBlock)
216+
};
217+
218+
var tryBlock = new TryBlockStandard(loggerBlock,catchBlocks);
219+
220+
var updatedlogicClass = await VisualStudioActions.AddClassMissingMembersAsync(result.SourceCode,logicClass,false,loggerBlock,Microsoft.Extensions.Logging.LogLevel.Information,boundChecks,tryBlock,missingMembers);
221+
222+
}
223+
catch (CodeFactoryException cfException)
224+
{
225+
MessageBox.Show(cfException.Message,"CodeFactory Error",MessageBoxButton.OK,MessageBoxImage.Error);
226+
}
227+
catch (Exception unhandledError)
228+
{
229+
_logger.Error($"The following unhandled error occurred while executing the solution explorer C# document command {commandTitle}. ",
230+
unhandledError);
231+
232+
}
233+
234+
}
235+
236+
/// <summary>
237+
/// Validation check to make sure the logic class is formatted to correct name.
238+
/// </summary>
239+
/// <param name="logicClass">Class to check.</param>
240+
/// <param name="logicPrefix">The prefix the logic class should start with, this can be null.</param>
241+
/// <param name="logicSuffix">The suffix the logic class should end with, this can be null.</param>
242+
/// <returns>True class name is formatted correctly, false if not.</returns>
243+
private bool IsLogicClass(CsClass logicClass,string logicPrefix, string logicSuffix)
244+
{
245+
246+
bool islogicClass = false;
247+
248+
if (logicClass != null) islogicClass = true;
249+
250+
if(islogicClass & logicPrefix != null) islogicClass = logicClass.Name.StartsWith(logicPrefix);
251+
252+
if(islogicClass & logicSuffix != null) islogicClass = logicClass.Name.EndsWith(logicSuffix);
253+
254+
return islogicClass;
255+
}
256+
257+
#endregion
258+
}
259+
}

0 commit comments

Comments
 (0)