public void CanGetExistingFeaturesFastEnough()
        {
            IFeatureWorkspace ws = OpenTestWorkspace();
            IFeatureClass     fc = ws.OpenFeatureClass("TOPGIS_TLM.TLM_STRASSE");

            const int count = 100;
            IDictionary <int, IRow> rows = GetFirstNRows((ITable)fc, count);

            var watch = new Stopwatch();

            watch.Start();

            foreach (int oid in rows.Keys)
            {
                Assert.NotNull(GdbQueryUtils.GetFeature(fc, oid));
                _msg.Info($"Oid {oid} time: {watch.ElapsedMilliseconds}");
            }

            watch.Stop();

            double msPerIteration = watch.ElapsedMilliseconds / (double)rows.Count;

            _msg.InfoFormat(@"GetFeature() per iteration: {0} ms", msPerIteration);

            Assert.True(msPerIteration < 50,
                        "GetFeature with existing feature takes too long ({0} ms)",
                        msPerIteration);
        }
        public void FilterLogs(object parameter)
        {
            //var type = (string)parameter;

            // TODO filter log list or log4net has built in option?
            //filtereMessagedList = LogMessageList.Where(t => t.Type == LogType.Debug)

            if (DebugLogsAreVisible)
            {
                _disabledLogTypes.Remove(LogType.Debug);
            }
            else
            {
                _disabledLogTypes.Add(LogType.Debug);
            }

            if (VerboseLogsAreVisible)
            {
                _disabledLogTypes.Remove(LogType.Verbose);
            }
            else
            {
                _disabledLogTypes.Add(LogType.Verbose);
            }

            _msg.Info(DebugLogsAreVisible ? "Debug logs visible" : "Debug logs hidden");
            _msg.Info(VerboseLogsAreVisible ? "Verbose logs visible" : "Verbose logs hidden");
        }
Beispiel #3
0
        public static void GracefullyStop(Grpc.Core.Server server)
        {
            Assert.ArgumentNotNull(server, nameof(server));

            _msg.Info("Starting shut down...");

            server.ShutdownAsync().Wait();

            _msg.Info("Server shut down.");
        }
Beispiel #4
0
        public void WriteLine()
        {
            if ((_target & UsageTarget.Console) != 0)
            {
                Console.Out.WriteLine();
            }

            if ((_target & UsageTarget.Log) != 0)
            {
                _msg.Info(string.Empty);
            }
        }
        private static void LogResults(
            [NotNull] IEnumerable <QualitySpecificationElement> qualitySpecificationElements,
            [NotNull] IssueProcessor issueProcessor,
            int qualityConditionCount, int datasetCount,
            bool fulfilled, bool cancelled,
            [CanBeNull] IExceptionStatistics exceptionStatistics)
        {
            using (_msg.IncrementIndentation("Quality verification finished"))
            {
                _msg.InfoFormat("Number of verified datasets: {0:N0}", datasetCount);
                using (_msg.IncrementIndentation("Number of verified quality conditions: {0:N0}",
                                                 qualityConditionCount))
                {
                    LogVerifiedConditions(qualitySpecificationElements,
                                          issueProcessor,
                                          exceptionStatistics);
                }

                _msg.InfoFormat("Warning count: {0:N0}", issueProcessor.WarningCount);
                _msg.InfoFormat("Error count: {0:N0}", issueProcessor.ErrorCount);

                if (issueProcessor.RowsWithStopConditionsCount > 0)
                {
                    _msg.WarnFormat("Number of features with stop errors: {0:N0}",
                                    issueProcessor.RowsWithStopConditionsCount);
                }

                if (exceptionStatistics != null &&
                    exceptionStatistics.TablesWithNonUniqueKeys.Count > 0)
                {
                    _msg.WarnFormat(
                        "Number of tables with non-unique keys referenced by exception objects: {0}",
                        exceptionStatistics.TablesWithNonUniqueKeys.Count);
                }

                if (cancelled)
                {
                    _msg.Warn("The quality verification was cancelled");
                }
                else if (fulfilled)
                {
                    _msg.Info("The quality specification is fulfilled");
                }
                else
                {
                    _msg.Warn("The quality specification is not fulfilled");
                }
            }
        }
Beispiel #6
0
        public static bool TryBuffer(
            [NotNull] IGeometry geometry,
            double tolerance,
            [CanBeNull] int?logInfoPointCountThreshold,
            [CanBeNull] string bufferingMessage,
            [CanBeNull] NotificationCollection notifications,
            [CanBeNull] out IPolygon bufferedPolygon)
        {
            bufferedPolygon = null;

            if (logInfoPointCountThreshold >= 0 &&
                ((IPointCollection)geometry).PointCount > logInfoPointCountThreshold)
            {
                _msg.Info(bufferingMessage);
            }

            if (notifications == null)
            {
                notifications = new NotificationCollection();
            }

            if (!ValidateBufferDistance(geometry, tolerance, notifications))
            {
                _msg.DebugFormat("{0}: {1}.",
                                 bufferingMessage, notifications.Concatenate(". "));
                return(false);
            }

            bufferedPolygon = GetOutlineBuffer(geometry, tolerance);

            return(true);
        }
Beispiel #7
0
        private void LogTransfer([CanBeNull] object sourceValue,
                                 FieldValueTransferLogLevel logLevel)
        {
            string formattedValue = GetFormattedValue(sourceValue);

            string message =
                string.Format("Transferring value from field '{0}' to field '{1}': {2}",
                              SourceFieldName, TargetFieldName, formattedValue);

            switch (logLevel)
            {
            case FieldValueTransferLogLevel.Debug:
                _msg.Debug(message);
                break;

            case FieldValueTransferLogLevel.VerboseDebug:
                _msg.VerboseDebug(message);
                break;

            case FieldValueTransferLogLevel.Info:
                _msg.Info(message);
                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(logLevel));
            }
        }
Beispiel #8
0
        void IVerificationReportBuilder.EndVerification(bool cancelled)
        {
            if (cancelled)
            {
                _msg.Warn("The verification was cancelled");
            }

            if (_errors.Count == 0)
            {
                _msg.Info("No errors found");
            }
            else
            {
                _msg.WarnFormat(_errors.Count == 1
                                                        ? "{0:N0} error found:"
                                                        : "{0:N0} errors found:", _errors.Count);

                if (_rowsWithStopConditions > 0)
                {
                    _msg.WarnFormat(
                        "Number of rows with stop conditions (not completely tested): {0:N0}",
                        _rowsWithStopConditions);
                }
            }

            ReportErrors(_errors);
        }
Beispiel #9
0
        protected override async Task SetStatusCoreAsync(IWorkItem item, ISourceClass source)
        {
            Table table = OpenFeatureClass(source);

            try
            {
                var databaseSourceClass = (DatabaseSourceClass)source;

                string description = GetOperationDescription(item.Status);

                _msg.Info($"{description}, {item.Proxy}");

                var operation = new EditOperation {
                    Name = description
                };

                string fieldName = databaseSourceClass.StatusFieldName;
                object value     = databaseSourceClass.GetValue(item.Status);

                operation.Modify(table, item.ObjectID, fieldName, value);

                await operation.ExecuteAsync();
            }
            catch (Exception e)
            {
                _msg.Error($"Error set status of work item {item.OID}, {item.Proxy}", e);
                throw;
            }
            finally
            {
                table?.Dispose();
            }
        }
Beispiel #10
0
 private void SetMessage(string message)
 {
     if (!string.IsNullOrEmpty(message))
     {
         _logger.Info(message);
     }
 }
Beispiel #11
0
        private static IIssueTableFields GetTargetFields(
            [NotNull] ICollection <IObjectClass> targetExceptionClasses,
            bool ensureRequiredFields = true)
        {
            IWorkspace workspace =
                Assert.NotNull(DatasetUtils.GetUniqueWorkspace(targetExceptionClasses));

            IIssueTableFieldManagement fields =
                IssueTableFieldsFactory.GetIssueTableFields(
                    addExceptionFields: true,
                    useDbfFieldNames: WorkspaceUtils.IsShapefileWorkspace(workspace),
                    addManagedExceptionFields: true);

            if (ensureRequiredFields)
            {
                using (_msg.IncrementIndentation("Ensuring required target fields"))
                {
                    int addedFields = EnsureTargetFields(targetExceptionClasses, fields);

                    if (addedFields == 0)
                    {
                        _msg.Info("All required fields exist in target datasets");
                    }
                }
            }

            return(fields);
        }
 protected override void SetText(string message)
 {
     if (!string.IsNullOrEmpty(message))
     {
         _logger.Info(message);
     }
 }
Beispiel #13
0
        protected override void LogEnteringSketchMode()
        {
            string logText = LocalizableStrings.AdvancedReshapeTool_LogEnteringSketchMode;
            //	"Sketch the reshape line to change the selection.<br>- Press R to restore the sketch from the previous reshape operation.<br>- Press S to toggle the non-default reshape side of the geometry.<br>- Press ESC to select different features.";

            int selectionCount = ActiveMapView.Map.SelectionCount;

            if (selectionCount > 1)
            {
                // What about lines? Idea: hyperlinks that open the relevant page in the help
                logText +=
                    string.Format(
                        "{0}- Press N to define the target connection point for the extended shared boundary when reshaping two polygons",
                        Environment.NewLine);
            }

            _msg.Info(logText);
        }
Beispiel #14
0
        private static IPolyline BufferTargetLine([NotNull] IPolyline targetLine,
                                                  [NotNull] TargetBufferOptions options,
                                                  [CanBeNull] IEnvelope envelopeScope,
                                                  [CanBeNull]
                                                  NotificationCollection bufferNotifications,
                                                  [CanBeNull] ITrackCancel trackCancel)
        {
            Assert.ArgumentNotNull(targetLine, nameof(targetLine));
            Assert.ArgumentCondition(!targetLine.IsEmpty,
                                     "BufferTargetLine: Target line is empty.");

            IPolyline result = null;

            IPolygon targetBuffer;

            if (AdjustUtils.TryBuffer(targetLine,
                                      options.BufferDistance,
                                      options.LogInfoPointThreshold,
                                      "Buffering target geometry...",
                                      bufferNotifications, out targetBuffer))
            {
                Assert.NotNull(targetBuffer, "targetBuffer");

                if (trackCancel != null && !trackCancel.Continue())
                {
                    return(targetLine);
                }

                if (options.EnforceMinimumBufferSegmentLength)
                {
                    // TODO: removing short segments is slow if many adjacent segments
                    //		 need to be removed.
                    if (trackCancel != null && !trackCancel.Continue())
                    {
                        return(targetLine);
                    }

                    if (((IPointCollection)targetLine).PointCount > options.LogInfoPointThreshold)
                    {
                        _msg.Info("Removing short segments from buffer...");
                    }

                    EnforceMinimumSegmentLength(targetBuffer,
                                                options.BufferMinimumSegmentLength,
                                                envelopeScope);
                }

                result = GeometryFactory.CreatePolyline(targetBuffer);

                Marshal.ReleaseComObject(targetBuffer);
            }

            return(result);
        }
        /// <summary>
        /// Shows the info dialog.
        /// </summary>
        /// <param name="owner">The owner.</param>
        /// <param name="message">The message.</param>
        /// <param name="title">The title.</param>
        public void ShowInfo(IWin32Window owner, string title, string message)
        {
            Assert.ArgumentNotNullOrEmpty(title, nameof(title));
            Assert.ArgumentNotNullOrEmpty(message, nameof(message));

            _msg.Info(message);

            Show(owner,
                 MsgBase.ReplaceBreakTags(message), title,
                 MessageBoxButtons.OK,
                 MessageBoxIcon.Information,
                 MessageBoxDefaultButton.Button1);
        }
        public static AdvancedReshapeResponse Reshape(
            [NotNull] AdvancedReshapeRequest request)
        {
            var polyline = (IPolyline)ProtobufGeometryUtils.FromShapeMsg(request.ReshapePaths);

            List <IPath> reshapePaths = GeometryUtils.GetPaths(Assert.NotNull(polyline)).ToList();

            GeometryReshaperBase reshaper = CreateReshaper(request, reshapePaths);

            bool useNonDefaultReshapeSide = request.UseNonDefaultReshapeSide;

            var notifications = new NotificationCollection();

            IDictionary <IGeometry, NotificationCollection> reshapedGeometries =
                reshaper.Reshape(reshapePaths, useNonDefaultReshapeSide, notifications);

            Assert.NotNull(reshapedGeometries, "No reshaped geometries");

            if (reshapedGeometries.Count == 0)
            {
                return(NoReshapeResponse(notifications));
            }

            var response = new AdvancedReshapeResponse();

            if (reshaper.ResultWithinOtherResultButNotInOriginal(
                    reshapedGeometries.Keys, out IPolygon containedPolygon))
            {
                response.OverlapPolygon = ProtobufGeometryUtils.ToShapeMsg(containedPolygon);
            }

            // Messages regarding some of the features that were not reshaped:
            if (notifications.Count > 0 && request.Features.Count > 1)
            {
                string overallMessage = notifications.Concatenate(". ");

                _msg.Info(overallMessage);
                response.WarningMessage = overallMessage;
            }

            // Junction-move, updating of adjacent lines is performed in Save:
            IList <IFeature> storedFeatures = reshaper.Save(reshapedGeometries);

            response.OpenJawReshapeHappened   = reshaper.OpenJawReshapeOcurred;
            response.OpenJawIntersectionCount = reshaper.OpenJawIntersectionPointCount;

            PackReshapeResponseFeatures(response, storedFeatures, reshapedGeometries,
                                        reshaper.OpenJawReshapeOcurred,
                                        reshaper.NotificationIsWarning);

            return(response);
        }
Beispiel #17
0
        private ChangeAlongZSource DetermineZSource(IFeature feature)
        {
            string             note    = null;
            ChangeAlongZSource zSource = ZSourceProvider?.GetValue(feature, out note) ??
                                         ChangeAlongZSource.Target;

            if (note != null)
            {
                _msg.Info(note);
            }

            return(zSource);
        }
        private void SetMessage(string message)
        {
            if (message == null)
            {
                return;                 // no-op if null message
            }

            _statusLabel.Text = message;

            if (_logger != null && !string.IsNullOrEmpty(message))
            {
                _logger.Info(message);
            }
        }
Beispiel #19
0
        static void Main(string[] args)
        {
            try
            {
                IServiceHealth   health;
                Grpc.Core.Server server = Run(args, out health);

                _msg.Info("Type Q(uit) to stop the server.");

                while (true)
                {
                    // Avoid mindless spinning
                    Thread.Sleep(100);

                    if (System.Console.KeyAvailable)
                    {
                        if (System.Console.ReadKey(true).Key == ConsoleKey.Q)
                        {
                            _msg.Warn("Shutting down due to user input");
                            break;
                        }
                    }

                    // TODO: Uncomment after next pull
                    //if (health.IsAnyServiceUnhealthy())
                    //{
                    //	_msg.Warn("Shutting down due to service state NOT_SERVING");
                    //	break;
                    //}
                }

                if (server != null)
                {
                    GrpcServerUtils.GracefullyStop(server);
                }
            }
            catch (Exception ex)
            {
                _msg.Error("An error occurred in microservice.", ex);
                Environment.ExitCode = -1;
            }
            finally
            {
                _msg.Debug("License released, shutting down...");
            }
        }
 // TODO algr: temporary tests
 protected override async void OnClick()
 {
     try
     {
         var window = FrameworkApplication.ActiveWindow as IProjectWindow;
         var path   = window?.SelectedItems.First().Path;
         if (path != null)
         {
             _msg.Info($"Open worklist file {path}");
             await ProSuiteToolsModule.OpenIssuesWorklist(path);
         }
     }
     catch (Exception ex)
     {
         _msg.Error("Open WorkList error", ex);
     }
 }
Beispiel #21
0
        private static void Execute([NotNull] string statement, [NotNull] IDbCommand cmd)
        {
            Assert.ArgumentNotNullOrEmpty(statement, nameof(statement));
            Assert.ArgumentNotNull(cmd, nameof(cmd));

            _msg.Info(statement);

            try
            {
                cmd.CommandText = statement;
                cmd.ExecuteNonQuery();
            }
            catch (Exception e)
            {
                _msg.Warn(e.Message);
            }
        }
Beispiel #22
0
        private void ProcessFeature([NotNull] IFeature feature,
                                    [NotNull] IPolycurve overlappingGeometry)
        {
            IGeometry featureShape = feature.Shape;

            if (GeometryUtils.Disjoint(featureShape, overlappingGeometry))
            {
                return;
            }

            IList <IGeometry> overlappingResults;

            string             note    = null;
            ChangeAlongZSource zSource = ZSourceProvider?.GetValue(feature, out note) ??
                                         ChangeAlongZSource.Target;

            if (note != null)
            {
                _msg.Info(note);
            }

            var sourceMultipatch = featureShape as IMultiPatch;

            IList <IGeometry> modifiedGeometries =
                sourceMultipatch != null
                                        ? RemoveOverlaps(sourceMultipatch, (IPolygon)overlappingGeometry,
                                                         zSource, out overlappingResults)
                                        : RemoveOverlap((IPolycurve)featureShape, overlappingGeometry,
                                                        zSource, out overlappingResults);

            // additional check for undefined z values - this happens if the target has no Zs or UseSourceZs is active
            // -> currently the undefined Zs are interpolated before storing
            if (HasAnyGeometryUndefinedZs(modifiedGeometries))
            {
                _msg.DebugFormat(
                    "The result geometry of {0} has undefined z values.",
                    GdbObjectUtils.ToString(feature));
            }

            OverlapResultGeometries singleFeatureResult =
                new OverlapResultGeometries(feature, modifiedGeometries,
                                            overlappingResults);

            Result.ResultsByFeature.Add(singleFeatureResult);
        }
        private static string GetSelectedItemPath(string title, string filter,
                                                  BrowseProjectFilter browseFilter)
        {
            var dialog = new OpenItemDialog
            {
                BrowseFilter = browseFilter,
                Filter       = filter,
                Title        = title
            };

            if (dialog.ShowDialog().HasValue&& dialog.Items.ToList().Count > 0)
            {
                return(dialog.Items.FirstOrDefault()?.Path);
            }

            _msg.Info("No Issue Geodatabase selected");
            return(null);
        }
        private void StartHealthChecking(IServiceHealth health)
        {
            _health = health;

            if (_health == null)
            {
                return;
            }

            if (_timer != null)
            {
                _msg.Info("Health-check timer is already running.");
                return;
            }

            _timer = new Timer(_interval)
            {
                AutoReset = true
            };

            _timer.Elapsed += _timer_Elapsed;
            _timer.Start();
        }
Beispiel #25
0
        private static async Task <bool> ExecuteAsync([NotNull] string tool,
                                                      [NotNull] IReadOnlyList <string> parameters)
        {
            Assert.ArgumentNotNullOrEmpty(tool, nameof(tool));
            Assert.ArgumentNotNull(parameters, nameof(parameters));
            Assert.ArgumentCondition(parameters.Count > 0, "no parameter");

            _msg.VerboseDebug($"{tool}, Parameters: {StringUtils.Concatenate(parameters, ", ")}");

            IReadOnlyList <KeyValuePair <string, string> > environments =
                Geoprocessing.MakeEnvironmentArray(overwriteoutput: true);

            IGPResult result = await Geoprocessing.ExecuteToolAsync(tool, parameters, environments);

            if (!result.IsFailed)
            {
                return(true);
            }

            _msg.Info(
                $"{tool} has failed: {StringUtils.Concatenate(Format(result.Messages), ", ")}, Parameters: {StringUtils.Concatenate(parameters, ", ")}");
            return(false);
        }
Beispiel #26
0
        public static string GetIssueGeodatabasePath([NotNull] string worklistDefinitionFile)
        {
            Assert.ArgumentNotNullOrEmpty(worklistDefinitionFile, nameof(worklistDefinitionFile));

            if (!File.Exists(worklistDefinitionFile))
            {
                _msg.Debug($"{worklistDefinitionFile} does not exist");
                return(null);
            }

            string extension = Path.GetExtension(worklistDefinitionFile);

            if (!string.Equals(extension, ".iwl"))
            {
                _msg.Debug($"{worklistDefinitionFile} is no issue work list");
                return(null);
            }

            var helper = new XmlSerializationHelper <XmlWorkListDefinition>();

            XmlWorkListDefinition       definition = helper.ReadFromFile(worklistDefinitionFile);
            List <XmlWorkListWorkspace> workspaces = definition.Workspaces;

            string result = workspaces[0].ConnectionString;

            if (workspaces.Count > 0)
            {
                _msg.Info(
                    $"There are many issue geodatabases in {worklistDefinitionFile} but only one is expected. Taking the first one {result}");
            }
            else
            {
                _msg.Debug($"Found issue geodatabase {result} in {worklistDefinitionFile}");
            }

            return(result);
        }
Beispiel #27
0
 protected override void LogEnteringSketchMode()
 {
     _msg.Info("Sketch a hole or any polygon to be erased from the selection.<br>Press [ESC] to reselect the polygon(s).");
 }
Beispiel #28
0
 public void ReportInfo(string text)
 {
     _msg.Info(text);
 }
        private bool Verify([NotNull] QualitySpecification qualitySpecification,
                            double tileSize,
                            [NotNull] string directory,
                            IssueRepositoryType issueRepositoryType,
                            [NotNull] IEnumerable <KeyValuePair <string, string> > properties,
                            [CanBeNull] XmlVerificationOptions verificationOptions,
                            [CanBeNull] AreaOfInterest areaOfInterest,
                            [CanBeNull] ITrackCancel trackCancel,
                            out int errorCount,
                            out int warningCount,
                            out int exceptionCount,
                            out int unusedExceptionObjectCount,
                            out int rowCountWithStopConditions)
        {
            Model primaryModel = StandaloneVerificationUtils.GetPrimaryModel(qualitySpecification);

            Assert.NotNull(primaryModel, "no primary model found for quality specification");

            // TODO disable quality conditions based on primaryModel and DatasetTestParameterValue.UsedAsReferenceData?
            // TODO this would probably require an explicit identification of the primary data source
            XmlVerificationReportBuilder xmlReportBuilder = GetReportBuilder();
            var statisticsBuilder = new IssueStatisticsBuilder();

            var datasetsCollector = new InvolvedDatasetsCollector();

            var service = new StandaloneQualityVerificationService(
                new MultiReportBuilder(xmlReportBuilder,
                                       statisticsBuilder,
                                       datasetsCollector),
                (context) => new SimpleDatasetOpener(context));

            // This context excludes geometric networks, terrains, topology, etc.:
            var datasetContext  = new MasterDatabaseDatasetContext();
            var datasetResolver =
                new QualityConditionObjectDatasetResolver(
                    new MasterDatabaseWorkspaceContextLookup());

            string issueWorkspaceName =
                VerificationOptionUtils.GetIssueWorkspaceName(verificationOptions);
            string verificationReportFileName =
                VerificationOptionUtils.GetXmlReportFileName(verificationOptions);

            ISpatialReference spatialReference =
                primaryModel.SpatialReferenceDescriptor?.SpatialReference;

            var  issueGdbWritten = false;
            bool fulfilled;

            List <string> htmlReportFilePaths;
            List <string> specificationReportFilePaths;
            string        gdbPath = null;

            Func <IObjectDataset, string> getKeyField =
                StandaloneVerificationUtils.GetKeyFieldLookupFunction(verificationOptions);

            ExceptionObjectRepository exceptionObjectRepository =
                StandaloneVerificationUtils.PrepareExceptionRepository(
                    qualitySpecification, datasetContext, datasetResolver, areaOfInterest,
                    verificationOptions);

            using (IIssueRepository issueRepository =
                       ExternalIssueRepositoryUtils.GetIssueRepository(
                           directory, issueWorkspaceName, spatialReference, issueRepositoryType,
                           addExceptionFields: true))
            {
                fulfilled = service.Verify(qualitySpecification, datasetContext, datasetResolver,
                                           issueRepository, exceptionObjectRepository, tileSize,
                                           getKeyField,
                                           areaOfInterest, trackCancel,
                                           out errorCount,
                                           out warningCount,
                                           out rowCountWithStopConditions);

                if (issueRepository != null)
                {
                    issueGdbWritten = true;

                    gdbPath = ((IWorkspace)issueRepository.FeatureWorkspace).PathName;

                    _msg.InfoFormat("Issues written to {0}", gdbPath);

                    issueRepository.CreateIndexes(GetForSubProcess(trackCancel),
                                                  ignoreErrors: true);
                }

                using (_msg.IncrementIndentation("Documenting verification results..."))
                {
                    XmlVerificationReport verificationReport = GetVerificationReport(
                        xmlReportBuilder, qualitySpecification, properties);

                    string verificationReportPath = Path.Combine(directory,
                                                                 verificationReportFileName);
                    XmlUtils.Serialize(verificationReport, verificationReportPath);

                    _msg.InfoFormat("Verification report written to {0}", verificationReportPath);

                    IssueStatistics issueStatistics = statisticsBuilder.IssueStatistics;

                    if (issueRepository != null)
                    {
                        var issueStatisticsWriter =
                            new IssueStatisticsWriter(issueRepository.FeatureWorkspace);

                        issueStatisticsWriter.WriteStatistics(issueStatistics);

                        if (spatialReference != null &&
                            areaOfInterest != null &&
                            !areaOfInterest.IsEmpty)
                        {
                            var aoiWriter =
                                new AreaOfInterestWriter(issueRepository.FeatureWorkspace);
                            aoiWriter.WriteAreaOfInterest(areaOfInterest, spatialReference);
                        }
                    }

                    specificationReportFilePaths =
                        StandaloneVerificationUtils.WriteQualitySpecificationReport(
                            qualitySpecification, directory, _qualitySpecificationTemplatePath,
                            verificationOptions);

                    htmlReportFilePaths = StandaloneVerificationUtils.WriteHtmlReports(
                        qualitySpecification, directory, issueStatistics, verificationReport,
                        verificationReportFileName, _htmlReportTemplatePath, verificationOptions,
                        issueGdbWritten ? gdbPath : null,
                        null, specificationReportFilePaths);
                }
            }

            GC.Collect();
            GC.WaitForPendingFinalizers();

            if (htmlReportFilePaths.Count > 0)
            {
                using (_msg.IncrementIndentation(htmlReportFilePaths.Count == 1
                                                                         ? "Html report:"
                                                                         : "Html reports:"))
                {
                    foreach (string path in htmlReportFilePaths)
                    {
                        _msg.Info(path);
                    }
                }
            }

            if (specificationReportFilePaths.Count > 0)
            {
                using (_msg.IncrementIndentation(specificationReportFilePaths.Count == 1
                                                                         ? "Quality specification report:"
                                                                         : "Quality specification reports:"))
                {
                    foreach (string path in specificationReportFilePaths)
                    {
                        _msg.Info(path);
                    }
                }
            }

            if (exceptionObjectRepository != null)
            {
                IExceptionStatistics stats = exceptionObjectRepository.ExceptionStatistics;
                exceptionCount             = stats.ExceptionCount;
                unusedExceptionObjectCount = stats.UnusedExceptionObjectCount;
            }
            else
            {
                exceptionCount             = 0;
                unusedExceptionObjectCount = 0;
            }

            return(fulfilled);
        }
 protected override void LogPromptForSelection()
 {
     _msg.Info(LocalizableStrings.RemoveOverlapsTool_LogPromptForSelection);
 }