private static Context ParseArgs(string[] args)
        {
            var context = new Context();

            var options = new[]
            {
                new CommandLineOption {
                    Key = nameof(context.AssemblyFolder), Setter = value => context.AssemblyFolder = value, Getter = () => context.AssemblyFolder, Description = "Path to the folder containing the plugin."
                },
                new CommandLineOption {
                    Key = nameof(context.AssemblyPath), Setter = value => context.AssemblyPath = value, Getter = () => context.AssemblyPath, Description = "Path to the plugin assembly."
                },
                new CommandLineOption {
                    Key = nameof(context.OutputPath), Setter = value => context.OutputPath = value, Getter = () => context.OutputPath, Description = "Path to packaged output file."
                },
                new CommandLineOption {
                    Key = nameof(context.DeployedFolderName), Setter = value => context.DeployedFolderName = value, Getter = () => context.DeployedFolderName, Description = "Name of the deployed folder"
                },
                new CommandLineOption {
                    Key = nameof(context.Description), Setter = value => context.Description = value, Getter = () => context.Description, Description = "Description of the plugin"
                },
                new CommandLineOption {
                    Key = nameof(context.AssemblyQualifiedTypeName), Setter = value => context.AssemblyQualifiedTypeName = value, Getter = () => context.AssemblyQualifiedTypeName, Description = "Assembly-qualified type name of the plugin"
                },
                new CommandLineOption {
                    Key = nameof(context.Subfolders), Setter = value => context.Subfolders = bool.Parse(value), Getter = () => context.Subfolders.ToString(), Description = "Include all subfolders"
                },
                new CommandLineOption {
                    Key = nameof(context.Include), Setter = value => AddToList(value, context.Include), Getter = () => string.Join(", ", context.Include), Description = "Include file or DOS wildcard pattern"
                },
                new CommandLineOption {
                    Key = nameof(context.Exclude), Setter = value => AddToList(value, context.Exclude), Getter = () => string.Join(", ", context.Exclude), Description = "Exclude file or DOS wildcard pattern"
                },
            };

            var usageMessage = CommandLineUsage.ComposeUsageText(
                "Package a field data plugin into a deployable .plugin file.", options);

            var optionResolver = new CommandLineOptionResolver();

            optionResolver.Resolve(args, options, usageMessage, arg => ResolvePositionalArgument(context, arg));

            if (string.IsNullOrEmpty(context.AssemblyFolder) && string.IsNullOrEmpty(context.AssemblyPath))
            {
                throw new ExpectedException($"You must specify at least one /{nameof(context.AssemblyPath)} or /{nameof(context.AssemblyFolder)} option.");
            }

            if (string.IsNullOrEmpty(context.OutputPath))
            {
                throw new ExpectedException($"You must specify the /{nameof(context.OutputPath)} option.");
            }

            return(context);
        }
        private void ParseArgs(string[] args)
        {
            var options = new[]
            {
                new CommandLineOption {
                    Key = "Plugin", Setter = value => Context.PluginPath = value, Getter = () => Context.PluginPath, Description = "Path to the plugin assembly to debug"
                },
                new CommandLineOption {
                    Key = "Data", Setter = value => AddDataPath(Context, value), Getter = () => string.Empty, Description = "Path to the data file to be parsed. Can be set more than once."
                },
                new CommandLineOption {
                    Key = nameof(Context.RecursiveSearch), Setter = value => Context.RecursiveSearch = bool.Parse(value), Getter = () => $"{Context.RecursiveSearch}", Description = "Search /Data directories recursively. -R shortcut is also supported."
                },
                new CommandLineOption {
                    Key = "Location", Setter = value => Context.LocationIdentifier = value, Getter = () => Context.LocationIdentifier, Description = "Optional location identifier context"
                },
                new CommandLineOption {
                    Key = "UtcOffset", Setter = value => Context.LocationUtcOffset = TimeSpan.Parse(value), Getter = () => Context.LocationUtcOffset.ToString(), Description = "UTC offset in .NET TimeSpan format."
                },
                new CommandLineOption {
                    Key = "Json", Setter = value => Context.JsonPath = value, Getter = () => Context.JsonPath, Description = "Optional path to write the appended results as JSON"
                },
                new CommandLineOption {
                    Key = "Setting", Setter = value => AddSetting(Context, value), Getter = () => string.Empty, Description = "Supply plugin settings as 'key=text' or 'key=@pathToTextFile' values."
                },
                new CommandLineOption {
                    Key = "ExpectedError", Setter = value => Context.ExpectedError = value, Getter = () => Context.ExpectedError, Description = "Expected error message"
                },
                new CommandLineOption {
                    Key = "ExpectedStatus", Setter = value => Context.ExpectedStatus = (ParseFileStatus)Enum.Parse(typeof(ParseFileStatus), value, true), Getter = () => Context.ExpectedStatus.ToString(), Description = $"Expected parse status. One of {string.Join(", ", Enum.GetNames(typeof(ParseFileStatus)))}"
                },
            };

            var usageMessage = CommandLineUsage.ComposeUsageText(
                "Parse a file using a field data plugin, logging the results.", options);

            var optionResolver = new CommandLineOptionResolver();

            optionResolver.Resolve(args, options, usageMessage, arg => PositionalArgumentResolver(Context, arg));

            if (string.IsNullOrEmpty(Context.PluginPath))
            {
                throw new ExpectedException("No plugin assembly specified.");
            }

            if (!Context.DataPaths.Any())
            {
                throw new ExpectedException("No data file specified.");
            }
        }
        private void ParseArgs(string[] args)
        {
            var options = new[]
            {
                new CommandLineOption {
                    Description = "Specify the plugin to be tested"
                },
                new CommandLineOption
                {
                    Key         = "Plugin",
                    Setter      = value => Context.PluginPath = value,
                    Getter      = () => Context.PluginPath,
                    Description = "Path to the plugin assembly. Can be a folder, a DLL, or a packaged *.plugin file."
                },
                new CommandLineOption
                {
                    Key         = nameof(Context.Verbose),
                    Setter      = value => Context.Verbose = bool.Parse(value),
                    Getter      = () => $"{Context.Verbose}",
                    Description = "Enables verbose logging of assembly loading logic."
                },
                new CommandLineOption
                {
                    Key         = nameof(Context.FrameworkAssemblyPath),
                    Setter      = value => Context.FrameworkAssemblyPath = value,
                    Getter      = () => Context.FrameworkAssemblyPath,
                    Description = "Optional path to the FieldDataPluginFramework.dll assembly. [default: Test using the latest framework version]"
                },
                new CommandLineOption(), new CommandLineOption {
                    Description = "Test data settings"
                },
                new CommandLineOption
                {
                    Key         = "Data",
                    Setter      = value => AddDataPath(Context, value),
                    Getter      = () => string.Empty,
                    Description = "Path to the data file to be parsed. Can be set more than once."
                },
                new CommandLineOption
                {
                    Key         = nameof(Context.RecursiveSearch),
                    Setter      = value => Context.RecursiveSearch = bool.Parse(value),
                    Getter      = () => $"{Context.RecursiveSearch}",
                    Description = "Search /Data directories recursively. -R shortcut is also supported."
                },
                new CommandLineOption
                {
                    Key         = "Setting",
                    Setter      = value => AddSetting(Context, value),
                    Getter      = () => string.Empty,
                    Description = "Supply plugin settings as 'key=text' or 'key=@pathToTextFile' values."
                },
                new CommandLineOption(), new CommandLineOption {
                    Description = "Plugin context settings"
                },
                new CommandLineOption
                {
                    Key         = "Location",
                    Setter      = value => Context.LocationIdentifier = value,
                    Getter      = () => Context.LocationIdentifier,
                    Description = "Optional location identifier context"
                },
                new CommandLineOption
                {
                    Key         = "UtcOffset",
                    Setter      = value => Context.LocationUtcOffset = TimeSpan.Parse(value),
                    Getter      = () => Context.LocationUtcOffset.ToString(),
                    Description = "UTC offset in .NET TimeSpan format."
                },
                new CommandLineOption(), new CommandLineOption {
                    Description = "Output settings"
                },
                new CommandLineOption
                {
                    Key         = "Json",
                    Setter      = value => Context.JsonPath = value,
                    Getter      = () => Context.JsonPath,
                    Description = "Optional path (file or folder) to write the appended results as JSON."
                },
                new CommandLineOption(), new CommandLineOption {
                    Description = "Expected response settings"
                },
                new CommandLineOption
                {
                    Key         = nameof(Context.ExpectedError),
                    Setter      = value => Context.ExpectedError = value,
                    Getter      = () => Context.ExpectedError,
                    Description = "Expected error message"
                },
                new CommandLineOption
                {
                    Key         = nameof(Context.ExpectedStatus),
                    Setter      = value => Context.ExpectedStatus = (StatusType)Enum.Parse(typeof(StatusType), value, true),
                    Getter      = () => Context.ExpectedStatus.ToString(),
                    Description = $"Expected parse status. One of {string.Join(", ", Enum.GetNames(typeof(StatusType)))}"
                },
            };

            var usageMessage = CommandLineUsage.ComposeUsageText(
                "Parse a file using a field data plugin, logging the results.", options);

            var optionResolver = new CommandLineOptionResolver();

            optionResolver.Resolve(args, options, usageMessage, arg => PositionalArgumentResolver(Context, arg));

            if (string.IsNullOrEmpty(Context.PluginPath))
            {
                throw new ExpectedException("No plugin assembly specified.");
            }

            if (!Context.DataPaths.Any())
            {
                throw new ExpectedException("No data file specified.");
            }
        }
Пример #4
0
        public static Context GetContext(Context context, string[] args)
        {
            context.LocationAliases.Clear();

            var options = new[]
            {
                new CommandLineOption {
                    Description = "AQTS connection settings"
                },
                new CommandLineOption
                {
                    Key         = nameof(context.Server),
                    Setter      = value => context.Server = value,
                    Getter      = () => context.Server,
                    Description = "The AQTS app server."
                },
                new CommandLineOption
                {
                    Key         = nameof(context.Username),
                    Setter      = value => context.Username = value,
                    Getter      = () => context.Username,
                    Description = "AQTS username."
                },
                new CommandLineOption
                {
                    Key         = nameof(context.Password),
                    Setter      = value => context.Password = value,
                    Getter      = () => context.Password,
                    Description = "AQTS credentials."
                },
                new CommandLineOption
                {
                    Key         = nameof(context.MaximumConnectionAttempts),
                    Setter      = value => context.MaximumConnectionAttempts = int.Parse(value),
                    Getter      = () => context.MaximumConnectionAttempts.ToString(),
                    Description = "The maximum number of connection attempts before exiting."
                },
                new CommandLineOption
                {
                    Key         = nameof(context.ConnectionRetryDelay),
                    Setter      = value => context.ConnectionRetryDelay = TimeSpan.Parse(value),
                    Getter      = () => context.ConnectionRetryDelay.ToString(),
                    Description = "The TimeSpan to wait in between AQTS connection attempts."
                },
                new CommandLineOption
                {
                    Key         = nameof(context.MaximumConcurrentRequests),
                    Setter      = value => context.MaximumConcurrentRequests = int.Parse(value),
                    Getter      = () => context.MaximumConcurrentRequests.ToString(),
                    Description = "Maximum concurrent requests during field visit import."
                },

                new CommandLineOption(), new CommandLineOption {
                    Description = "Visit merge settings"
                },
                new CommandLineOption
                {
                    Key         = nameof(context.MergeMode),
                    Setter      = value => context.MergeMode = ParseEnum <MergeMode>(value),
                    Getter      = () => context.MergeMode.ToString(),
                    Description = $"One of {DescribeEnumValues<MergeMode>()}."
                },
                new CommandLineOption
                {
                    Key         = nameof(context.OverlapIncludesWholeDay),
                    Setter      = value => context.OverlapIncludesWholeDay = bool.Parse(value),
                    Getter      = () => context.OverlapIncludesWholeDay.ToString(),
                    Description = $"True if a conflict includes any visit on same day. False can generate multiple visits on the same day."
                },
                new CommandLineOption
                {
                    Key         = nameof(context.MaximumVisitDuration),
                    Setter      = value => context.MaximumVisitDuration = TimeSpan.Parse(value),
                    Getter      = () => context.MaximumVisitDuration.ToString(),
                    Description = "Maximum visit duration. Visits exceeding this duration will not be imported."
                },
                new CommandLineOption
                {
                    Key         = nameof(context.DryRun),
                    Setter      = value => context.DryRun = bool.Parse(value),
                    Getter      = () => context.DryRun.ToString(),
                    Description = $"True if no visits will be imported. Use /N as a shortcut."
                },

                new CommandLineOption(), new CommandLineOption {
                    Description = "Location alias settings"
                },
                new CommandLineOption
                {
                    Key         = nameof(context.LocationAliases),
                    Setter      = value => ParseLocationAliases(context, value),
                    Getter      = () => string.Empty,
                    Description = $"A list of location aliases, in alias=locationIdentifier syntax."
                },

                new CommandLineOption(), new CommandLineOption {
                    Description = "Plugin configuration settings"
                },
                new CommandLineOption
                {
                    Key         = nameof(context.PluginSettings),
                    Setter      = value => AddSetting(context, value),
                    Getter      = () => string.Empty,
                    Description = $"Configure plugin settings as 'pluginFolderName=key=text' or 'pluginFolderName=key=@pathToTextFile' values."
                },
                new CommandLineOption
                {
                    Key         = nameof(context.PluginPriority),
                    Setter      = value => AddPluginPriority(context, value),
                    Getter      = () => string.Empty,
                    Description = $"Configure plugin priority as 'pluginFolderName=integerPriority' [defaults to the AQTS plugin priority]"
                },
                new CommandLineOption
                {
                    Key         = nameof(context.Verbose),
                    Setter      = value => context.Verbose = bool.Parse(value),
                    Getter      = () => $"{context.Verbose}",
                    Description = "Enables verbose logging of plugin assembly loading logic."
                },

                new CommandLineOption(), new CommandLineOption {
                    Description = "File monitoring settings"
                },
                new CommandLineOption
                {
                    Key         = nameof(context.HotFolderPath),
                    Setter      = value => context.HotFolderPath = value,
                    Getter      = () => context.HotFolderPath,
                    Description = "The root path to monitor for field visit files."
                },
                new CommandLineOption
                {
                    Key         = nameof(context.FileMask),
                    Setter      = value => context.FileMask = value,
                    Getter      = () => context.FileMask,
                    Description = "A comma-separated list of file patterns to monitor. [defaults to '*.*' if omitted]"
                },
                new CommandLineOption
                {
                    Key         = nameof(context.FileQuietDelay),
                    Setter      = value => context.FileQuietDelay = TimeSpan.Parse(value),
                    Getter      = () => context.FileQuietDelay.ToString(),
                    Description = "Timespan of no file activity before processing begins."
                },
                new CommandLineOption
                {
                    Key         = nameof(context.FileScanInterval),
                    Setter      = value => context.FileScanInterval = TimeSpan.Parse(value),
                    Getter      = () => context.FileScanInterval.ToString(),
                    Description = "Maximum timespan between scanning for new files."
                },
                new CommandLineOption
                {
                    Key         = nameof(context.ProcessingFolder),
                    Setter      = value => context.ProcessingFolder = value,
                    Getter      = () => context.ProcessingFolder,
                    Description = "Move files to this folder during processing."
                },
                new CommandLineOption
                {
                    Key         = nameof(context.UploadedFolder),
                    Setter      = value => context.UploadedFolder = value,
                    Getter      = () => context.UploadedFolder,
                    Description = "Move files to this folder after successful uploads."
                },
                new CommandLineOption
                {
                    Key         = nameof(context.PartialFolder),
                    Setter      = value => context.PartialFolder = value,
                    Getter      = () => context.PartialFolder,
                    Description = "Move files to this folder if when partial uploads are performed to avoid duplicates."
                },
                new CommandLineOption
                {
                    Key         = nameof(context.ArchivedFolder),
                    Setter      = value => context.ArchivedFolder = value,
                    Getter      = () => context.ArchivedFolder,
                    Description = $"Any visits replaced via /{nameof(context.MergeMode)}={MergeMode.ArchiveAndReplace} will be archived here before being replace with new visits."
                },
                new CommandLineOption
                {
                    Key         = nameof(context.FailedFolder),
                    Setter      = value => context.FailedFolder = value,
                    Getter      = () => context.FailedFolder,
                    Description = "Move files to this folder if an upload error occurs."
                },
                new CommandLineOption
                {
                    Key         = nameof(context.MaximumFileCount),
                    Setter      = value => context.MaximumFileCount = int.Parse(value),
                    Getter      = () => $"{context.MaximumFileCount}",
                    Description = "Maximum number of files to process before exiting. [default: Keep running forever]"
                },
                new CommandLineOption
                {
                    Key         = nameof(context.MaximumFileWaitInterval),
                    Setter      = value => context.MaximumFileWaitInterval = TimeSpan.Parse(value),
                    Getter      = () => $"{context.MaximumFileWaitInterval}",
                    Description = "Maximum TimeSpan to wait for new files before exiting. [default: Keep running forever]"
                },
                new CommandLineOption
                {
                    Key         = nameof(context.MaximumDuplicateRetry),
                    Setter      = value => context.MaximumDuplicateRetry = int.Parse(value),
                    Getter      = () => $"{context.MaximumDuplicateRetry}",
                    Description = "Maximum number of retries for duplicate visits."
                },
                new CommandLineOption(), new CommandLineOption {
                    Description = "Export settings"
                },
                new CommandLineOption
                {
                    Key         = nameof(context.ExportFolder),
                    Setter      = value => context.ExportFolder = value,
                    Getter      = () => context.ExportFolder,
                    Description = "Export visits to this root folder."
                },
                new CommandLineOption
                {
                    Key         = nameof(context.ExportLocations),
                    Setter      = value => ParseExportLocations(context, value),
                    Description = "Export only these locations [default: All locations]"
                },
                new CommandLineOption
                {
                    Key         = nameof(context.ExportBefore),
                    Setter      = value => context.ExportBefore = ParseDateTimeOffset(value),
                    Description = "Export existing visits before this time."
                },
                new CommandLineOption
                {
                    Key         = nameof(context.ExportAfter),
                    Setter      = value => context.ExportAfter = ParseDateTimeOffset(value),
                    Description = "Export existing visits after this time."
                },
                new CommandLineOption
                {
                    Key         = nameof(context.ExportOverwrite),
                    Setter      = value => context.ExportOverwrite = bool.Parse(value),
                    Getter      = () => context.ExportOverwrite.ToString(),
                    Description = $"When true, any already exported visits will be re-exported."
                },
                new CommandLineOption
                {
                    Key         = nameof(context.ExportUtcOverride),
                    Setter      = value => context.ExportUtcOverride = ParseUtcOffset(value),
                    Getter      = () => context.ExportUtcOverride.ToString(),
                    Description = $"When set, change all timestamps in exported visits to the specific UTC offset. Supported formats: ±HH, ±HHmm, ±HH:mm."
                },
            };

            var usageMessage = CommandLineUsage.ComposeUsageText(
                "Purpose: Monitors a folder for field visit files and appends them to an AQTS app server", options);

            var optionResolver = new CommandLineOptionResolver();

            optionResolver.Resolve(InjectOptionsFileByDefault(args), options, usageMessage, arg => ResolvePositionalArgument(context, arg));

            ValidateContext(context);

            return(context);
        }