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}