Пример #1
0
        private bool DoesSpecificVisitMatch(VisitIdentifier specificVisit, Visit visit)
        {
            if (specificVisit.StartDateTime.TimeOfDay == TimeSpan.Zero)
            {
                return(visit.StartDate.Date == specificVisit.StartDateTime.Date);
            }

            return(visit.StartDate == specificVisit.StartDateTime);
        }
Пример #2
0
        private static Context ParseArgs(string[] args)
        {
            var context = new Context();

            var resolvedArgs = args
                               .SelectMany(ResolveOptionsFromFile)
                               .ToArray();

            var options = new[]
            {
                new Option {
                    Key = nameof(context.Server), Setter = value => context.Server = value, Getter = () => context.Server, Description = "The AQTS app server."
                },
                new Option {
                    Key = nameof(context.Username), Setter = value => context.Username = value, Getter = () => context.Username, Description = "AQTS username."
                },
                new Option {
                    Key = nameof(context.Password), Setter = value => context.Password = value, Getter = () => context.Password, Description = "AQTS credentials."
                },
                new Option {
                    Key = nameof(context.SessionToken), Setter = value => context.SessionToken = value, Getter = () => context.SessionToken
                },
                new Option {
                    Key = nameof(context.SkipConfirmation), Setter = value => context.SkipConfirmation = bool.Parse(value), Getter = () => context.SkipConfirmation.ToString(), Description = "When true, skip the confirmation prompt. '/Y' is a shortcut for this option."
                },
                new Option {
                    Key = nameof(context.DryRun), Setter = value => context.DryRun = bool.Parse(value), Getter = () => context.DryRun.ToString(), Description = "When true, don't make any changes. '/N' is a shortcut for this option."
                },
                new Option {
                    Key = nameof(context.RecreateLocations), Setter = value => context.RecreateLocations = bool.Parse(value), Getter = () => context.RecreateLocations.ToString(), Description = "When true, recreate the location with the same properties."
                },
                new Option {
                    Key = "Location", Setter = value => context.LocationsToDelete.Add(value), Getter = () => string.Join(", ", context.LocationsToDelete), Description = "Locations to delete."
                },
                new Option {
                    Key = "TimeSeries", Setter = value => context.TimeSeriesToDelete.Add(value), Getter = () => string.Join(", ", context.TimeSeriesToDelete), Description = "Time-series to delete."
                },
                new Option {
                    Key = "RatingModel", Setter = value => context.RatingModelsToDelete.Add(value), Getter = () => string.Join(", ", context.RatingModelsToDelete), Description = "Rating models to delete."
                },
                new Option {
                    Key = "Visit", Setter = value => context.VisitsToDelete.Add(value), Getter = () => string.Join(", ", context.VisitsToDelete), Description = "Visits to delete."
                },
                new Option {
                    Key = nameof(context.VisitsBefore), Setter = value => context.VisitsBefore = ParseDateTime(value), Getter = () => context.VisitsBefore?.ToString("O"), Description = "Delete all visits in matching locations before and including this date."
                },
                new Option {
                    Key = nameof(context.VisitsAfter), Setter = value => context.VisitsAfter = ParseDateTime(value), Getter = () => context.VisitsAfter?.ToString("O"), Description = "Delete all visits in matching locations after and including this date."
                },
            };

            var usageMessage
                = $"Deletes locations, time-series, rating models, and/or field visits from an AQTS server."
                  + $"\n"
                  + $"\nusage: {GetProgramName()} [-option=value] [@optionsFile] [location] [time-series] [rating model] [specific-visit] ..."
                  + $"\n"
                  + $"\nSupported -option=value settings (/option=value works too):\n\n  -{string.Join("\n  -", options.Select(o => o.UsageText()))}"
                  + $"\n"
                  + $"\nUse the @optionsFile syntax to read more options from a file."
                  + $"\n"
                  + $"\n  Each line in the file is treated as a command line option."
                  + $"\n  Blank lines and leading/trailing whitespace is ignored."
                  + $"\n  Comment lines begin with a # or // marker."
                  + $"\n"
                  + $"\nLocation deletion:"
                  + $"\n================="
                  + $"\nLocations can be specified by either location identifier or location unique ID."
                  + $"\nLocation identifiers are matched case-insensitively."
                  + $"\nPublish API wildcard expansion of '*' is supported. '02*' will match locations beginning with '02'."
                  + $"\n"
                  + $"\nTime-series deletion:"
                  + $"\n====================="
                  + $"\nTime-series can specified by identifier or by time-series unique ID."
                  + $"\n"
                  + $"\nRating model deletion:"
                  + $"\n====================="
                  + $"\nRating models can specified by identifier."
                  + $"\n"
                  + $"\nField-visit deletion:"
                  + $"\n====================="
                  + $"\nVisits can be specified by locationIdentifier@date, or locationIdentifier@dateAndTime."
                  + $"\n"
                  + $"\nWhen locationIdentifier@date is used, all visits starting on the date will be deleted."
                  + $"\nWhen locationIdentifier@dateAndTime is used, only visits starting at the exact date and time will be deleted."
                  + $"\n"
                  + $"\nWhen the /{nameof(context.VisitsBefore)}= or /{nameof(context.VisitsAfter)}= options are given, all the visits falling within the time-range will be deleted."
                  + $"\nIf no locations are specified when deleting field visits, visits from all locations will be considered."
                ;

            foreach (var arg in resolvedArgs)
            {
                var match = ArgRegex.Match(arg);

                if (!match.Success)
                {
                    if (arg.StartsWith("/") || arg.StartsWith("-"))
                    {
                        var keyword = arg.Substring(1);

                        if (keyword.Equals("y", StringComparison.InvariantCultureIgnoreCase))
                        {
                            context.SkipConfirmation = true;
                            continue;
                        }

                        if (keyword.Equals("n", StringComparison.InvariantCultureIgnoreCase))
                        {
                            context.DryRun = true;
                            continue;
                        }

                        throw new ExpectedException($"Unknown argument: {arg}\n\n{usageMessage}");
                    }

                    if (RatingModelIdentifier.TryParse(arg, out _))
                    {
                        context.RatingModelsToDelete.Add(arg);
                        continue;
                    }

                    if (TimeSeriesIdentifier.TryParse(arg, out _))
                    {
                        context.TimeSeriesToDelete.Add(arg);
                        continue;
                    }

                    if (VisitIdentifier.TryParse(arg, out _))
                    {
                        context.VisitsToDelete.Add(arg);
                        continue;
                    }

                    // Otherwise assume it is a location to delete
                    context.LocationsToDelete.Add(arg);
                    continue;
                }

                var key   = match.Groups["key"].Value.ToLower();
                var value = match.Groups["value"].Value;

                var option = options.FirstOrDefault(o => o.Key.Equals(key, StringComparison.InvariantCultureIgnoreCase));

                if (option == null)
                {
                    throw new ExpectedException($"Unknown -option=value: {arg}\n\n{usageMessage}");
                }

                option.Setter(value);
            }

            if (string.IsNullOrWhiteSpace(context.Server))
            {
                throw new ExpectedException("No AQTS server specified. See /help or -help for details");
            }

            if (string.IsNullOrWhiteSpace(context.SessionToken) && (string.IsNullOrWhiteSpace(context.Username) || string.IsNullOrWhiteSpace(context.Password)))
            {
                throw new ExpectedException("Valid AQTS credentials must be supplied.");
            }

            if (!context.LocationsToDelete.Any() &&
                !context.TimeSeriesToDelete.Any() &&
                !context.RatingModelsToDelete.Any() &&
                !context.VisitsToDelete.Any() &&
                !context.VisitsAfter.HasValue &&
                !context.VisitsBefore.HasValue)
            {
                throw new ExpectedException($"You must specify something to delete. See /help or -help for details.");
            }

            return(context);
        }
Пример #3
0
        public static bool TryParse(string text, out VisitIdentifier visitIdentifier)
        {
            visitIdentifier = VisitIdentifierParser.ParseIdentifier(text);

            return(visitIdentifier != null);
        }