protected override void LogDerivedGeometriesCalculated(CancelableProgressor progressor) { if (_overlaps != null && _overlaps.Notifications.Count > 0) { _msg.Info(_overlaps.Notifications.Concatenate(Environment.NewLine)); if (!_overlaps.HasOverlaps()) { _msg.InfoFormat("Select one or more different features."); } } else if (_overlaps == null || !_overlaps.HasOverlaps()) { _msg.Info( "No overlap of other polygons with current selection found. Select one or more different features."); } if (_overlaps != null && _overlaps.HasOverlaps()) { string msg = _overlaps.OverlapGeometries.Count == 1 ? "Select the overlap to subtract from the selection" : "Select one or more overlaps to subtract from the selection. Draw a box to select overlaps completely within the box."; _msg.InfoFormat(LocalizableStrings.RemoveOverlapsTool_AfterSelection, msg); } }
public override async Task VerifyQuality( VerificationRequest request, IServerStreamWriter <VerificationResponse> responseStream, ServerCallContext context) { try { await StartRequest(request); Func <ITrackCancel, ServiceCallStatus> func = trackCancel => VerifyQualityCore(request, responseStream, trackCancel); ServiceCallStatus result = await GrpcServerUtils.ExecuteServiceCall( func, context, _staThreadScheduler); _msg.InfoFormat("Verification {0}", result); } catch (Exception e) { _msg.Error($"Error verifying quality for request {request}", e); SendFatalException(e, responseStream); SetUnhealthy(); } finally { EndRequest(); } }
private static void AddOrUpdateAttribute( [NotNull] AttributedAssociation attributedAssociation, [NotNull] IField field, int fieldIndex) { Assert.ArgumentNotNull(field, nameof(field)); const bool includeDeleted = true; AssociationAttribute attribute = attributedAssociation.GetAttribute(field.Name, includeDeleted); if (attribute == null) { _msg.InfoFormat("Adding attribute {0}", field.Name); attribute = attributedAssociation.AddAttribute(field.Name, (FieldType)field.Type); } else { // attribute already registered if (attribute.Deleted) { _msg.WarnFormat( "Attribute {0} was registered as deleted, but exists now. " + "Resurrecting it...", attribute.Name); attribute.RegisterExisting(); } attribute.FieldType = (FieldType)field.Type; } // configure the attribute attribute.SortOrder = fieldIndex; }
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); }
protected override void LogPromptForSelection() { //string enterMsg = CanUseSelection() // ? "- To re-use the existing selection, press Enter" // : string.Empty; _msg.InfoFormat( "Select one or more polygon features.<br>- Press and hold SHIFT to add or remove features from the existing selection.<br>- Press and hold P to draw a polygon that completely contains the features to be selected. Finish the polygon with double-click."); }
private static Grpc.Core.Server Run(string[] args, out IServiceHealth health) { Grpc.Core.Server server; try { MicroserverArguments arguments; string configFilePath; if (!TryGetArgumentsFromConfigFile(args, _configFileName, out arguments, out configFilePath)) { var parsedArgs = Parser.Default.ParseArguments <MicroserverArguments>(args); parsedArgs.WithParsed(a => { arguments = a; }); } ConfigureLogging(arguments.VerboseLogging, _logConfigFileName); // Read the RuntimeUtils.Version to initialize it and use fall-back implementation // to avoid subsequent hang once the license has been initialized (this is probably // only relevant for 10.x). _msg.DebugFormat("Installed ArcGIS Version: {0}.", RuntimeUtils.Version); if (configFilePath != null) { _msg.InfoFormat("Using service configuration defined in {0}", configFilePath); } else { _msg.DebugFormat( "Program was called with the following command line arguments: {0}{1}", Environment.NewLine, arguments); } _msg.DebugFormat("Host: {0}", arguments.HostName); _msg.DebugFormat("Port: {0}", arguments.Port); _msg.InfoFormat("Checking out ArcGIS license..."); ComUtils.ExecuteInStaThread(CheckoutLicense); EnvironmentUtils.SetConfigurationDirectoryProvider( ConfigurationUtils.GetAppDataConfigDirectoryProvider()); server = StartServer(arguments, out health); } catch (Exception ex) { _msg.Error("An error occurred in QA microservice startup.", ex); throw; } return(server); }
/// <summary> /// Starts the grpc server, binds the <see cref="QualityVerificationGrpcImpl"/> together /// with the <see cref="IServiceHealth"/> implementation and returns a handle for both. /// </summary> /// <param name="arguments">The microserver command line / config arguments.</param> /// <param name="inputsFactoryMethod">The factory method that creates the /// <see cref="IBackgroundVerificationInputs"/> instance. If no factory is proveded, only /// stand-alone verification (such as XML) can be used.</param> /// <param name="checkout3dAnalyst"></param> /// <param name="markUnhealthyOnExceptions"></param> /// <returns></returns> public static StartedGrpcServer StartVerificationServer( [NotNull] MicroserverArguments arguments, [CanBeNull] Func <VerificationRequest, IBackgroundVerificationInputs> inputsFactoryMethod, bool checkout3dAnalyst, bool markUnhealthyOnExceptions) { var healthService = new HealthServiceImpl(); IServiceHealth health = new ServiceHealth(healthService); var wuVerificationServiceImpl = new QualityVerificationGrpcImpl(inputsFactoryMethod, arguments.MaxParallel) { Checkout3DAnalyst = checkout3dAnalyst }; if (markUnhealthyOnExceptions) { wuVerificationServiceImpl.Health = health; } health.SetStatus(wuVerificationServiceImpl.GetType(), true); ServerCredentials serverCredentials = GrpcServerUtils.GetServerCredentials(arguments.Certificate, arguments.PrivateKeyFile, arguments.EnforceMutualTls); var oneGb = (int)Math.Pow(1024, 3); IList <ChannelOption> channelOptions = GrpcServerUtils.CreateChannelOptions(oneGb); var server = new Grpc.Core.Server(channelOptions) { Services = { QualityVerificationGrpc.BindService(wuVerificationServiceImpl), Health.BindService(healthService) }, Ports = { new ServerPort(arguments.HostName, arguments.Port, serverCredentials) } }; server.Start(); _msg.InfoFormat("Service is listening on host {0}, port {1}.", arguments.HostName, arguments.Port); return(new StartedGrpcServer(server, health)); }
private static void AddOrUpdateObjectType([NotNull] ObjectDataset objectDataset, [NotNull] Subtype subtype, int subtypeIndex, [NotNull] IEnumerable <Subtype> allSubtypes) { Assert.ArgumentNotNull(subtype, nameof(subtype)); Assert.ArgumentNotNull(allSubtypes, nameof(allSubtypes)); ObjectType objectType = GetObjectType(objectDataset, subtype, allSubtypes); if (objectType == null) { objectType = new ObjectType(objectDataset, subtype.Code, subtype.Name); _msg.InfoFormat("Adding object type {0}", objectType.Name); objectDataset.AddObjectType(subtype.Code, subtype.Name); } else { // object type already registered if (objectType.Deleted) { _msg.WarnFormat( "Object type {0} ({1}) was registered as deleted, but exists now. " + "Resurrecting it...", objectType.Name, objectType.SubtypeCode); objectType.RegisterExisting(); } // update properties if (!Equals(objectType.Name, subtype.Name)) { _msg.InfoFormat("Updating name of object type {0} to {1}", objectType.Name, subtype.Name); objectType.UpdateName(subtype.Name); } if (!Equals(objectType.SubtypeCode, subtype.Code)) { _msg.InfoFormat("Updating subtype code of object type {0} from {1} to {2}", objectType.Name, objectType.SubtypeCode, subtype.Code); objectType.UpdateSubtypeCode(subtype.Code); } } // configure the object type objectType.SortOrder = subtypeIndex; }
private static Grpc.Core.Server Run(string[] args, out IServiceHealth health) { Grpc.Core.Server server; try { MicroserverArguments arguments; string configFilePath; if (!ConfigurationUtils.TryGetArgumentsFromConfigFile( args, _configFileName, out arguments, out configFilePath)) { var parsedArgs = Parser.Default.ParseArguments <MicroserverArguments>(args); parsedArgs.WithParsed(a => { arguments = a; }); } ConfigureLogging(arguments.VerboseLogging, _logConfigFileName); if (configFilePath != null) { _msg.InfoFormat("Using service configuration defined in {0}", configFilePath); } else { _msg.DebugFormat( "Program was called with the following command line arguments: {0}{1}", Environment.NewLine, arguments); } _msg.DebugFormat("Host: {0}", arguments.HostName); _msg.DebugFormat("Port: {0}", arguments.Port); _msg.InfoFormat("Checking out ArcGIS license..."); ArcGISLicenses.InitializeAo11(); EnvironmentUtils.SetConfigurationDirectoryProvider( ConfigurationUtils.GetAppDataConfigDirectoryProvider()); server = StartServer(arguments, out health); } catch (Exception ex) { _msg.Error("An error occurred in QA microservice startup.", ex); throw; } return(server); }
public void LogSuccessfulCut() { if (ResultGeometriesByFeature.Count == 1) { _msg.InfoFormat("The selected feature was cut into {0} features", GetResultPolygonCount(ResultGeometriesByFeature)); } else { _msg.InfoFormat("{0} features were cut into {1} features", ResultGeometriesByFeature.Count, GetResultPolygonCount(ResultGeometriesByFeature)); } }
/// <summary> /// Creates the server credentials using either two PEM files or a certificate from the /// Certificate Store. /// </summary> /// <param name="certificate">The certificate store's certificate (subject or thumbprint) /// or the PEM file containing the certificate chain.</param> /// <param name="privateKeyFilePath">The PEM file containing the private key (only if the /// certificate was provided by a PEM file</param> /// <param name="enforceMutualTls">Enforce client authentication.</param> /// <returns></returns> public static ServerCredentials GetServerCredentials( [CanBeNull] string certificate, [CanBeNull] string privateKeyFilePath, bool enforceMutualTls = false) { if (string.IsNullOrEmpty(certificate)) { _msg.InfoFormat("Certificate was not provided. Using insecure credentials."); return(ServerCredentials.Insecure); } KeyPair certificateKeyPair = TryGetServerCertificateKeyPair(certificate, privateKeyFilePath); if (certificateKeyPair == null) { return(ServerCredentials.Insecure); } List <KeyCertificatePair> keyCertificatePairs = new List <KeyCertificatePair> { new KeyCertificatePair( certificateKeyPair.PublicKey, certificateKeyPair.PrivateKey) }; string rootCertificatesAsPem = CertificateUtils.GetUserRootCertificatesInPemFormat(); if (_msg.IsVerboseDebugEnabled) { _msg.DebugFormat("Trusted root credentials provided: {0}", rootCertificatesAsPem); } // If not required, still verify the client certificate, if presented var clientCertificates = enforceMutualTls ? SslClientCertificateRequestType.RequestAndRequireAndVerify : SslClientCertificateRequestType.RequestAndVerify; ServerCredentials result = new SslServerCredentials( keyCertificatePairs, rootCertificatesAsPem, clientCertificates); return(result); }
private static void ValidateConnectLines([NotNull] ICurve sourcePart, [CanBeNull] ref IPath startSourceConnection, [CanBeNull] ref IPath endSourceConnection, [CanBeNull] IPath startFallback, [CanBeNull] IPath endFallback) { startSourceConnection = startSourceConnection ?? startFallback; endSourceConnection = endSourceConnection ?? endFallback; var fallbackAssigned = false; // crossing source connections if (startSourceConnection != null && startSourceConnection.Length > 0 && endSourceConnection != null && endSourceConnection.Length > 0 && InteriorIntersects(startSourceConnection, endSourceConnection)) { // can happen if one (or both) is (are) prolongated _msg.InfoFormat( "Unable to use adjust line with source prolongation. Resulting line would cross."); if (TryAssignFallback(ref startSourceConnection, startFallback)) { fallbackAssigned = true; } if (TryAssignFallback(ref endSourceConnection, endFallback)) { fallbackAssigned = true; } } if (startSourceConnection != null && endSourceConnection != null) { if (EnsureMinimumSourceReplacementLength(sourcePart, ref startSourceConnection, ref endSourceConnection, startFallback, endFallback)) { fallbackAssigned = true; } } if (fallbackAssigned) { // validate again -> fall backs could cross too ValidateConnectLines(sourcePart, ref startSourceConnection, ref endSourceConnection, startFallback, endFallback); } }
public static string RenderHtmlQualitySpecification( [NotNull] HtmlQualitySpecification qualitySpecification, [NotNull] string templateFilePath, [NotNull] string reportFilePath, bool throwTemplateErrors = false) { Assert.ArgumentNotNull(qualitySpecification, nameof(qualitySpecification)); Assert.ArgumentNotNullOrEmpty(templateFilePath, nameof(templateFilePath)); Assert.ArgumentNotNullOrEmpty(reportFilePath, nameof(reportFilePath)); Assert.ArgumentCondition(File.Exists(templateFilePath), "template file does not exist: {0}", (object)templateFilePath); _msg.DebugFormat( "Rendering quality specification documentation based on template {0}", templateFilePath); LiquidUtils.RegisterSafeType <HtmlQualitySpecification>(); LiquidUtils.RegisterSafeType <HtmlTexts>(); const string rootName = "specification"; string output = LiquidUtils.Render( templateFilePath, throwTemplateErrors, new KeyValuePair <string, object>(rootName, qualitySpecification), new KeyValuePair <string, object>("text", new HtmlTexts())); _msg.DebugFormat("Writing quality specification report to {0}", reportFilePath); FileSystemUtils.WriteTextFile(output, reportFilePath); _msg.InfoFormat("Quality specification report written to {0}", reportFilePath); return(reportFilePath); }
private void ProcessSelection([NotNull] MapView activeMapView, [CanBeNull] CancelableProgressor progressor = null) { Dictionary <MapMember, List <long> > selectionByLayer = activeMapView.Map.GetSelection(); NotificationCollection notifications = new NotificationCollection(); List <Feature> applicableSelection = GetApplicableSelectedFeatures(selectionByLayer, notifications).ToList(); int selectionCount = selectionByLayer.Sum(kvp => kvp.Value.Count); if (applicableSelection.Count > 0 && (AllowNotApplicableFeaturesInSelection || applicableSelection.Count == selectionCount)) { LogUsingCurrentSelection(); AfterSelection(applicableSelection, progressor); } else { if (selectionCount > 0) { _msg.InfoFormat(notifications.Concatenate(Environment.NewLine)); } LogPromptForSelection(); StartSelectionPhase(); } }
public static bool TryGetArgumentsFromConfigFile(string[] args, string configFileName, out MicroserverArguments arguments, out string configFilePath) { arguments = null; configFilePath = null; if (args.Length == 0) { _msg.InfoFormat("Getting server host/port parameters from configuration file."); configFilePath = GetConfigFilePath(configFileName, false); if (configFilePath != null) { XmlSerializationHelper <MicroserverArguments> helper = new XmlSerializationHelper <MicroserverArguments>(); arguments = helper.ReadFromFile(configFilePath); return(true); } } return(false); }
private static void CreateIndex([NotNull] IssueFeatureWriter writer, [CanBeNull] ITrackCancel trackCancel, bool ignoreErrors) { _msg.InfoFormat(writer.WriteCount == 1 ? "Creating spatial index for {0} issue feature in '{1}'" : "Creating spatial index for {0} issue features in '{1}'", writer.WriteCount, writer.Name); try { writer.CreateSpatialIndex(trackCancel); } catch (Exception e) { if (!ignoreErrors) { throw; } _msg.Debug("Error creating spatial index", e); _msg.WarnFormat("Error creating spatial index for feature class {0}: {1}", writer.Name, e.Message); } }
public static async Task <bool> FlashResultPolygonsAsync( [NotNull] MapView activeView, [NotNull] IDictionary <Feature, Geometry> resultFeatures, int maxFeatureCountThreshold = 5) { if (resultFeatures.Count > maxFeatureCountThreshold) { _msg.InfoFormat("{0} have been updated (no feature flashing).", resultFeatures.Count); return(false); } var polySymbol = SymbolFactory.Instance.DefaultPolygonSymbol; foreach (Geometry resultGeometry in resultFeatures.Values) { if (!(resultGeometry is Polygon poly)) { continue; } using (await activeView.AddOverlayAsync(poly, polySymbol.MakeSymbolReference())) { await Task.Delay(400); } } return(true); }
private static void LogBeginVerification( [NotNull] QualitySpecification qualitySpecification, double tileSize, [CanBeNull] AreaOfInterest areaOfInterest) { using (_msg.IncrementIndentation("Begin quality verification")) { _msg.InfoFormat("Quality specification: {0}", qualitySpecification.Name); _msg.InfoFormat("Verification tile size: {0}", tileSize); if (areaOfInterest != null) { IGeometry testPerimeter = areaOfInterest.Geometry; if (testPerimeter.IsEmpty) { _msg.Warn("Test perimeter is empty"); } else { var envelope = testPerimeter as IEnvelope; string message; if (envelope == null) { Assert.ArgumentCondition(testPerimeter is IPolygon, "Unexpected test perimeter type: {0}; must be polygon or envelope", testPerimeter.GeometryType); envelope = testPerimeter.Envelope; message = string.Format("Polygon extent: {0} x {1}", envelope.Width, envelope.Height); } else { message = string.Format("Extent: {0} x {1}", envelope.Width, envelope.Height); } using (_msg.IncrementIndentation(message)) { _msg.InfoFormat("X-Min: {0}", envelope.XMin); _msg.InfoFormat("Y-Min: {0}", envelope.YMin); _msg.InfoFormat("X-Max: {0}", envelope.XMax); _msg.InfoFormat("Y-Max: {0}", envelope.YMax); } } } } }
protected override void LogPromptForSelection() { _msg.InfoFormat( "Select one or more features by clicking or dragging a box. Options: " + "<br>-Press and hold SHIFT to add or remove features from the existing selection." + "<br>-Press CTRL and drag a box to show a list of selectable feature classes." + "<br>-Press CTRL and click on overlapping features to select a single feature." + "<br>-Press ALT and click to select all features at the click point."); }
private static void EnsuresZsAreNonNan([NotNull] IGeometry inGeometry, [NotNull] IGeometry originalGeometry, [NotNull] IFeature feature) { bool zSimple = GeometryUtils.TrySimplifyZ(inGeometry); if (zSimple) { return; } _msg.Debug( "Geometry has undefined Zs, even after calculating non-simple Zs."); // Remaining NaNs cannot be interpolated -> e.g. because there is only 1 Z value in a part // make sure each part has at least some Z values, otherwise CalculateNonSimpleZs fails: int geometryCount = ((IGeometryCollection)inGeometry).GeometryCount; for (var i = 0; i < geometryCount; i++) { IGeometry part = ((IGeometryCollection)inGeometry).Geometry[i]; if (!GeometryUtils.HasUndefinedZValues(part)) { continue; } _msg.DebugFormat("Geometry part <index> {0} has no Zs. Extrapolating...", i); IGeometry originalGeoInDataSpatialRef; // NOTE: same SR needed because ExtrapolateZs / QueryPointAndDistance does not honor different spatial refs if (GeometryUtils.EnsureSpatialReference(originalGeometry, feature, out originalGeoInDataSpatialRef)) { _msg.DebugFormat( "The original shape of {0} was projected from map coordinates back to the feature class' spatial reference.", GdbObjectUtils.ToString(feature)); } IGeometry extrapolatedPart = GeometryUtils.ExtrapolateZ( part, (IPolycurve)originalGeoInDataSpatialRef); GeometryUtils.ReplaceGeometryPart(inGeometry, i, extrapolatedPart); if (originalGeoInDataSpatialRef != originalGeometry) { Marshal.ReleaseComObject(originalGeoInDataSpatialRef); } _msg.InfoFormat( "Z values for {0} were extrapolated from source geometry.", GdbObjectUtils.ToString(feature)); } }
public static bool StoreTx( EditOperation.IEditContext editContext, [CanBeNull] IDictionary <Feature, Geometry> updates, [CanBeNull] IDictionary <Feature, IList <Geometry> > copies = null) { _msg.DebugFormat("Saving {0} updates and {1} inserts...", updates?.Count ?? 0, copies?.Count ?? 0); if (updates != null && updates.Count > 0) { foreach (KeyValuePair <Feature, Geometry> keyValuePair in updates) { StoreShape(keyValuePair, editContext); } _msg.InfoFormat("Successfully stored {0} updated feature(s).", updates.Count); } if (copies != null && copies.Count > 0) { foreach (KeyValuePair <Feature, IList <Geometry> > keyValuePair in copies) { Feature originalFeature = keyValuePair.Key; IList <Geometry> newGeometries = keyValuePair.Value; FeatureClass featureClass = originalFeature.GetTable(); foreach (Geometry newGeometry in newGeometries) { RowBuffer rowBuffer = DuplicateRow(originalFeature); SetShape(rowBuffer, newGeometry, featureClass); Feature newFeature = featureClass.CreateRow(rowBuffer); StoreShape(newFeature, newGeometry, editContext); } } _msg.InfoFormat("Successfully created {0} new feature(s).", copies.Count); } return(true); }
private static bool ValidateFlowDirection( [NotNull] IFeature feature, [NotNull] ILinearNetworkFeatureFinder featureFinder, [NotNull] NotificationCollection notifications) { if (((IFeatureClass)feature.Class).ShapeType != esriGeometryType.esriGeometryPolyline) { return(true); } IGeometry newGeometry = feature.Shape; IPolyline polyline = (IPolyline)newGeometry; bool hasCorrectOrientation = false; bool hasWrongOrientation = false; int fromEdgeCount = ValidateConnections(feature, LineEnd.From, featureFinder, ref hasCorrectOrientation, ref hasWrongOrientation); int toEdgeCount = ValidateConnections(feature, LineEnd.To, featureFinder, ref hasCorrectOrientation, ref hasWrongOrientation); if (!hasWrongOrientation) { return(true); } if (!hasCorrectOrientation) { // all other connections are different -> flip polyline.ReverseOrientation(); feature.Shape = polyline; feature.Store(); _msg.InfoFormat("Feature {0} was flipped to enforce flow direction", GdbObjectUtils.ToString(feature)); return(true); } // Mixed situation: if (fromEdgeCount <= 1 && toEdgeCount <= 1) { // No bifurcation or confluence but still incorrect at one end -> error? NotificationUtils.Add(notifications, "Feature {0} does not have a consistent flow direction with respect to its connected edges", GdbObjectUtils.ToString(feature)); return(false); } // Confluence or bifurcation -> probably ok return(true); }
public override async Task VerifyQuality( VerificationRequest request, IServerStreamWriter <VerificationResponse> responseStream, ServerCallContext context) { try { _msg.InfoFormat("Starting verification request from {0}", request.UserName); _msg.DebugFormat("Request details: {0}", request); if (Checkout3DAnalyst) { // It must be re-checked out (but somehow it's enough to do it // on the calling thread-pool thread!?) Ensure3dAnalyst(); } Func <ITrackCancel, ServiceCallStatus> func = trackCancel => VerifyQualityCore(request, responseStream, trackCancel); ServiceCallStatus result = await GrpcServerUtils.ExecuteServiceCall( func, context, _singleStaThreadScheduler); _msg.InfoFormat("Verification {0}", result); } catch (Exception e) { _msg.Error($"Error verifying quality for request {request}", e); SendFatalException(e, responseStream); SetUnhealthy(); } }
protected override void LogPromptForSelection() { // TODO: Only usable selection bool hasSelection = ActiveMapView.Map.SelectionCount > 0; // If the last reshape was just finished and the feature is still selected, Enter is entering the sketch mode again using the same selection string enterMsg = hasSelection ? LocalizableStrings.AdvancedReshapeTool_LogPromptForSelection_Enter : string.Empty; _msg.InfoFormat(LocalizableStrings.AdvancedReshapeTool_LogPromptForSelection, enterMsg); }
private static void WriteHtmlReport( [NotNull] QualitySpecification qualitySpecification, [NotNull] string directory, [NotNull] HtmlReportDefinition reportDefinition, [NotNull] IssueStatistics issueStatistics, [NotNull] XmlVerificationReport verificationReport, [NotNull] string verificationReportFileName, [CanBeNull] string issueGdbPath, [CanBeNull] IEnumerable <string> issueMapFilePaths, [NotNull] IEnumerable <string> htmlReportFileNames, [CanBeNull] IEnumerable <string> qualitySpecificationReportFilePaths) { Assert.ArgumentNotNull(reportDefinition, nameof(reportDefinition)); Assert.ArgumentCondition(File.Exists(reportDefinition.TemplatePath), "Template file does not exist: {0}", reportDefinition.TemplatePath); string reportFilePath = Path.Combine(directory, reportDefinition.FileName); _msg.DebugFormat("Preparing html report model"); var reportModel = new HtmlReportModel(qualitySpecification, issueStatistics, verificationReport, directory, verificationReportFileName, issueGdbPath, issueMapFilePaths, htmlReportFileNames, qualitySpecificationReportFilePaths, reportDefinition); _msg.DebugFormat("Rendering html report based on template {0}", reportDefinition.TemplatePath); LiquidUtils.RegisterSafeType <HtmlReportModel>(); LiquidUtils.RegisterSafeType <HtmlTexts>(); string output = LiquidUtils.Render( reportDefinition.TemplatePath, new KeyValuePair <string, object>("report", reportModel), new KeyValuePair <string, object>("text", new HtmlTexts())); _msg.DebugFormat("Writing html report to {0}", reportFilePath); FileSystemUtils.WriteTextFile(output, reportFilePath); _msg.InfoFormat("Html report written to {0}", reportFilePath); }
/// <summary> /// Starts the grpc server, binds the <see cref="QualityVerificationGrpcImpl"/> together /// with the <see cref="IServiceHealth"/> implementation and returns a handle for both. /// </summary> /// <param name="arguments">The microserver command line / config arguments.</param> /// <param name="inputsFactory">The factory method that creates the /// <see cref="IBackgroundVerificationInputs"/> instance. If no factory is proveded, only /// stand-alone verification (such as XML) can be used.</param> /// <param name="markUnhealthyOnExceptions"></param> /// <returns></returns> public static StartedGrpcServer <QualityVerificationGrpcImpl> StartVerificationServer( [NotNull] MicroserverArguments arguments, [CanBeNull] Func <VerificationRequest, IBackgroundVerificationInputs> inputsFactory, bool markUnhealthyOnExceptions) { var healthService = new HealthServiceImpl(); IServiceHealth health = new ServiceHealth(healthService); LoadReportingGrpcImpl loadReporting = new LoadReportingGrpcImpl(); ServiceLoad serviceLoad = new ServiceLoad(arguments.MaxParallel); loadReporting.AllowMonitoring(nameof(QualityVerificationGrpc), serviceLoad); var verificationServiceImpl = new QualityVerificationGrpcImpl(inputsFactory, arguments.MaxParallel) { CurrentLoad = serviceLoad }; if (markUnhealthyOnExceptions) { verificationServiceImpl.Health = health; } health.SetStatus(verificationServiceImpl.GetType(), true); Grpc.Core.Server server = StartGrpcServer(arguments, verificationServiceImpl, healthService, loadReporting); _msg.InfoFormat("Service is listening on host {0}, port {1}.", arguments.HostName, arguments.Port); return(new StartedGrpcServer <QualityVerificationGrpcImpl>( server, verificationServiceImpl, health)); }
internal static void LogQualityVerification( [NotNull] QualityVerification verification) { try { var sb = new StringBuilder(); sb.AppendLine(verification.Cancelled ? "The quality verification was cancelled" : "Quality verified"); int conditionCount = verification.ConditionVerifications.Count; sb.AppendFormat("- {0:N0} quality condition{1} verified", conditionCount, conditionCount == 1 ? "" : "s"); sb.AppendLine(); int issueCount = verification.IssueCount; if (issueCount == 0) { sb.AppendLine("- No issues found"); } else { sb.AppendFormat(issueCount == 1 ? "- {0:N0} issue found" : "- {0:N0} issues found", issueCount); sb.AppendLine(); sb.AppendFormat(" - Errors: {0:N0}", verification.ErrorCount); sb.AppendLine(); sb.AppendFormat(" - Warnings: {0:N0}", verification.WarningCount); sb.AppendLine(); if (verification.RowsWithStopConditions > 0) { sb.AppendFormat(" - Number of rows with a stop condition error: {0:N0}", verification.RowsWithStopConditions); sb.AppendLine(); } } if (!verification.Cancelled) { sb.AppendLine(verification.Fulfilled ? "- The quality specification is fulfilled" : "- The quality specification is not fulfilled"); } if (verification.Fulfilled) { _msg.InfoFormat(sb.ToString()); } else { _msg.WarnFormat(sb.ToString()); } LogVerificationDetails(verification); } catch (Exception e) { _msg.Warn("Error writing report to log", e); // continue } }
public static void Import( [CanBeNull] string importWhereClause, [NotNull] IList <IObjectClass> targetExceptionClasses, [NotNull] IList <IObjectClass> importExceptionClasses, [NotNull] string importOriginValue, DateTime importDate) { IIssueTableFields importFields = GetImportFields(importExceptionClasses); IIssueTableFields targetFields = GetTargetFields(targetExceptionClasses); IDictionary <Guid, QualityConditionExceptions> targetExceptionsByConditionVersion; using (_msg.IncrementIndentation( "Reading existing exceptions in target workspace")) { targetExceptionsByConditionVersion = ReadTargetExceptions(targetExceptionClasses, targetFields); } var replacedExceptionObjects = new Dictionary <esriGeometryType, HashSet <int> >(); using (_msg.IncrementIndentation("Importing new exceptions from issue datasets...") ) { foreach (ITable importTable in importExceptionClasses.Cast <ITable>()) { using (_msg.IncrementIndentation("from {0}...", DatasetUtils.GetName(importTable))) { ITable targetTable = GetTargetTable(importTable, targetExceptionClasses); if (targetTable == null) { _msg.Warn( "No matching table in target workspace, ignoring import table"); continue; } var factory = new ExceptionObjectFactory( importTable, importFields, defaultStatus: ExceptionObjectStatus.Inactive); var newCount = 0; var updateCount = 0; var ignoredCount = 0; using (var writer = new ExceptionWriter(importTable, importFields, targetTable, targetFields)) { foreach (IRow row in GdbQueryUtils.GetRows(importTable, GetQueryFilter( importWhereClause), recycle: true)) { int matchCount; bool added = ImportException(row, importOriginValue, importDate, factory, targetExceptionsByConditionVersion, replacedExceptionObjects, writer, out matchCount); if (!added) { ignoredCount++; } else if (matchCount == 0) { newCount++; } else { updateCount++; } } } _msg.InfoFormat("{0:N0} exception(s) imported as new", newCount); _msg.InfoFormat("{0:N0} exception(s) imported as updates", updateCount); if (ignoredCount > 0) { _msg.InfoFormat("{0:N0} exception(s) ignored", ignoredCount); } } } } using (_msg.IncrementIndentation("Processing replaced exceptions...")) { foreach (ITable targetTable in targetExceptionClasses.Cast <ITable>()) { using (_msg.IncrementIndentation("Target table {0}...", DatasetUtils.GetName(targetTable))) { int fixedStatusCount; int updateCount = ProcessReplacedExceptions(targetTable, targetFields, replacedExceptionObjects, importDate, out fixedStatusCount); _msg.InfoFormat("{0:N0} replaced exception(s) updated", updateCount); if (fixedStatusCount > 0) { _msg.InfoFormat("Status value of {0:N0} old exception version(s) fixed", fixedStatusCount); } } } } }
public static IEnvelope GetFullExtent( [NotNull] IEnumerable <IGeoDataset> geoDatasets) { IEnvelope extentUnion = null; double maxXyTolerance = 0; foreach (IGeoDataset geoDataset in geoDatasets) { if (geoDataset == null) { continue; } IEnvelope datasetExtent = geoDataset.Extent; if (datasetExtent == null || datasetExtent.IsEmpty) { continue; } string datasetName = geoDataset is IDataset ? ((IDataset)geoDataset).Name : "raster"; _msg.DebugFormat("Adding extent of {0}: {1}", datasetName, GeometryUtils.Format(datasetExtent)); var featureClass = geoDataset as IFeatureClass; if (featureClass != null) { double xyTolerance; if (DatasetUtils.TryGetXyTolerance(featureClass, out xyTolerance)) { maxXyTolerance = Math.Max(maxXyTolerance, xyTolerance); } } if (extentUnion == null) { extentUnion = datasetExtent; } else { double previousArea = ((IArea)extentUnion).Area; extentUnion.Union(datasetExtent); double area = ((IArea)extentUnion).Area; if ((area - previousArea) / area > 0.5) { _msg.DebugFormat("Enlarged test extent by more than half: {0}", datasetName); } } } if (extentUnion != null) { _msg.InfoFormat("Full test extent of all datasets: {0}", GeometryUtils.Format(extentUnion)); extentUnion = EnsureMinimumSize(extentUnion, maxXyTolerance * 10); } return(extentUnion); }
public void ReportInfo(string format, params object[] args) { _msg.InfoFormat(format, args); }