Browse Source

Functionality built.

The solution now has a working version of the class library on the console program. The console program is now setup, as well. I have not implemented the Help section properly in the console program yet. But, it is wired up and awaiting the addition of the attributes to the command-methods.
merge-requests/1/head
Craig Oates 7 years ago
parent
commit
4398ae6ad0
  1. 6
      Console.Waterworks/CW_Console/App.config
  2. 10
      Console.Waterworks/CW_Console/CW_Console.csproj
  3. 36
      Console.Waterworks/CW_Console/ConsoleCommands.cs
  4. 5
      Console.Waterworks/CW_Console/Program.cs
  5. 6
      Console.Waterworks/Console.Waterworks.sln
  6. 46
      Console.Waterworks/Console.Waterworks/Assistants/CoOrdinatorAssistant.cs
  7. 99
      Console.Waterworks/Console.Waterworks/Assistants/CommandsAssistant.cs
  8. 13
      Console.Waterworks/Console.Waterworks/Attributes/DescriptionAttribute.cs
  9. 16
      Console.Waterworks/Console.Waterworks/Attributes/ListCommandAttribute.cs
  10. 12
      Console.Waterworks/Console.Waterworks/Attributes/ParametersAttribute.cs
  11. 12
      Console.Waterworks/Console.Waterworks/Attributes/UsageAttribute.cs
  12. 12
      Console.Waterworks/Console.Waterworks/CWLiaision.cs
  13. 23
      Console.Waterworks/Console.Waterworks/CW_Liaison.cs
  14. 94
      Console.Waterworks/Console.Waterworks/CoOrdinators/CoOrdinator.cs
  15. 26
      Console.Waterworks/Console.Waterworks/Console.Waterworks.csproj
  16. 19
      Console.Waterworks/Console.Waterworks/Constants/CW_Constants.cs
  17. 10
      Console.Waterworks/Console.Waterworks/Loggers/CW_Logger.cs
  18. 68
      Console.Waterworks/Console.Waterworks/Models/Command.cs
  19. 172
      Console.Waterworks/Console.Waterworks/Specialists/CoercionSpecialist.cs
  20. 52
      Console.Waterworks/Console.Waterworks/Specialists/CommandsSpecialist.cs
  21. 61
      Console.Waterworks/Console.Waterworks/Specialists/ConsoleIOSpecialist.cs
  22. 59
      Console.Waterworks/Console.Waterworks/Specialists/HelpSpecialist.cs
  23. 66
      Console.Waterworks/Console.Waterworks/Specialists/ProgramInfoSpecialist.cs

6
Console.Waterworks/CW_Console/App.config

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7"/>
</startup>
</configuration>
</configuration>

10
Console.Waterworks/CW_Console/CW_Console.csproj

@ -8,9 +8,10 @@
<OutputType>Exe</OutputType>
<RootNamespace>CW_Console</RootNamespace>
<AssemblyName>CW_Console</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.7</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
@ -42,11 +43,18 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="ConsoleCommands.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Console.Waterworks\Console.Waterworks.csproj">
<Project>{d1354760-61f7-4aee-8d6f-e78a463ee3c9}</Project>
<Name>Console.Waterworks</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

36
Console.Waterworks/CW_Console/ConsoleCommands.cs

@ -0,0 +1,36 @@
using Console.Waterworks;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CW_Console
{
public static class ConsoleCommands
{
public static string Help()
{
CW_Liaison liaison = new CW_Liaison();
return liaison.RequestHelpDocumentation("CW_Console");
}
public static string Command1() => "Command1 has completed";
public static string Command2(string input) => $"Command2 has completed... {input} was entered";
public static string Command3(int input) => $"Command3 has completed... The number {input} was entered";
public static string Command4(int int1, int int2) => $"Command4 has completed... {int1} and {int2} was entered and make {int1 + int2} when added together";
public static string Command5(int int1, double double1) => $"Command5 has completed... {int1} and {double1} was entered and make {int1 + double1} when added together";
public static void Quit() => Environment.Exit(-1);
#region Alias Methods
// These methods are shorthand versions of the ones above.
// These are useful for experienced users of your console program.
public static string c1() => Command1();
public static string c2(string input) => Command2(input);
public static string c3(int input) => Command3(input);
public static string c4(int int1, int int2) => Command4(int1, int2);
public static string c5(int int1, double double1) => Command5(int1, double1);
public static void quit() => Quit();
#endregion
}
}

5
Console.Waterworks/CW_Console/Program.cs

@ -1,4 +1,5 @@
using System;
using Console.Waterworks;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@ -10,6 +11,8 @@ namespace CW_Console
{
static void Main(string[] args)
{
CW_Liaison bob = new CW_Liaison();
bob.Run("CW_Console", true);
}
}
}

6
Console.Waterworks/Console.Waterworks.sln

@ -5,6 +5,8 @@ VisualStudioVersion = 15.0.26730.16
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Console.Waterworks", "Console.Waterworks\Console.Waterworks.csproj", "{D1354760-61F7-4AEE-8D6F-E78A463EE3C9}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CW_Console", "CW_Console\CW_Console.csproj", "{E26D7001-2A4E-4618-8C27-8BF504993EE9}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -15,6 +17,10 @@ Global
{D1354760-61F7-4AEE-8D6F-E78A463EE3C9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D1354760-61F7-4AEE-8D6F-E78A463EE3C9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D1354760-61F7-4AEE-8D6F-E78A463EE3C9}.Release|Any CPU.Build.0 = Release|Any CPU
{E26D7001-2A4E-4618-8C27-8BF504993EE9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E26D7001-2A4E-4618-8C27-8BF504993EE9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E26D7001-2A4E-4618-8C27-8BF504993EE9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E26D7001-2A4E-4618-8C27-8BF504993EE9}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

46
Console.Waterworks/Console.Waterworks/Assistants/CoOrdinatorAssistant.cs

@ -1,12 +1,52 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Console.Waterworks.Loggers;
using Console.Waterworks.Specialists;
using System.Reflection;
using Console.Waterworks.Constants;
namespace Console.Waterworks.Assistants
{
class CoOrdinatorAssistant
{
internal void SetConsoleTitle(CW_Logger logger, ProgramInfoSpecialist progInfoSpec, ConsoleIOSpecialist consoleSpec)
{
logger.LogInfoMessage("Attempting to set console title..");
var title = progInfoSpec.GetProductName();
if (!string.IsNullOrEmpty(title))
{
consoleSpec.SetConsoleTitle(title);
logger.LogSuccessMessage("Console title is now set");
}
else
logger.LogErrorMessage("Unable to determine the program's title. Check the manifest file to make sure it has been set");
}
internal void OutputProgramInfo(CW_Logger logger, ProgramInfoSpecialist progInfoSpec, ConsoleIOSpecialist consoleSpec)
{
logger.LogInfoMessage("Attempting to retrieve program information..");
List<string> programInfo = progInfoSpec.GatherProgramInfomation();
logger.LogInfoMessage($"Found {programInfo.Count} out of {CW_Constants.PROGRAM_INFO_PROPERTIES_COUNT} properties");
logger.LogInfoMessage($"Writing program properties to console..");
consoleSpec.WriteProgramInfo(programInfo);
}
internal void LogCommandGatheringAttempt(List<Type> commandClasses, Dictionary<string, Dictionary<string, IEnumerable<ParameterInfo>>> commandLibraries, CW_Logger logger)
{
logger.LogInfoMessage($"Found {commandClasses.Count} command class(es)..");
logger.LogInfoMessage($"Found {GetFoundCommandsTotal(commandLibraries)} command(s)..");
logger.LogInfoMessage($"Found [{CW_Constants.COMMAND_CLASS_NAME}] class: { commandLibraries.ContainsKey(CW_Constants.COMMAND_CLASS_NAME)}");
logger.LogNoteMessage($"WaterWorks is only looking for the methods in the [{CW_Constants.COMMAND_CLASS_NAME}] class in the specified namespace. Everything else will be ignored");
logger.LogInfoMessage("Program is now initialised and awaiting input from the user. You are welcome ;-)");
}
internal int GetFoundCommandsTotal(Dictionary<string, Dictionary<string, IEnumerable<ParameterInfo>>> commandLibraries)
{
int total = 0;
foreach (var currentClass in commandLibraries.Values)
total += currentClass.Count;
return total;
}
}
}

99
Console.Waterworks/Console.Waterworks/Assistants/CommandsAssistant.cs

@ -1,12 +1,105 @@
using System;
using Console.Waterworks.Models;
using Console.Waterworks.Specialists;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;
namespace Console.Waterworks.Assistants
{
class CommandsAssistant
{
internal bool ValidateClass(Command command, Dictionary<string, Dictionary<string, IEnumerable<ParameterInfo>>> commandLibraries)
=> (commandLibraries.ContainsKey(command.ClassName)) ? true : false;
internal bool ValidateCommand(Command command, Dictionary<string, Dictionary<string, IEnumerable<ParameterInfo>>> commandLibraries)
{
var methodDict = commandLibraries[command.ClassName];
return (methodDict.ContainsKey(command.Name)) ? true : false;
}
internal string ExecuteBadCommandProcedure(Command command, ConsoleIOSpecialist consoleSpec)
{
consoleSpec.WriteErrorSuffix();
return $"The command \'{command.Name}\' is not recognised.";
}
internal bool ValidateParamArguments(Command command, List<ParameterInfo> paramInfoList)
{
var requiredParams = paramInfoList.Where(p => p.IsOptional == false);
var optionalParams = paramInfoList.Where(p => p.IsOptional == true);
int requiredCount = requiredParams.Count();
int optionalCount = optionalParams.Count();
int providedCount = command.Arguments.Count();
return (requiredCount > providedCount) ? false : true;
}
internal string ExecuteMissingArgumentProcedure(Command command, List<ParameterInfo> paramInfoList, ConsoleIOSpecialist consoleSpec)
{
var requiredParams = paramInfoList.Where(p => p.IsOptional == false);
var optionalParams = paramInfoList.Where(p => p.IsOptional == true);
int requiredCount = requiredParams.Count();
int optionalCount = optionalParams.Count();
int providedCount = command.Arguments.Count();
return $"Missing required argument. {requiredCount} required, {optionalCount} optional, {providedCount} provided.";
}
internal List<object> GetParametreValueList(Command command, List<ParameterInfo> paramInfoList)
{
var methodParameterValueList = new List<object>();
if (paramInfoList.Count() > 0)
{
foreach (var param in paramInfoList)
{
methodParameterValueList.Add(param.DefaultValue);
}
for (int i = 0; i < command.Arguments.Count(); i++)
{
var methodParam = paramInfoList.ElementAt(i);
var typeRequired = methodParam.ParameterType;
object value = null;
try
{
value = CoercionSpecialist.CoerceArgument(typeRequired, command.Arguments.ElementAt(i));
methodParameterValueList.RemoveAt(i);
methodParameterValueList.Insert(i, value);
}
catch (ArgumentException ex)
{
string message = $"The value passed for argument '{methodParam.Name}' cannot be parsed to type '{typeRequired.Name}'"; // The exception message is being used instead, for now.
throw new ArgumentException(ex.Message);
}
}
}
return methodParameterValueList;
}
internal Type BuildCommandLibraryClass(Command command, string commandsNamespace)
{
Assembly programAssembly = Assembly.GetEntryAssembly();
Type commandLibraryClass = programAssembly.GetType($"{commandsNamespace}.{command.ClassName}");
return commandLibraryClass;
}
internal string InvokeCommand(Command command, Type typeInfo, object[] inputArguments)
{
try
{
var result = typeInfo.InvokeMember(command.Name, BindingFlags.InvokeMethod | BindingFlags.Static | BindingFlags.Public, null, null, inputArguments);
return result.ToString();
}
catch (TargetInvocationException ex)
{
throw ex.InnerException;
}
}
internal object[] GetInputArguments(List<object> methodParametreValueList)
{
object[] inputArguments = null;
if (methodParametreValueList.Count > 0)
inputArguments = methodParametreValueList.ToArray();
return inputArguments;
}
}
}

13
Console.Waterworks/Console.Waterworks/Attributes/DescriptionAttribute.cs

@ -1,12 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Console.Waterworks.Attributes
{
class DescriptionAttribute
[AttributeUsage(AttributeTargets.All)]
public class DescriptionAttribute : Attribute
{
public readonly string Description;
public DescriptionAttribute(string description)
{
Description = description;
}
}
}

16
Console.Waterworks/Console.Waterworks/Attributes/ListCommandAttribute.cs

@ -1,12 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Console.Waterworks.Attributes
{
class ListCommandAttribute
[AttributeUsage(AttributeTargets.All)]
public class ListCommandAttribute : Attribute
{
public readonly bool ShowCommand;
public ListCommandAttribute()
{
ShowCommand = true;
}
public ListCommandAttribute(bool show)
{
ShowCommand = show;
}
}
}

12
Console.Waterworks/Console.Waterworks/Attributes/ParametersAttribute.cs

@ -1,12 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Console.Waterworks.Attributes
{
class ParametersAttribute
[AttributeUsage(AttributeTargets.All)]
public class ParametresAttribute : Attribute
{
public readonly string Parametres;
public ParametresAttribute(string arguments)
{
Parametres = arguments;
}
}
}

12
Console.Waterworks/Console.Waterworks/Attributes/UsageAttribute.cs

@ -1,12 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Console.Waterworks.Attributes
{
class UsageAttribute
[AttributeUsage(AttributeTargets.All)]
public class UsageAttribute : Attribute
{
public readonly string UsageExample;
public UsageAttribute(string example)
{
UsageExample = example;
}
}
}

12
Console.Waterworks/Console.Waterworks/CWLiaision.cs

@ -1,12 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Console.Waterworks
{
public class CWLiaision
{
}
}

23
Console.Waterworks/Console.Waterworks/CW_Liaison.cs

@ -0,0 +1,23 @@
using Console.Waterworks.CoOrdinators;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Console.Waterworks
{
public class CW_Liaison
{
CoOrdinator kevin = new CoOrdinator();
public void Run(string consoleCommandsNamespace,bool includeProgramInfo)
{
kevin.PrepareConsoleEnvironment();
if (includeProgramInfo == true) kevin.DisplayProgramInfo();
kevin.RunProgram(consoleCommandsNamespace);
}
public string RequestHelpDocumentation(string consoleCommandsNamespace) => kevin.DisplayHelpSection(consoleCommandsNamespace);
}
}

94
Console.Waterworks/Console.Waterworks/CoOrdinators/CoOrdinator.cs

@ -1,12 +1,96 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Console.Waterworks.Assistants;
using Console.Waterworks.Constants;
using Console.Waterworks.Loggers;
using Console.Waterworks.Models;
using Console.Waterworks.Specialists;
using System;
namespace Console.Waterworks.CoOrdinators
{
class CoOrdinator
{
CoOrdinatorAssistant Assistant = new CoOrdinatorAssistant();
ProgramInfoSpecialist ProgInfoSpec = new ProgramInfoSpecialist();
ConsoleIOSpecialist ConsoleSpec = new ConsoleIOSpecialist();
CommandsSpecialist CommSpec = new CommandsSpecialist();
HelpSpecialist HelpSpec = new HelpSpecialist();
CW_Logger Logger = new CW_Logger();
internal void PrepareConsoleEnvironment()
{
Logger.LogInfoMessage($"Preparing console..");
ConsoleSpec.PrepareConsoleEnvironment();
ConsoleSpec.SetInputPrompt($"{ProgInfoSpec.GetProductName()}> ");
Logger.LogSuccessMessage("Console environment is now setup");
}
internal void DisplayProgramInfo()
{
Logger.LogInfoMessage($"Displaying program information..");
Assistant.SetConsoleTitle(Logger, ProgInfoSpec, ConsoleSpec);
Assistant.OutputProgramInfo(Logger, ProgInfoSpec, ConsoleSpec);
}
internal void RunProgram(string commandsNamespace)
{
Logger.LogInfoMessage("Attempting to building commands library..");
var commandClasses = CommSpec.GetCommandClasses(commandsNamespace);
var commandLibraries = CommSpec.GetCommandLibraries(commandClasses);
Assistant.LogCommandGatheringAttempt(commandClasses, commandLibraries, Logger);
while (true)
{
var consoleInput = ConsoleSpec.GetInputFromUser();
if (string.IsNullOrEmpty(consoleInput)) continue;
try
{
Logger.LogInfoMessage("Parsing input from user..");
var command = new Command(consoleInput, commandsNamespace, CW_Constants.COMMAND_CLASS_NAME);
Logger.LogInfoMessage("Attempting to execute command..");
var result = CommSpec.ExecuteCommand(commandsNamespace, command, commandClasses, commandLibraries, ConsoleSpec);
ConsoleSpec.WriteOutputToConsole(result);
Logger.LogSuccessMessage("Command has been executed.");
Logger.LogNoteMessage("An error message does not mean the command did not execute properly or sucessfully.");
}
catch (Exception ex)
{
Logger.LogErrorMessage("Command was not successfully executed. See the error message in console for further details");
ConsoleSpec.WriteErrorMessage(ex.Message);
}
Logger.LogInfoMessage("Resetting the console's formatting..");
Logger.LogNoteMessage("This is to make sure no error messages or one-off formating change corrupts the console environment.");
ConsoleSpec.ResetConsoleColour();
Logger.LogSuccessMessage("Console's formating has been reset");
}
}
internal string DisplayHelpSection(string commandsNamespace)
{
Logger.LogInfoMessage("Attempting to display help section..");
var commandClasses = CommSpec.GetCommandClasses(commandsNamespace);
if (commandClasses.Count == 0)
{
Logger.LogErrorMessage("Unable to find any help information. Make sure the commands hace the correct atrributes applied");
ConsoleSpec.WriteErrorSuffix();
return "Unable to find help information";
}
Logger.LogSuccessMessage("Found help information");
Logger.LogInfoMessage("Attempting to display the help information..");
ConsoleSpec.WriteOutputToConsole("Displaying Help section.");
ConsoleSpec.LineBreak();
var commandMembers = HelpSpec.GetCommandMembers(commandClasses);
foreach (var command in commandMembers)
{
if (HelpSpec.ListCommand(command) == true)
{
ConsoleSpec.WriteOutputToConsole($"Command Name: {command.Name}");
ConsoleSpec.WriteOutputToConsole($"Parametres: {HelpSpec.GetParametres(command)}");
ConsoleSpec.WriteOutputToConsole($"Description: {HelpSpec.GetDescription(command)}");
ConsoleSpec.WriteOutputToConsole($"Example: {HelpSpec.GetUsageExamples(command)}");
ConsoleSpec.LineBreak();
}
}
Logger.LogSuccessMessage("Help section displayed in the console");
return "End of Help section.";
}
}
}

26
Console.Waterworks/Console.Waterworks/Console.Waterworks.csproj

@ -44,17 +44,25 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="CWLiaision.cs" />
<Compile Include="Assistants\CommandsAssistant.cs" />
<Compile Include="Assistants\CoOrdinatorAssistant.cs" />
<Compile Include="Attributes\DescriptionAttribute.cs" />
<Compile Include="Attributes\ListCommandAttribute.cs" />
<Compile Include="Attributes\ParametersAttribute.cs" />
<Compile Include="Attributes\UsageAttribute.cs" />
<Compile Include="Constants\CW_Constants.cs" />
<Compile Include="CoOrdinators\CoOrdinator.cs" />
<Compile Include="CW_Liaison.cs" />
<Compile Include="Loggers\CW_Logger.cs" />
<Compile Include="Models\Command.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Specialists\CoercionSpecialist.cs" />
<Compile Include="Specialists\CommandsSpecialist.cs" />
<Compile Include="Specialists\ConsoleIOSpecialist.cs" />
<Compile Include="Specialists\HelpSpecialist.cs" />
<Compile Include="Specialists\ProgramInfoSpecialist.cs" />
</ItemGroup>
<ItemGroup>
<Folder Include="Assistants\" />
<Folder Include="Attributes\" />
<Folder Include="Constants\" />
<Folder Include="CoOrdinators\" />
<Folder Include="Models\" />
<Folder Include="Specialists\" />
</ItemGroup>
<ItemGroup />
<ItemGroup>
<Content Include="WaterWorksIcon.ico" />
</ItemGroup>

19
Console.Waterworks/Console.Waterworks/Constants/CW_Constants.cs

@ -1,12 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Console.Waterworks.Constants
namespace Console.Waterworks.Constants
{
class CWConstants
class CW_Constants
{
/// <summary>
/// This represents the maximum number of properties the console can display when the client "DisplayProgramInfo" to true. This is used mostly for logging purposes.
/// </summary>
public const int PROGRAM_INFO_PROPERTIES_COUNT = 4;
/// <summary>
/// This specifies the name of the class WaterWorks looks for when it tries to build its command library. This class should not be in WaterWorks. It should be in the clients console program.
/// </summary>
public const string COMMAND_CLASS_NAME = "ConsoleCommands";
}
}

10
Console.Waterworks/Console.Waterworks/Loggers/CW_Logger.cs

@ -1,12 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
namespace Console.Waterworks.Loggers
{
class CW_Logger
{
internal void LogInfoMessage(string message) => Debug.WriteLine($"[Console.WaterWorks] INFO: {message}.");
internal void LogNoteMessage(string message) => Debug.WriteLine($"[Console.WaterWorks] NOTE: {message}.");
internal void LogSuccessMessage(string message) => Debug.WriteLine($"[Console.WaterWorks] SUCCESS: {message}.");
internal void LogErrorMessage(string message) => Debug.WriteLine($"[Console.WaterWorks] ERROR: {message}.");
}
}

68
Console.Waterworks/Console.Waterworks/Models/Command.cs

@ -1,12 +1,70 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Text.RegularExpressions;
namespace Console.Waterworks.Models
{
class Command
{
public string Name { get; set; }
public string ClassName { get; set; }
private List<string> _arguments;
public IEnumerable<string> Arguments
{
get
{
return _arguments;
}
}
public Command(string input, string commandsNamespace, string className)
{
// Ugly regex to split string on spaces, but preserve quoted text intact:
var stringArray =
Regex.Split(input, "(?<=^[^\"]*(?:\"[^\"]*\"[^\"]*)*) (?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)");
_arguments = new List<string>();
for (int i = 0; i < stringArray.Length; i++)
{
// The first element is always the command:
if (i == 0)
{
Name = stringArray[i];
// Set the class name
ClassName = className;
string[] s = stringArray[0].Split('.');
if (s.Length == 2)
{
ClassName = s[0];
Name = s[1];
}
}
else
{
var inputArgument = stringArray[i];
// Assume that most of the time, the input argument is NOT quoted text:
string argument = inputArgument;
// Is the argument a quoted text string?
var regex = new Regex("\"(.*?)\"", RegexOptions.Singleline);
var match = regex.Match(inputArgument);
// If it IS quoted, there will be at least one capture:
if (match.Captures.Count > 0)
{
// Get the unquoted text from within the qoutes:
var captureQuotedText = new Regex("[^\"]*[^\"]");
var quoted = captureQuotedText.Match(match.Captures[0].Value);
// The argument should include all text from between the quotes
// as a single string:
argument = quoted.Captures[0].Value;
}
_arguments.Add(argument);
}
}
}
}
}

172
Console.Waterworks/Console.Waterworks/Specialists/CoercionSpecialist.cs

@ -1,12 +1,174 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Console.Waterworks.Specialists
{
class CoercionSpecialist
internal static class CoercionSpecialist
{
internal static object CoerceArgument(Type requiredType, string inputValue)
{
var requiredTypeCode = Type.GetTypeCode(requiredType);
string exceptionMessage = $"Cannnot coerce the input argument {inputValue} to required type {requiredType.Name}";
object result = null;
switch (requiredTypeCode)
{
case TypeCode.String:
result = inputValue;
break;
case TypeCode.Int16:
short number16;
if (Int16.TryParse(inputValue, out number16))
{
result = number16;
}
else
{
throw new ArgumentException(exceptionMessage);
}
break;
case TypeCode.Int32:
int number32;
if (Int32.TryParse(inputValue, out number32))
{
result = number32;
}
else
{
throw new ArgumentException(exceptionMessage);
}
break;
case TypeCode.Int64:
long number64;
if (Int64.TryParse(inputValue, out number64))
{
result = number64;
}
else
{
throw new ArgumentException(exceptionMessage);
}
break;
case TypeCode.Boolean:
bool trueFalse;
if (bool.TryParse(inputValue, out trueFalse))
{
result = trueFalse;
}
else
{
throw new ArgumentException(exceptionMessage);
}
break;
case TypeCode.Byte:
byte byteValue;
if (byte.TryParse(inputValue, out byteValue))
{
result = byteValue;
}
else
{
throw new ArgumentException(exceptionMessage);
}
break;
case TypeCode.Char:
char charValue;
if (char.TryParse(inputValue, out charValue))
{
result = charValue;
}
else
{
throw new ArgumentException(exceptionMessage);
}
break;
case TypeCode.DateTime:
DateTime dateValue;
if (DateTime.TryParse(inputValue, out dateValue))
{
result = dateValue;
}
else
{
throw new ArgumentException(exceptionMessage);
}
break;
case TypeCode.Decimal:
Decimal decimalValue;
if (Decimal.TryParse(inputValue, out decimalValue))
{
result = decimalValue;
}
else
{
throw new ArgumentException(exceptionMessage);
}
break;
case TypeCode.Double:
Double doubleValue;
if (Double.TryParse(inputValue, out doubleValue))
{
result = doubleValue;
}
else
{
throw new ArgumentException(exceptionMessage);
}
break;
case TypeCode.Single:
Single singleValue;
if (Single.TryParse(inputValue, out singleValue))
{
result = singleValue;
}
else
{
throw new ArgumentException(exceptionMessage);
}
break;
case TypeCode.UInt16:
UInt16 uInt16Value;
if (UInt16.TryParse(inputValue, out uInt16Value))
{
result = uInt16Value;
}
else
{
throw new ArgumentException(exceptionMessage);
}
break;
case TypeCode.UInt32:
UInt32 uInt32Value;
if (UInt32.TryParse(inputValue, out uInt32Value))
{
result = uInt32Value;
}
else
{
throw new ArgumentException(exceptionMessage);
}
break;
case TypeCode.UInt64:
UInt64 uInt64Value;
if (UInt64.TryParse(inputValue, out uInt64Value))
{
result = uInt64Value;
}
else
{
throw new ArgumentException(exceptionMessage);
}
break;
default:
throw new ArgumentException(exceptionMessage);
}
return result;
}
}
}

52
Console.Waterworks/Console.Waterworks/Specialists/CommandsSpecialist.cs

@ -1,12 +1,60 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Console.Waterworks.Models;
using System.Reflection;
using Console.Waterworks.Assistants;
namespace Console.Waterworks.Specialists
{
class CommandsSpecialist
{
CommandsAssistant Assistant = new CommandsAssistant();
internal List<Type> GetCommandClasses(string commandsNameSpace)
{
string theNamespace = commandsNameSpace;
var q = from t in Assembly.GetEntryAssembly().GetTypes()
where t.IsClass && t.Namespace == theNamespace
select t;
return q.ToList();
}
internal Dictionary<string, Dictionary<string, IEnumerable<ParameterInfo>>> GetCommandLibraries(List<Type> commandClasses)
{
var commandLibraries = new Dictionary<string, Dictionary<string, IEnumerable<ParameterInfo>>>();
foreach (var commandClass in commandClasses)
{
var methods = commandClass.GetMethods(BindingFlags.Static | BindingFlags.Public);
var methodDictionary = new Dictionary<string, IEnumerable<ParameterInfo>>();
foreach (var method in methods)
{
string commandName = method.Name;
methodDictionary.Add(commandName, method.GetParameters());
}
commandLibraries.Add(commandClass.Name, methodDictionary);
}
return commandLibraries;
}
internal string ExecuteCommand(string commandsNamespace, Command command, List<Type> commandClasses, Dictionary<string, Dictionary<string, IEnumerable<ParameterInfo>>> commandLibraries, ConsoleIOSpecialist consoleSpec)
{
var classValidated = Assistant.ValidateClass(command, commandLibraries);
var commandNameValidated = Assistant.ValidateCommand(command, commandLibraries);
Dictionary<string, IEnumerable<ParameterInfo>> methodDictionary;
if (classValidated != true || commandNameValidated != true)
return Assistant.ExecuteBadCommandProcedure(command, consoleSpec);
else
methodDictionary = commandLibraries[command.ClassName];
var paramInfoList = methodDictionary[command.Name].ToList();
var paramsValidated = Assistant.ValidateParamArguments(command, paramInfoList);
if (paramsValidated == false)
return Assistant.ExecuteMissingArgumentProcedure(command, paramInfoList, consoleSpec);
var methodParametreValueList = Assistant.GetParametreValueList(command, paramInfoList);
var typeInfo = Assistant.BuildCommandLibraryClass(command, commandsNamespace);
var inputArguments = Assistant.GetInputArguments(methodParametreValueList);
var result = Assistant.InvokeCommand(command, typeInfo, inputArguments);
return result;
}
}
}

61
Console.Waterworks/Console.Waterworks/Specialists/ConsoleIOSpecialist.cs

@ -1,12 +1,67 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Console.Waterworks.Specialists
{
class ConsoleIOSpecialist
{
string _consolePrompt;
internal void PrepareConsoleEnvironment()
{
#if DEBUG
System.Console.BackgroundColor = ConsoleColor.DarkGray;
System.Console.Clear();
System.Console.ForegroundColor = ConsoleColor.White;
System.Console.WriteLine(" ------------ ");
System.Console.WriteLine("| DEBUG MODE |");
System.Console.WriteLine(" ------------ ");
#endif
}
internal void SetConsoleTitle(string title) => System.Console.Title = title;
internal void SetInputPrompt(string prompt) => _consolePrompt = prompt;
internal void WriteProgramInfo(List<string> programInfo)
{
foreach (var line in programInfo)
{
if (!string.IsNullOrEmpty(line)) System.Console.WriteLine(line);
}
}
internal string GetInputFromUser()
{
System.Console.ForegroundColor = ConsoleColor.Green;
System.Console.Write(_consolePrompt);
System.Console.ResetColor();
return System.Console.ReadLine();
}
internal void WriteOutputToConsole(string message) => System.Console.WriteLine(message);
internal void LineBreak() => System.Console.WriteLine();
internal void WriteErrorSuffix()
{
System.Console.ForegroundColor = ConsoleColor.Red;
System.Console.Write("[ERROR] ");
}
internal void WriteErrorMessage(string message)
{
System.Console.ForegroundColor = ConsoleColor.Red;
System.Console.WriteLine($"[ERROR] {message}");
System.Console.ResetColor();
}
internal void ResetConsoleColour() => System.Console.ResetColor();
internal void WriteInfoSuffix()
{
System.Console.ForegroundColor = ConsoleColor.Yellow;
System.Console.Write("[INFO] ");
}
}
}

59
Console.Waterworks/Console.Waterworks/Specialists/HelpSpecialist.cs

@ -1,12 +1,63 @@
using System;
using Console.Waterworks.Attributes;
using Console.Waterworks.Loggers;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;
namespace Console.Waterworks.Specialists
{
class HelpSpecialist
{
CW_Logger _logger = new CW_Logger();
internal MemberInfo[] GetCommandMembers(List<Type> commandClasses) => commandClasses[0].GetMembers();
internal bool ListCommand(MemberInfo command)
{
var customAttributes = GetCustomAttributes(command);
var castedAttributes = CheckForAttributesType<ListCommandAttribute>(customAttributes);
return (castedAttributes != null) ? castedAttributes.ShowCommand : false;
}
T CheckForAttributesType<T>(object[] attributes)
{
T theAttributes = default(T);
for (int i = 0; i < attributes.Length; i++)
{
try
{
theAttributes = (T)attributes[i];
break;
}
catch (Exception)
{
_logger.LogInfoMessage("The attempted casting attempt failed. Do not panic. This was expected");
}
}
return theAttributes;
}
object[] GetCustomAttributes(MemberInfo command) => command.GetCustomAttributes(true);
internal object GetParametres(MemberInfo command)
{
var attributes = GetCustomAttributes(command);
var castedAttributes = CheckForAttributesType<ParametresAttribute>(attributes);
return (castedAttributes != null) ? castedAttributes.Parametres : "Parametres values could not be found";
}
internal object GetDescription(MemberInfo command)
{
var attributes = GetCustomAttributes(command);
var castedAttributes = CheckForAttributesType<DescriptionAttribute>(attributes);
return (castedAttributes != null) ? castedAttributes.Description : "Description could not be found";
}
internal object GetUsageExamples(MemberInfo command)
{
var attributes = GetCustomAttributes(command);
var castedAttributes = CheckForAttributesType<UsageAttribute>(attributes);
return (castedAttributes != null) ? castedAttributes.UsageExample : "Example could not be found";
}
}
}

66
Console.Waterworks/Console.Waterworks/Specialists/ProgramInfoSpecialist.cs

@ -1,12 +1,70 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;
namespace Console.Waterworks.Specialists
{
class ProgramInfoSpecialist
{
internal List<string> GatherProgramInfomation()
{
var info = new List<string>()
{
addProductLine(),
addCompanyLine(),
addCopyRightLine(),
addProductDescription()
};
return info;
}
private string addCopyRightLine()
{
Assembly assembly = Assembly.GetEntryAssembly();
var copyRightAttribute = assembly
.GetCustomAttributes(typeof(AssemblyCopyrightAttribute), false)
.OfType<AssemblyCopyrightAttribute>()
.FirstOrDefault();
return (copyRightAttribute != null) ? copyRightAttribute.Copyright : null;
}
string addProductLine()
{
var name = GetProductName();
var buildInfo = getBuildInfo();
return (!string.IsNullOrEmpty(name) && !string.IsNullOrEmpty(buildInfo)) ? $"{name} {buildInfo}" : null;
}
string addCompanyLine()
{
Assembly assembly = Assembly.GetEntryAssembly();
var companyAttribute = assembly
.GetCustomAttributes(typeof(AssemblyCompanyAttribute), false)
.OfType<AssemblyCompanyAttribute>()
.FirstOrDefault();
return (companyAttribute != null) ? $"by {companyAttribute.Company}" : null;
}
string addProductDescription()
{
Assembly assembly = Assembly.GetEntryAssembly();
var descriptionAttribute = assembly
.GetCustomAttributes(typeof(AssemblyDescriptionAttribute), false)
.OfType<AssemblyDescriptionAttribute>()
.FirstOrDefault();
return (descriptionAttribute != null) ? descriptionAttribute.Description : null;
}
internal string GetProductName()
{
Assembly assembly = Assembly.GetEntryAssembly();
var productAttribute = assembly
.GetCustomAttributes(typeof(AssemblyProductAttribute), false)
.OfType<AssemblyProductAttribute>()
.FirstOrDefault();
return (productAttribute != null) ? productAttribute.Product : null;
}
string getBuildInfo() => Assembly.GetEntryAssembly().GetName().Version.ToString();
}
}

Loading…
Cancel
Save