
001package org.hl7.fhir.r5.utils.validation; 002 003import java.util.EnumSet; 004import java.util.HashSet; 005import java.util.List; 006import java.util.Set; 007 008import lombok.Getter; 009import org.hl7.fhir.r5.elementmodel.Element; 010import org.hl7.fhir.r5.model.ElementDefinition; 011import org.hl7.fhir.r5.model.StructureDefinition; 012import org.hl7.fhir.r5.model.ValueSet; 013import org.hl7.fhir.r5.utils.validation.constants.ContainedReferenceValidationPolicy; 014import org.hl7.fhir.r5.utils.validation.constants.ReferenceValidationPolicy; 015import org.hl7.fhir.utilities.MarkedToMoveToAdjunctPackage; 016import org.hl7.fhir.utilities.validation.ValidationMessage; 017import org.hl7.fhir.r5.utils.validation.constants.CodedContentValidationPolicy; 018import org.hl7.fhir.r5.utils.validation.IValidationPolicyAdvisor.ElementValidationAction; 019import org.hl7.fhir.r5.utils.validation.IValidationPolicyAdvisor.ReferenceDestinationType; 020import org.hl7.fhir.r5.utils.validation.IValidationPolicyAdvisor.SpecialValidationAction; 021import org.hl7.fhir.r5.utils.validation.IValidationPolicyAdvisor.SpecialValidationRule; 022import org.hl7.fhir.r5.utils.validation.constants.BindingKind; 023 024@MarkedToMoveToAdjunctPackage 025public interface IValidationPolicyAdvisor { 026 027 028 029 public enum ReferenceDestinationType { 030 CONTAINED, // the reference points to a contained resource in the resource being validated 031 INTERNAL, // the reference points to another resource in the scope of what is being validated 032 EXTERNAL; // the reference points outside what is being validated. 033 // Note that at the point this is called, the validator has not tried to see whether the reference 034 // is resolvable based on the resources made available to it 035 036 public String toCode() { 037 switch (this) { 038 case CONTAINED: return "contained"; 039 case EXTERNAL: return "external"; 040 case INTERNAL: return "internal"; 041 } 042 return null; 043 } 044 } 045 046 public IValidationPolicyAdvisor getPolicyAdvisor(); 047 public IValidationPolicyAdvisor setPolicyAdvisor(IValidationPolicyAdvisor policyAdvisor); 048 049 /** 050 * Internal use, for chaining advisors - if you define an implementation, you return the default policy. 051 * Usually, this is the policy for the operating policy advisor in place before your implementation is 052 * registered, so keep a reference to that and pass the value through 053 * 054 * @return 055 */ 056 ReferenceValidationPolicy getReferencePolicy(); 057 058 /** 059 * a list of servers for which the ReferenceValidationPolicy will be CHECK_VALID. 060 * if the reference is to a server not in this list, getReferencePolicy() applies 061 */ 062 Set<String> getCheckReferencesTo(); 063 064 /** 065 * Return true if the validation message for this message id should not be reported 066 * 067 * Note that this is generally a pretty blunt instrument. E.g. you might want to suppress 068 * errors associated with a particular code system, but this can only suppress errors associated 069 * with all code systems 070 * 071 * @param path - the current path of the element 072 * @param messageId - the message id (from messages.properties) 073 * @return true if the validator should ignore the message 074 */ 075 boolean isSuppressMessageId(String path, String messageId); 076 077 /** 078 * Whether to try validating a reference, and if so, how much validation to apply 079 * 080 * @param validator 081 * @param appContext What was originally provided from the app for it's context 082 * @param path Path that led us to this resource. 083 * @param url Url of the profile the container resource is being validated against. 084 * @return {@link ReferenceValidationPolicy} 085 */ 086 ReferenceValidationPolicy policyForReference(IResourceValidator validator, 087 Object appContext, 088 String path, 089 String url, 090 ReferenceDestinationType destinationType); 091 092 /** 093 * whether to validate a contained resource. Note that if there's a reference to the 094 * contained resource (and there should be), then the policyForReference will override 095 * this value (e.g. if the result of policyForReference is CHECK_VALID, then the 096 * resource will be validated, irrespective of the value of policyForContained) 097 * 098 * //TODO pass through the actual containing Element as opposed to the type, id 099 * @param validator 100 * @param appContext What was originally provided from the app for it's context 101 * @param containerType Type of the resources that contains the resource being validated 102 * @param containerId Id of the resources that contains the resource being validated 103 * @param containingResourceType Type of the resource that will be validated (BUNDLE_ENTRY, BUNDLE_OUTCOME, CONTAINED_RESOURCE, PARAMETER) 104 * @param path Path that led us to this resource. 105 * @param url Url of the profile the container resource is being validated against. 106 * @return {@link ReferenceValidationPolicy} 107 */ 108 ContainedReferenceValidationPolicy policyForContained(IResourceValidator validator, 109 Object appContext, 110 StructureDefinition structure, 111 ElementDefinition element, 112 String containerType, 113 String containerId, 114 Element.SpecialElement containingResourceType, 115 String path, 116 String url); 117 118 119 public enum ResourceValidationAction { 120 BaseType, 121 StatedProfiles, 122 MetaProfiles, 123 GlobalProfiles 124 } 125 126 EnumSet<ResourceValidationAction> policyForResource(IResourceValidator validator, 127 Object appContext, 128 StructureDefinition type, 129 String path); 130 131 public enum ElementValidationAction { 132 Cardinality, // though you can't stop slice matching cardinality checks from happening 133 Invariants, 134 Bindings, 135 AdditionalBindings, 136 StatusCheck 137 } 138 139 EnumSet<ElementValidationAction> policyForElement(IResourceValidator validator, 140 Object appContext, 141 StructureDefinition structure, 142 ElementDefinition element, 143 String path); 144 145 public enum AdditionalBindingPurpose { 146 Minimum, 147 Required, 148 Extensible, 149 Current, 150 Preferred, 151 Ui 152 } 153 154 public enum CodedContentValidationAction { 155 VSCheck, 156 VSCheckThisCode, 157 NotFound, 158 InvalidCode, 159 InvalidDisplay, 160 CannotInfer, 161 CodeRule, 162 VSInvalid, 163 StatusCheck 164 } 165 166 /** 167 * Called before validating a concept in an instance against the terminology sub-system 168 * 169 * There's two reasons to use this policy advisor feature: 170 * - save time by not calling the terminology server for validation that don't bring value to the context calling the validation 171 * - suppressing known issues from being listed as a problem 172 * 173 * Note that the terminology subsystem has two parts: a mini-terminology server running inside the 174 * validator, and then calling out to an external terminology service (usually tx.fhir.org, though you 175 * run your own local copy of this - see https://confluence.hl7.org/display/FHIR/Running+your+own+copy+of+tx.fhir.org). 176 * You can't tell which subsystem will handle the terminology validation directly from the content provided here which 177 * subsystem will be called - you'll haev to investigate based on your set up. (matters, since it makes a huge performance 178 * difference, though it also depends on caching, and the impact of caching is also not known at this point) 179 * 180 * @param validator 181 * @param appContext What was originally provided from the app for it's context 182 * @param stackPath The current path for the stack. Note that the because of cross-references and FHIRPath conformsTo() statements, the stack can wind through the content unpredictably. 183 * @param definition the definition being validated against (might be useful: ElementDefinition.base.path, ElementDefinition.type, ElementDefinition.binding 184 * @param structure The structure definition that contains the element definition being validated against (may be from the base spec, may be from a profile) 185 * @param kind The part of the binding being validated 186 * @param valueSet The value set for the binding part that's being validated 187 * @param systems A list of canonical URls (including versions if known) of the systems in the instance that's being validated. Note that if a plain code is being validated, then there'll be no known system when this is called (systems will be empty, not null) 188 * @return {@link CodedContentValidationPolicy} 189 */ 190 EnumSet<CodedContentValidationAction> policyForCodedContent(IResourceValidator validator, 191 Object appContext, 192 String stackPath, 193 ElementDefinition definition, 194 StructureDefinition structure, 195 BindingKind kind, 196 AdditionalBindingPurpose purpose, 197 ValueSet valueSet, 198 List<String> systems); 199 200 public enum SpecialValidationAction { 201 CHECK_RULE, IGNORE_RULE 202 } 203 204 public enum SpecialValidationRule { 205 CODESYSTEM_METADATA_CHECKS, // check code system metadata - including count, hierarchy, etc 206 CODESYSTEM_SUPPLEMENT_CHECKS, // check supplement integrity 207 CODESYSTEM_VALUESET_CHECKS, // check that the designated value set actually is the right value set 208 CODESYSTEM_PROPERTY_CHECKS, // check that the properties are defined properly 209 CODESYSTEM_DESIGNATION_CHECKS, // check that concept designations (element = concept) 210 VALUESET_METADATA_CHECKS, // check the value set metadata (element = include/exclude) 211 VALUESET_SYSTEM_CHECKS, // check that value set against the system definition (element = include/exclude) 212 VALUESET_IMPORT_CHECKS // check the value set imports (element = include/exclude) 213 } 214 215 /** 216 * This routine gives control over the execution of the advanced validator functionality that applies to particular kinds of resources 217 * 218 * @param validator 219 * @param appContext What was originally provided from the app for it's context 220 * @param rule The rule that is to be executed (actually often a group of checks) 221 * @param stackPath The current path for the stack. Note that the because of cross-references and FHIRPath conformsTo() statements, the stack can wind through the content unpredictably. 222 * @param resource The resource that is being checked 223 * @param element The element that is being checked (if relevant for the rule) 224 * @return whether to execute the rule or not 225 */ 226 SpecialValidationAction policyForSpecialValidation(IResourceValidator validator, 227 Object appContext, 228 SpecialValidationRule rule, 229 String stackPath, 230 Element resource, 231 Element element); 232 233 /** 234 * This is called after a resource has been validated against the base structure, 235 * but before it's validated against any profiles specified in .meta.profile or in the parameters. 236 * This can be used to determine what additional profiles should be applied, for instance 237 * those derived from the http://hl7.org/fhir/tools/StructureDefinition/profile-mapping extension 238 * 239 * Note that the resource is an elementModel resource, not an IBaseResource. This is less convenient to 240 * read values from, but is the way the internals of the validator works (e.g. the version of the resource 241 * might be any version from R2-R6) 242 * 243 * The base implementation applies the mandatory vital signs to observations that have LOINC or SNOMED CT 244 * codes that indicate that they are vital signs. Note that these profiles are not optional; all vital sign resources 245 * are required to conform to them. For this reason, if you're providing your own policy advisor, you should 246 * keep a reference to the default one, or call BasePolicyAdvisorForFullValidation directly. You can choose not to, 247 * but if you do, you are allowing for resources that deviate from the FHIR specification (in a way that the 248 * community considers clinically unsafe, since it means that software (probably) will miss vital signs for 249 * patients). 250 * 251 * @param validator 252 * @param appContext What was originally provided from the app for it's context 253 * @param stackPath The current path for the stack. Note that the because of cross-references and FHIRPath conformsTo() statements, the stack can wind through the content unpredictably. 254 * @param definition the definition being validated against (might be useful: ElementDefinition.base.path, ElementDefinition.type, ElementDefinition.binding 255 * @param structure The structure definition that contains the element definition being validated against (may be from the base spec, may be from a profile) 256 * @param resource The actual resource (as an element model) so that the implementation can inspect the values in order to decide what profiles to apply 257 * @param valid true if the resource is so far considered valid 258 * @param messages all the validation messages. Implementations can inspect this, but the real purpose is to populate the messages with information messages explaining why profiles were (or weren't) applied 259 * @return 260 */ 261 List<StructureDefinition> getImpliedProfilesForResource(IResourceValidator validator, 262 Object appContext, 263 String stackPath, 264 ElementDefinition definition, 265 StructureDefinition structure, 266 Element resource, 267 boolean valid, 268 IMessagingServices msgServices, 269 List<ValidationMessage> messages); 270 271 272}