/// <summary> /// Create model /// </summary> /// <param name="document"></param> public static ApplicationInfoModel ToServiceModel( this ApplicationDocument document) { return(new ApplicationInfoModel { ApplicationId = document.ApplicationId, State = document.ApplicationState, ApplicationUri = document.ApplicationUri, ApplicationName = document.GetApplicationName(), ApplicationType = document.ApplicationType, LocalizedNames = GetLocalizedText(document.ApplicationNames), ProductUri = document.ProductUri, DiscoveryUrls = document.DiscoveryUrls.ToHashSetSafe(), Capabilities = GetServerCapabilities(document.ServerCapabilities), GatewayServerUri = document.GatewayServerUri, DiscoveryProfileUri = document.DiscoveryProfileUri, NotSeenSince = document.NotSeenSince, Approved = ToServiceModel( document.ApproveTime, document.ApproveAuthorityId), Created = ToServiceModel( document.CreateTime, document.CreateAuthorityId), Updated = ToServiceModel( document.UpdateTime, document.UpdateAuthorityId), }); }
/// <summary> /// Validates all fields in an application record to be consistent with /// the OPC UA specification. /// </summary> /// <param name="document">The application</param> public static void Validate(this ApplicationDocument document) { if (document == null) { throw new ArgumentNullException(nameof(document)); } if (document.ApplicationUri == null) { throw new ArgumentNullException(nameof(document.ApplicationUri)); } if (!Uri.IsWellFormedUriString(document.ApplicationUri, UriKind.Absolute)) { throw new ArgumentException(document.ApplicationUri + " is not a valid URI.", nameof(document.ApplicationUri)); } if ((document.ApplicationType < ApplicationType.Server) || (document.ApplicationType > ApplicationType.DiscoveryServer)) { throw new ArgumentException(document.ApplicationType.ToString() + " is not a valid ApplicationType.", nameof(document.ApplicationType)); } if (string.IsNullOrEmpty(document.GetApplicationName())) { throw new ArgumentException( "At least one ApplicationName must be provided.", nameof(document.ApplicationNames)); } if (string.IsNullOrEmpty(document.ProductUri)) { throw new ArgumentException( "A ProductUri must be provided.", nameof(document.ProductUri)); } if (!Uri.IsWellFormedUriString(document.ProductUri, UriKind.Absolute)) { throw new ArgumentException(document.ProductUri + " is not a valid URI.", nameof(document.ProductUri)); } if (document.DiscoveryUrls != null) { foreach (var discoveryUrl in document.DiscoveryUrls) { if (string.IsNullOrEmpty(discoveryUrl)) { continue; } if (!Uri.IsWellFormedUriString(discoveryUrl, UriKind.Absolute)) { throw new ArgumentException(discoveryUrl + " is not a valid URL.", nameof(document.DiscoveryUrls)); } // TODO: check for https:/hostname:62541, typo is not detected here } } if ((int)document.ApplicationType != (int)Opc.Ua.ApplicationType.Client) { if (document.DiscoveryUrls == null || document.DiscoveryUrls.Length == 0) { throw new ArgumentException( "At least one DiscoveryUrl must be provided.", nameof(document.DiscoveryUrls)); } if (string.IsNullOrEmpty(document.ServerCapabilities)) { throw new ArgumentException( "At least one Server Capability must be provided.", nameof(document.ServerCapabilities)); } // TODO: check for valid servercapabilities } else { if (document.DiscoveryUrls != null && document.DiscoveryUrls.Length > 0) { throw new ArgumentException( "DiscoveryUrls must not be specified for clients.", nameof(document.DiscoveryUrls)); } } }