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