001package org.hl7.fhir.r4b.utils;
002
003/*
004  Copyright (c) 2011+, HL7, Inc.
005  All rights reserved.
006  
007  Redistribution and use in source and binary forms, with or without modification, 
008  are permitted provided that the following conditions are met:
009    
010   * Redistributions of source code must retain the above copyright notice, this 
011     list of conditions and the following disclaimer.
012   * Redistributions in binary form must reproduce the above copyright notice, 
013     this list of conditions and the following disclaimer in the documentation 
014     and/or other materials provided with the distribution.
015   * Neither the name of HL7 nor the names of its contributors may be used to 
016     endorse or promote products derived from this software without specific 
017     prior written permission.
018  
019  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
020  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
021  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
022  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
023  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
024  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
025  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
026  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
027  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
028  POSSIBILITY OF SUCH DAMAGE.
029  
030 */
031
032
033
034import java.io.IOException;
035import java.io.InputStream;
036import java.net.MalformedURLException;
037import java.net.URISyntaxException;
038import java.util.List;
039import java.util.Locale;
040
041import org.hl7.fhir.exceptions.DefinitionException;
042import org.hl7.fhir.exceptions.FHIRException;
043import org.hl7.fhir.exceptions.FHIRFormatError;
044import org.hl7.fhir.r4b.elementmodel.Element;
045import org.hl7.fhir.r4b.elementmodel.Manager.FhirFormat;
046import org.hl7.fhir.r4b.model.CanonicalResource;
047import org.hl7.fhir.r4b.model.StructureDefinition;
048import org.hl7.fhir.r4b.utils.IResourceValidator.BundleValidationRule;
049import org.hl7.fhir.utilities.Utilities;
050import org.hl7.fhir.utilities.validation.ValidationMessage;
051
052import com.google.gson.JsonObject;
053
054/**
055 * Interface to the instance validator. This takes a resource, in one of many forms, and 
056 * checks whether it is valid
057   *  
058   * @author Grahame Grieve
059   *
060   */
061public interface IResourceValidator {
062
063  public class BundleValidationRule {
064    private String rule;
065    private String profile;
066    private boolean checked;
067    
068    public BundleValidationRule(String rule, String profile) {
069      super();
070      this.rule = rule;
071      this.profile = profile;
072    }
073    public String getRule() {
074      return rule;
075    }
076    public String getProfile() {
077      return profile;
078    }
079    public boolean isChecked() {
080      return checked;
081    }
082    public void setChecked(boolean checked) {
083      this.checked = checked;
084    }    
085  }
086
087  public enum ReferenceValidationPolicy {
088    IGNORE, CHECK_TYPE_IF_EXISTS, CHECK_EXISTS, CHECK_EXISTS_AND_TYPE, CHECK_VALID;
089    
090    public boolean checkExists() {
091      return this == CHECK_EXISTS_AND_TYPE || this == CHECK_EXISTS || this == CHECK_VALID || this == CHECK_TYPE_IF_EXISTS;
092    }
093    
094    public boolean checkType() {
095      return this == CHECK_TYPE_IF_EXISTS || this == CHECK_EXISTS_AND_TYPE || this == CHECK_VALID;
096    }
097    
098    public boolean checkValid() {
099      return this == CHECK_VALID;
100    }
101  }
102  
103  public interface IValidationProfileUsageTracker {
104    void recordProfileUsage(StructureDefinition profile, Object appContext, Element element);
105  }
106  
107
108  public interface IValidatorResourceFetcher {
109
110    Element fetch(Object appContext, String url) throws FHIRFormatError, DefinitionException, FHIRException, IOException;
111    ReferenceValidationPolicy validationPolicy(Object appContext, String path, String url);
112    boolean resolveURL(Object appContext, String path, String url, String type) throws IOException, FHIRException;
113
114    byte[] fetchRaw(String url) throws MalformedURLException, IOException; // for attachment checking
115
116    IValidatorResourceFetcher setLocale(Locale locale);
117    
118    
119    /**
120     * this is used when the validator encounters a reference to a structure definition, value set or code system at some random URL reference 
121     * while validating. 
122     *
123     *  Added in v5.2.2. return null to leave functionality as it was before then.
124     *  
125     * @param primitiveValue
126     * @return an R5 version of the resource
127     * @throws URISyntaxException 
128     */
129    CanonicalResource fetchCanonicalResource(String url) throws URISyntaxException;
130    
131    /**
132     * Whether to try calling fetchCanonicalResource for this reference (not whether it will succeed - just throw an exception from fetchCanonicalResource if it doesn't resolve. This is a policy thing.
133     * 
134     *  Added in v5.2.2. return false to leave functionality as it was before then.
135     *  
136     * @param url
137     * @return
138     */
139    boolean fetchesCanonicalResource(String url);
140  }
141  
142  public enum BestPracticeWarningLevel {
143    Ignore,
144    Hint,
145    Warning,
146    Error
147  }
148
149  public enum CheckDisplayOption {
150    Ignore,
151    Check,
152    CheckCaseAndSpace,
153    CheckCase,
154    CheckSpace
155  }
156
157  enum IdStatus {
158    OPTIONAL, REQUIRED, PROHIBITED
159  }
160  
161  /**
162   * how much to check displays for coded elements 
163   * @return
164   */
165  CheckDisplayOption getCheckDisplay();
166  void setCheckDisplay(CheckDisplayOption checkDisplay);
167
168  /**
169   * whether the resource must have an id or not (depends on context)
170   * 
171   * @return
172   */
173
174        IdStatus getResourceIdRule();
175        void setResourceIdRule(IdStatus resourceIdRule);
176  
177  /**
178   * whether the validator should enforce best practice guidelines
179   * as defined by various HL7 committees 
180   *  
181   */
182  BestPracticeWarningLevel getBestPracticeWarningLevel();
183  IResourceValidator setBestPracticeWarningLevel(BestPracticeWarningLevel value);
184
185  IValidatorResourceFetcher getFetcher();
186  IResourceValidator setFetcher(IValidatorResourceFetcher value);
187
188  IValidationProfileUsageTracker getTracker();
189  IResourceValidator setTracker(IValidationProfileUsageTracker value);
190
191  boolean isNoBindingMsgSuppressed();
192  IResourceValidator setNoBindingMsgSuppressed(boolean noBindingMsgSuppressed);
193  
194  public boolean isNoInvariantChecks();
195  public IResourceValidator setNoInvariantChecks(boolean value) ;
196  
197  public boolean isNoTerminologyChecks();
198  public IResourceValidator setNoTerminologyChecks(boolean noTerminologyChecks);
199
200  public boolean isNoExtensibleWarnings();
201  public IResourceValidator setNoExtensibleWarnings(boolean noExtensibleWarnings);
202  
203  /**
204   * Whether being unable to resolve a profile in found in Resource.meta.profile or ElementDefinition.type.profile or targetProfile is an error or just a warning
205   * @return
206   */
207  public boolean isErrorForUnknownProfiles();
208  public void setErrorForUnknownProfiles(boolean errorForUnknownProfiles);
209
210  public boolean isShowMessagesFromReferences();
211  public void setShowMessagesFromReferences(boolean value);
212
213  /** 
214   * this is used internally in the publishing stack to ensure that everything is water tight, but 
215   * this check is not necessary or appropriate at run time when the validator is hosted in HAPI
216   * @return
217   */
218  public boolean isWantCheckSnapshotUnchanged();
219  public void setWantCheckSnapshotUnchanged(boolean wantCheckSnapshotUnchanged);
220  
221  //FIXME: don't need that, gets never used?
222//  public String getValidationLanguage();
223//  public void setValidationLanguage(String value);
224  
225  /**
226   * It's common to see references such as Patient/234234 - these usually mean a reference to a Patient resource. 
227   * But there's no actual technical rule that it does, so the validator doesn't enforce that unless this setting is 
228   * set to true
229   * 
230   * @return
231   */
232  public boolean isAssumeValidRestReferences();
233  public void setAssumeValidRestReferences(boolean value);
234  
235  /** 
236   * if this is true, the validator will accept extensions and references to example.org and acme.com as 
237   * valid, on the basis that they are understood to be references to content that could exist in priniple but can't in practice
238   */
239  public boolean isAllowExamples();
240  public void setAllowExamples(boolean value) ;
241 
242  public boolean isNoCheckAggregation();
243  public void setNoCheckAggregation(boolean value);
244  /**
245   * CrumbTrail - whether the validator creates hints to 
246   * @return
247   */
248  public boolean isCrumbTrails();
249  public void setCrumbTrails(boolean crumbTrails);
250
251  public boolean isValidateValueSetCodesOnTxServer();
252  public void setValidateValueSetCodesOnTxServer(boolean value);
253
254  /** 
255   * Bundle validation rules allow for requesting particular entries in a bundle get validated against particular profiles
256   * Typically this is used from the command line to avoid having to construct profile just to validate a particular resource 
257   * in a bundle against a particular profile 
258   *  
259   * @return
260   */
261  public List<BundleValidationRule> getBundleValidationRules();
262  
263  /**
264   * Validate suite
265   *  
266   * you can validate one of the following representations of resources:
267   *  
268   * stream - provide a format - this is the preferred choice
269   * 
270   * Use one of these two if the content is known to be valid XML/JSON, and already parsed
271   * - a DOM element or Document
272   * - a Json Object
273   *  
274   * In order to use these, the content must already be parsed - e.g. it must syntactically valid    
275   * - a native resource
276   * - a elementmodel resource  
277   * 
278   * in addition, you can pass one or more profiles ti validate beyond the base standard - as structure definitions or canonical URLs 
279   * @throws IOException 
280   */
281  void validate(Object Context, List<ValidationMessage> errors, org.hl7.fhir.r4b.elementmodel.Element element) throws FHIRException;
282  void validate(Object Context, List<ValidationMessage> errors, org.hl7.fhir.r4b.elementmodel.Element element, String profile) throws FHIRException;
283  void validate(Object Context, List<ValidationMessage> errors, org.hl7.fhir.r4b.elementmodel.Element element, List<StructureDefinition> profiles) throws FHIRException;
284  
285  org.hl7.fhir.r4b.elementmodel.Element validate(Object Context, List<ValidationMessage> errors, InputStream stream, FhirFormat format) throws FHIRException;
286  org.hl7.fhir.r4b.elementmodel.Element validate(Object Context, List<ValidationMessage> errors, InputStream stream, FhirFormat format, String profile) throws FHIRException;
287  org.hl7.fhir.r4b.elementmodel.Element validate(Object Context, List<ValidationMessage> errors, InputStream stream, FhirFormat format, List<StructureDefinition> profiles) throws FHIRException;
288
289  org.hl7.fhir.r4b.elementmodel.Element validate(Object Context, List<ValidationMessage> errors, org.hl7.fhir.r4b.model.Resource resource) throws FHIRException;
290  org.hl7.fhir.r4b.elementmodel.Element validate(Object Context, List<ValidationMessage> errors, org.hl7.fhir.r4b.model.Resource resource, String profile) throws FHIRException;
291  org.hl7.fhir.r4b.elementmodel.Element validate(Object Context, List<ValidationMessage> errors, org.hl7.fhir.r4b.model.Resource resource, List<StructureDefinition> profiles) throws FHIRException;
292
293  org.hl7.fhir.r4b.elementmodel.Element validate(Object Context, List<ValidationMessage> errors, org.w3c.dom.Element element) throws FHIRException;
294  org.hl7.fhir.r4b.elementmodel.Element validate(Object Context, List<ValidationMessage> errors, org.w3c.dom.Element element, String profile) throws FHIRException;
295  org.hl7.fhir.r4b.elementmodel.Element validate(Object Context, List<ValidationMessage> errors, org.w3c.dom.Element element, List<StructureDefinition> profile) throws FHIRException;
296
297  org.hl7.fhir.r4b.elementmodel.Element validate(Object Context, List<ValidationMessage> errors, org.w3c.dom.Document document) throws FHIRException;
298  org.hl7.fhir.r4b.elementmodel.Element validate(Object Context, List<ValidationMessage> errors, org.w3c.dom.Document document, String profile) throws FHIRException;
299  org.hl7.fhir.r4b.elementmodel.Element validate(Object Context, List<ValidationMessage> errors, org.w3c.dom.Document document, List<StructureDefinition> profile) throws FHIRException;
300
301  org.hl7.fhir.r4b.elementmodel.Element validate(Object Context, List<ValidationMessage> errors, JsonObject object) throws FHIRException;
302  org.hl7.fhir.r4b.elementmodel.Element validate(Object Context, List<ValidationMessage> errors, JsonObject object, String profile) throws FHIRException;
303  org.hl7.fhir.r4b.elementmodel.Element validate(Object Context, List<ValidationMessage> errors, JsonObject object, List<StructureDefinition> profile) throws FHIRException; 
304
305
306}