/// <summary> /// Validates the instance, declared and stated profiles for consistenty. /// </summary> /// <returns></returns> public OperationOutcome Validate() { if (_lastValidationOutcome != null) { return(_lastValidationOutcome); } var outcome = new OperationOutcome(); // Resolve input profiles first (note: this is cached) var resolutionOutcome = Resolve(); if (!resolutionOutcome.Success) { return(resolutionOutcome); } else { outcome.Add(resolutionOutcome); } // If we have an instance type, it should be compatible with the declared type on the definition and the stated profiles if (InstanceType != null) { if (DeclaredType != null) { if (!ModelInfo.IsInstanceTypeFor(DeclaredType.BaseType(), InstanceType.BaseType())) { outcome.AddIssue($"The declared type of the element ({DeclaredType.ReadableName()}) is incompatible with that of the instance ('{InstanceType.ReadableName()}')", Issue.CONTENT_ELEMENT_HAS_INCORRECT_TYPE, _path); } } foreach (var type in StatedProfiles) { if (!ModelInfo.IsInstanceTypeFor(type.BaseType(), InstanceType.BaseType())) { outcome.AddIssue($"Instance of type '{InstanceType.ReadableName()}' is incompatible with the stated profile '{type.Url}' which is constraining constrained type '{type.ReadableName()}'", Issue.CONTENT_ELEMENT_HAS_INCORRECT_TYPE, _path); } } } // All stated profiles should be profiling the same core type if (StatedProfiles.Any()) { var baseTypes = StatedProfiles.Select(p => p.BaseType()).Distinct().ToList(); if (baseTypes.Count > 1) { var combinedNames = String.Join(" and ", baseTypes.Select(bt => bt.GetLiteral())); outcome.AddIssue($"The stated profiles are constraints on multiple different core types ({combinedNames}), which can never be satisfied.", Issue.CONTENT_MISMATCHING_PROFILES, _path); } else { // The stated profiles should be compatible with the declared type of the element if (DeclaredType != null) { if (!ModelInfo.IsInstanceTypeFor(DeclaredType.BaseType(), baseTypes.Single())) { outcome.AddIssue($"The stated profiles are all constraints on '{baseTypes.Single()}', which is incompatible with the declared type '{DeclaredType.ReadableName()}' of the element", Issue.CONTENT_MISMATCHING_PROFILES, _path); } } } } _lastValidationOutcome = outcome; return(outcome); }