| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using Quadarax.Foundation.Common.Console;
- using Quadarax.Foundation.Common.Value;
- using Quadarax.Foundation.QConsole.Argument;
- using Quadarax.Foundation.QConsole.Context;
- using Quadarax.Foundation.QConsole.Extensions;
- namespace Quadarax.Foundation.QConsole.Command.Base
- {
- public abstract class AbstractCommand
- {
- #region *** Private Fields ***
- private Engine _engine;
- private IDictionary<string, AbstractArgument> _arguments;
- protected ICommandContext _context;
- #endregion
- #region *** Properties ***
- public abstract string Name { get; }
- public abstract string Description { get; }
- public AbstractArgument[] Arguments => _arguments.Values.ToArray();
- protected Engine Engine => _engine;
- #endregion
- #region *** Constructor ***
- public AbstractCommand(Engine engine)
- {
- _engine = engine ?? throw new ArgumentNullException(nameof(engine));
- _arguments = new Dictionary<string, AbstractArgument>();
- _context = _engine.Context.CreateCommandContext();
- WriteDebugInfo($"Context for command '{Name}' created: {_context}");
- var args = SetupArguments();
- foreach (var arg in args)
- _arguments.Add(arg.Code, arg);
- Init();
- WriteDebugInfo($"Command '{Name}' has {_arguments.Count} arguments. Initialized.");
- }
- #endregion
- #region *** Public operations ***
- public Result Execute(string input)
- {
- ConsoleWriter writer = null;
- try
- {
- writer = new ConsoleWriter(ConsoleColor.Green);
- foreach (var arg in Arguments)
- arg.SetValueAsDefault();
- ParseInput(input);
- if (_engine.Configuration.ShowStatusOnEveryCommand)
- ShowContextStatus(writer);
- var result = OnExecute();
- result = EndExecute(result);
-
- return result;
- }
- catch (Exception e)
- {
- return new Result(e);
- }
- finally
- {
- writer?.Dispose();
- }
- }
- public override string ToString()
- {
- return "Command: " + Name;
- }
- #endregion
- #region *** Private operations ***
- private void Init()
- {
- OnCommandInit();
- }
- private void ParseInput(string input)
- {
- //var args = input.Split(new[] {Engine.Configuration.CharacterNamedArgumentSeparator}, StringSplitOptions.RemoveEmptyEntries);
- var args = Split(input, Engine.Configuration.CharacterTextValueBraceSeparator, new[]
- {
- Engine.Configuration.CharacterNamedArgumentSeparator,
- Engine.Configuration.CharacterOrdinalArgumentSeparator
- });
- for (int i = 1; i < args.Length; i++)
- {
- var arg = args[i];
- var index = i - 1;
- WriteDebugInfo($"Parsing argument [index={index}] by value string '{arg}' in progress..");
- AbstractArgument argument = null;
- if (arg.StartsWith(Engine.Configuration.CharacterNamedArgumentSeparator))
- {
- //Named
- WriteDebugInfo("Detects argument as named.");
- var parsed = ParseNamedArgument(arg);
- if (!ContainsArgument(parsed.Item1))
- throw new Exception(
- $"Invalid argument '{Engine.Configuration.CharacterNamedArgumentSeparator}{parsed.Item1}' for this command.");
- argument = GetArgument(parsed.Item1);
- if (argument.IsPositional())
- if (!((OrdinalArgument)argument).IsCodeAllowed)
- throw new Exception($"Usage of ordinal argument '{argument.Code}' as named argument is not allowed!");
- if (argument.IsFlag())
- ((FlagArgument)argument).Set();
- else
- argument.Value.Set(parsed.Item2);
- }
- else
- {
- //Ordinal
- WriteDebugInfo("Detects argument as ordinal.");
- argument = GetArgument(index);
- if (argument == null)
- throw new Exception(
- $"Invalid ordinal argument '{arg}' at position {index} for this command.");
- argument.Value.Set(arg);
- WriteDebugInfo($"Ordinal argument '{argument.Code}' is set to value '{argument.Value.AsString()}'.");
- }
- }
- }
- private Tuple<string, string> ParseNamedArgument(string argument)
- {
- try
- {
- var argParts = argument.Split(new[] {Engine.Configuration.CharacterNamedArgumentValueSeparator}, StringSplitOptions.RemoveEmptyEntries);
- WriteDebugInfo($"Splitting arg-parts '{argument}' to parts (count={argParts.Length}): {string.Join(",",argParts)}");
- var argName = argParts[0].Replace(Engine.Configuration.CharacterNamedArgumentSeparator,string.Empty);
- var argValue = argParts.Length > 1 ? argParts[1] : string.Empty;
- WriteDebugInfo($"Named argument '{argument}' parsed as name='{argName}'; value='{argValue}'.");
- return new Tuple<string, string>(argName, argValue);
- }
- catch (Exception e)
- {
- WriteDebugInfo($"Error during parsing named argument '{argument}'.");
- throw new Exception($"Argument '{argument}' parsing error.", e);
- }
-
- }
- private string[] Split(string input, string valueBracket, string[] separators)
- {
- var result = new List<string>();
- var trimedInput = input.Trim();
- if (string.IsNullOrEmpty(trimedInput))
- return result.ToArray();
- var cValueBracked = valueBracket.ToCharArray().First();
- var cSeparators = separators.Select(x => x.ToCharArray().First());
- var nIndexStart = 0;
- var nIndexEnd = 0;
- var isInsideBracked = false;
- int offset = 0;
- for (offset = 0; offset < trimedInput.Length; offset++)
- {
- var current = trimedInput[offset];
- // current | isInside | Result
- // 1 1 0
- // 1 0 1
- // 0 1 1
- // 0 0 0
- isInsideBracked = current == cValueBracked ^ isInsideBracked;
- if (isInsideBracked)
- continue;
- if (cSeparators.Contains(current))
- {
- nIndexEnd = offset;
- result.Add(trimedInput.Substring(nIndexStart,nIndexEnd - nIndexStart));
- nIndexStart = nIndexEnd;
- isInsideBracked = false;
- }
- }
- if (offset>nIndexStart)
- result.Add(trimedInput.Substring(nIndexStart,offset - nIndexStart));
- return result.Where(x => !string.IsNullOrEmpty(x.Trim())).Select(x=>x.Trim()).ToArray();
- }
- private IEnumerable<AbstractArgument> SetupArguments()
- {
- return OnSetupArguments();
- }
- protected void WriteDebugInfo(string text)
- {
- using (var debug = new DebugConsoleWriter())
- {
- debug.WriteDebugLine(text);
- }
- }
- protected void WriteInfo(string text)
- {
- using (var writer = new ConsoleWriter(ConsoleColor.Green))
- writer.WriteLine(text);
- }
- protected void WriteCaption(string text)
- {
- using (var writer = new ConsoleWriter(ConsoleColor.White))
- writer.WriteLine(text);
- }
- protected void WriteWarning(string text)
- {
- using (var writer = new ConsoleWriter(ConsoleColor.Yellow))
- writer.WriteLine(text);
- }
- private void ShowContextStatus(ConsoleWriter writer)
- {
- using (var writerBlue = new ConsoleWriter(ConsoleColor.Blue))
- {
- using (var writerYellow = new ConsoleWriter(ConsoleColor.Magenta))
- {
- writer.WriteLine("Engine context:");
- writerBlue.Write(_engine.Context.ToString()).Write(" : ");
- writerYellow.WriteLine(_engine.Context.Status);
- writer.WriteLine("Command context:");
- writerBlue.Write(_context.ToString()).Write(" : ");
- writerYellow.WriteLine(_context.Status);
- }
- }
- }
- #endregion
- #region *** Protected virtuals ***
- protected virtual void OnCommandInit()
- {
- WriteDebugInfo("Command called OnCommandInit.");
- }
- protected virtual IEnumerable<AbstractArgument> OnSetupArguments()
- {
- return new AbstractArgument[0];
- //{
- // new FlagArgument(Constants.Arguments.General.DebugMode.Code, Constants.Arguments.General.DebugMode.Description, Constants.Arguments.General.DebugMode.Hint, true),
- //};
- }
-
- protected abstract Result OnExecute();
- protected virtual Result EndExecute(Result incommingResult)
- {
- return incommingResult;
- }
- #endregion
- #region *** Protected operations ***
- protected AbstractArgument GetArgument(string code)
- {
- if (!_arguments.ContainsKey(code))
- throw new Exception($"Argument '{code}' is not defined.");
- return _arguments[code];
- }
- protected AbstractArgument GetArgument(int ordinalPosition)
- {
- return _arguments.Values.Where(x => x.IsPositional()).Skip(ordinalPosition).FirstOrDefault();
- }
- protected bool ContainsArgument(string code)
- {
- return _arguments.ContainsKey(code);
- }
- protected TContext GetContext<TContext>() where TContext : class, ICommandContext
- {
- return (TContext)_context;
- }
- #endregion
- }
- }
|