001/*
002 * #%L
003 * HAPI FHIR - Core Library
004 * %%
005 * Copyright (C) 2014 - 2023 Smile CDR, Inc.
006 * %%
007 * Licensed under the Apache License, Version 2.0 (the "License");
008 * you may not use this file except in compliance with the License.
009 * You may obtain a copy of the License at
010 *
011 * http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing, software
014 * distributed under the License is distributed on an "AS IS" BASIS,
015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016 * See the License for the specific language governing permissions and
017 * limitations under the License.
018 * #L%
019 */
020package ca.uhn.fhir.parser;
021
022import ca.uhn.fhir.context.ConfigurationException;
023import ca.uhn.fhir.context.FhirContext;
024import ca.uhn.fhir.context.ParserOptions;
025import ca.uhn.fhir.model.api.IResource;
026import ca.uhn.fhir.rest.api.EncodingEnum;
027import org.hl7.fhir.instance.model.api.IAnyResource;
028import org.hl7.fhir.instance.model.api.IBaseResource;
029import org.hl7.fhir.instance.model.api.IIdType;
030
031import java.io.IOException;
032import java.io.InputStream;
033import java.io.Reader;
034import java.io.Writer;
035import java.util.Collection;
036import java.util.List;
037import java.util.Set;
038
039/**
040 * A parser, which can be used to convert between HAPI FHIR model/structure objects, and their respective String wire
041 * formats, in either XML or JSON.
042 * <p>
043 * Thread safety: <b>Parsers are not guaranteed to be thread safe</b>. Create a new parser instance for every thread or
044 * every message being parsed/encoded.
045 * </p>
046 */
047public interface IParser {
048
049        String encodeResourceToString(IBaseResource theResource) throws DataFormatException;
050
051        void encodeResourceToWriter(IBaseResource theResource, Writer theWriter) throws IOException, DataFormatException;
052
053        /**
054         * If not set to null (as is the default) this ID will be used as the ID in any
055         * resources encoded by this parser
056         */
057        IIdType getEncodeForceResourceId();
058
059        /**
060         * When encoding, force this resource ID to be encoded as the resource ID
061         */
062        IParser setEncodeForceResourceId(IIdType theForceResourceId);
063
064        /**
065         * Which encoding does this parser instance produce?
066         */
067        EncodingEnum getEncoding();
068
069        /**
070         * Gets the preferred types, as set using {@link #setPreferTypes(List)}
071         *
072         * @return Returns the preferred types, or <code>null</code>
073         * @see #setPreferTypes(List)
074         */
075        List<Class<? extends IBaseResource>> getPreferTypes();
076
077        /**
078         * If set, when parsing resources the parser will try to use the given types when possible, in
079         * the order that they are provided (from highest to lowest priority). For example, if a custom
080         * type which declares to implement the Patient resource is passed in here, and the
081         * parser is parsing a Bundle containing a Patient resource, the parser will use the given
082         * custom type.
083         * <p>
084         * This feature is related to, but not the same as the
085         * {@link FhirContext#setDefaultTypeForProfile(String, Class)} feature.
086         * <code>setDefaultTypeForProfile</code> is used to specify a type to be used
087         * when a resource explicitly declares support for a given profile. This
088         * feature specifies a type to be used irrespective of the profile declaration
089         * in the metadata statement.
090         * </p>
091         *
092         * @param thePreferTypes The preferred types, or <code>null</code>
093         */
094        void setPreferTypes(List<Class<? extends IBaseResource>> thePreferTypes);
095
096        /**
097         * Returns true if resource IDs should be omitted
098         *
099         * @see #setOmitResourceId(boolean)
100         * @since 1.1
101         */
102        boolean isOmitResourceId();
103
104        /**
105         * If set to <code>true</code> (default is <code>false</code>) the ID of any resources being encoded will not be
106         * included in the output. Note that this does not apply to contained resources, only to root resources. In other
107         * words, if this is set to <code>true</code>, contained resources will still have local IDs but the outer/containing
108         * ID will not have an ID.
109         * <p>
110         * If the resource being encoded is a Bundle or Parameters resource, this setting only applies to the
111         * outer resource being encoded, not any resources contained wihthin.
112         * </p>
113         *
114         * @param theOmitResourceId Should resource IDs be omitted
115         * @return Returns a reference to <code>this</code> parser so that method calls can be chained together
116         * @since 1.1
117         */
118        IParser setOmitResourceId(boolean theOmitResourceId);
119
120        /**
121         * If set to <code>true<code> (which is the default), resource references containing a version
122         * will have the version removed when the resource is encoded. This is generally good behaviour because
123         * in most situations, references from one resource to another should be to the resource by ID, not
124         * by ID and version. In some cases though, it may be desirable to preserve the version in resource
125         * links. In that case, this value should be set to <code>false</code>.
126         *
127         * @return Returns the parser instance's configuration setting for stripping versions from resource references when
128         * encoding. This method will retun <code>null</code> if no value is set, in which case
129         * the value from the {@link ParserOptions} will be used (default is <code>true</code>)
130         * @see ParserOptions
131         */
132        Boolean getStripVersionsFromReferences();
133
134        /**
135         * If set to <code>true<code> (which is the default), resource references containing a version
136         * will have the version removed when the resource is encoded. This is generally good behaviour because
137         * in most situations, references from one resource to another should be to the resource by ID, not
138         * by ID and version. In some cases though, it may be desirable to preserve the version in resource
139         * links. In that case, this value should be set to <code>false</code>.
140         * <p>
141         * This method provides the ability to globally disable reference encoding. If finer-grained
142         * control is needed, use {@link #setDontStripVersionsFromReferencesAtPaths(String...)}
143         * </p>
144         *
145         * @param theStripVersionsFromReferences Set this to <code>false<code> to prevent the parser from removing resource versions from references (or <code>null</code> to apply the default setting from the {@link ParserOptions}
146         * @return Returns a reference to <code>this</code> parser so that method calls can be chained together
147         * @see #setDontStripVersionsFromReferencesAtPaths(String...)
148         * @see ParserOptions
149         */
150        IParser setStripVersionsFromReferences(Boolean theStripVersionsFromReferences);
151
152        /**
153         * Is the parser in "summary mode"? See {@link #setSummaryMode(boolean)} for information
154         *
155         * @see {@link #setSummaryMode(boolean)} for information
156         */
157        boolean isSummaryMode();
158
159        /**
160         * If set to <code>true</code> (default is <code>false</code>) only elements marked by the FHIR specification as
161         * being "summary elements" will be included.
162         *
163         * @return Returns a reference to <code>this</code> parser so that method calls can be chained together
164         */
165        IParser setSummaryMode(boolean theSummaryMode);
166
167        /**
168         * Parses a resource
169         *
170         * @param theResourceType The resource type to use. This can be used to explicitly specify a class which extends a built-in type
171         *                        (e.g. a custom type extending the default Patient class)
172         * @param theReader       The reader to parse input from. Note that the Reader will not be closed by the parser upon completion.
173         * @return A parsed resource
174         * @throws DataFormatException If the resource can not be parsed because the data is not recognized or invalid for any reason
175         */
176        <T extends IBaseResource> T parseResource(Class<T> theResourceType, Reader theReader) throws DataFormatException;
177
178        /**
179         * Parses a resource
180         *
181         * @param theResourceType The resource type to use. This can be used to explicitly specify a class which extends a built-in type
182         *                        (e.g. a custom type extending the default Patient class)
183         * @param theInputStream  The InputStream to parse input from, <b>with an implied charset of UTF-8</b>. Note that the InputStream will not be closed by the parser upon completion.
184         * @return A parsed resource
185         * @throws DataFormatException If the resource can not be parsed because the data is not recognized or invalid for any reason
186         */
187        <T extends IBaseResource> T parseResource(Class<T> theResourceType, InputStream theInputStream) throws DataFormatException;
188
189        /**
190         * Parses a resource
191         *
192         * @param theResourceType The resource type to use. This can be used to explicitly specify a class which extends a built-in type
193         *                        (e.g. a custom type extending the default Patient class)
194         * @param theString       The string to parse
195         * @return A parsed resource
196         * @throws DataFormatException If the resource can not be parsed because the data is not recognized or invalid for any reason
197         */
198        <T extends IBaseResource> T parseResource(Class<T> theResourceType, String theString) throws DataFormatException;
199
200        /**
201         * Parses a resource
202         *
203         * @param theReader The reader to parse input from. Note that the Reader will not be closed by the parser upon completion.
204         * @return A parsed resource. Note that the returned object will be an instance of {@link IResource} or
205         * {@link IAnyResource} depending on the specific FhirContext which created this parser.
206         * @throws DataFormatException If the resource can not be parsed because the data is not recognized or invalid for any reason
207         */
208        IBaseResource parseResource(Reader theReader) throws ConfigurationException, DataFormatException;
209
210        /**
211         * Parses a resource
212         *
213         * @param theInputStream The InputStream to parse input from (charset is assumed to be UTF-8).
214         *                       Note that the stream will not be closed by the parser upon completion.
215         * @return A parsed resource. Note that the returned object will be an instance of {@link IResource} or
216         * {@link IAnyResource} depending on the specific FhirContext which created this parser.
217         * @throws DataFormatException If the resource can not be parsed because the data is not recognized or invalid for any reason
218         */
219        IBaseResource parseResource(InputStream theInputStream) throws ConfigurationException, DataFormatException;
220
221        /**
222         * Parses a resource
223         *
224         * @param theMessageString The string to parse
225         * @return A parsed resource. Note that the returned object will be an instance of {@link IResource} or
226         * {@link IAnyResource} depending on the specific FhirContext which created this parser.
227         * @throws DataFormatException If the resource can not be parsed because the data is not recognized or invalid for any reason
228         */
229        IBaseResource parseResource(String theMessageString) throws ConfigurationException, DataFormatException;
230
231        /**
232         * If provided, specifies the elements which should NOT be encoded. Valid values for this
233         * field would include:
234         * <ul>
235         * <li><b>Patient</b> - Don't encode patient and all its children</li>
236         * <li><b>Patient.name</b> - Don't encode the patient's name</li>
237         * <li><b>Patient.name.family</b> - Don't encode the patient's family name</li>
238         * <li><b>*.text</b> - Don't encode the text element on any resource (only the very first position may contain a
239         * wildcard)</li>
240         * </ul>
241         * <p>
242         * DSTU2 note: Note that values including meta, such as <code>Patient.meta</code>
243         * will work for DSTU2 parsers, but values with subelements on meta such
244         * as <code>Patient.meta.lastUpdated</code> will only work in
245         * DSTU3+ mode.
246         * </p>
247         *
248         * @param theDontEncodeElements The elements to encode
249         * @see #setEncodeElements(Set)
250         */
251        IParser setDontEncodeElements(Collection<String> theDontEncodeElements);
252
253        /**
254         * If provided, specifies the elements which should be encoded, to the exclusion of all others. Valid values for this
255         * field would include:
256         * <ul>
257         * <li><b>Patient</b> - Encode patient and all its children</li>
258         * <li><b>Patient.name</b> - Encode only the patient's name</li>
259         * <li><b>Patient.name.family</b> - Encode only the patient's family name</li>
260         * <li><b>*.text</b> - Encode the text element on any resource (only the very first position may contain a
261         * wildcard)</li>
262         * <li><b>*.(mandatory)</b> - This is a special case which causes any mandatory fields (min > 0) to be encoded</li>
263         * </ul>
264         *
265         * @param theEncodeElements The elements to encode
266         * @see #setDontEncodeElements(Collection)
267         */
268        IParser setEncodeElements(Set<String> theEncodeElements);
269
270        /**
271         * If set to <code>true</code> (default is false), the values supplied
272         * to {@link #setEncodeElements(Set)} will not be applied to the root
273         * resource (typically a Bundle), but will be applied to any sub-resources
274         * contained within it (i.e. search result resources in that bundle)
275         */
276        boolean isEncodeElementsAppliesToChildResourcesOnly();
277
278        /**
279         * If set to <code>true</code> (default is false), the values supplied
280         * to {@link #setEncodeElements(Set)} will not be applied to the root
281         * resource (typically a Bundle), but will be applied to any sub-resources
282         * contained within it (i.e. search result resources in that bundle)
283         */
284        void setEncodeElementsAppliesToChildResourcesOnly(boolean theEncodeElementsAppliesToChildResourcesOnly);
285
286        /**
287         * Registers an error handler which will be invoked when any parse errors are found
288         *
289         * @param theErrorHandler The error handler to set. Must not be null.
290         */
291        IParser setParserErrorHandler(IParserErrorHandler theErrorHandler);
292
293        /**
294         * Sets the "pretty print" flag, meaning that the parser will encode resources with human-readable spacing and
295         * newlines between elements instead of condensing output as much as possible.
296         *
297         * @param thePrettyPrint The flag
298         * @return Returns an instance of <code>this</code> parser so that method calls can be chained together
299         */
300        IParser setPrettyPrint(boolean thePrettyPrint);
301
302        /**
303         * Sets the server's base URL used by this parser. If a value is set, resource references will be turned into
304         * relative references if they are provided as absolute URLs but have a base matching the given base.
305         *
306         * @param theUrl The base URL, e.g. "http://example.com/base"
307         * @return Returns an instance of <code>this</code> parser so that method calls can be chained together
308         */
309        IParser setServerBaseUrl(String theUrl);
310
311        /**
312         * If set to <code>true</code> (which is the default), the Bundle.entry.fullUrl will override the Bundle.entry.resource's
313         * resource id if the fullUrl is defined. This behavior happens when parsing the source data into a Bundle object. Set this
314         * to <code>false</code> if this is not the desired behavior (e.g. the client code wishes to perform additional
315         * validation checks between the fullUrl and the resource id).
316         *
317         * @param theOverrideResourceIdWithBundleEntryFullUrl Set this to <code>false</code> to prevent the parser from overriding resource ids with the
318         *                                                    Bundle.entry.fullUrl (or <code>null</code> to apply the default setting from the {@link ParserOptions})
319         * @return Returns a reference to <code>this</code> parser so that method calls can be chained together
320         * @see ParserOptions
321         */
322        IParser setOverrideResourceIdWithBundleEntryFullUrl(Boolean theOverrideResourceIdWithBundleEntryFullUrl);
323
324        /**
325         * If set to <code>true</code> (default is <code>false</code>), narratives will not be included in the encoded
326         * values.
327         */
328        IParser setSuppressNarratives(boolean theSuppressNarratives);
329
330        /**
331         * Returns the value supplied to {@link IParser#setDontStripVersionsFromReferencesAtPaths(String...)}
332         * or <code>null</code> if no value has been set for this parser (in which case the default from
333         * the {@link ParserOptions} will be used}
334         *
335         * @see #setDontStripVersionsFromReferencesAtPaths(String...)
336         * @see #setStripVersionsFromReferences(Boolean)
337         * @see ParserOptions
338         */
339        Set<String> getDontStripVersionsFromReferencesAtPaths();
340
341        /**
342         * If supplied value(s), any resource references at the specified paths will have their
343         * resource versions encoded instead of being automatically stripped during the encoding
344         * process. This setting has no effect on the parsing process.
345         * <p>
346         * This method provides a finer-grained level of control than {@link #setStripVersionsFromReferences(Boolean)}
347         * and any paths specified by this method will be encoded even if {@link #setStripVersionsFromReferences(Boolean)}
348         * has been set to <code>true</code> (which is the default)
349         * </p>
350         *
351         * @param thePaths A collection of paths for which the resource versions will not be removed automatically
352         *                 when serializing, e.g. "Patient.managingOrganization" or "AuditEvent.object.reference". Note that
353         *                 only resource name and field names with dots separating is allowed here (no repetition
354         *                 indicators, FluentPath expressions, etc.). Set to <code>null</code> to use the value
355         *                 set in the {@link ParserOptions}
356         * @return Returns a reference to <code>this</code> parser so that method calls can be chained together
357         * @see #setStripVersionsFromReferences(Boolean)
358         * @see ParserOptions
359         */
360        IParser setDontStripVersionsFromReferencesAtPaths(String... thePaths);
361
362        /**
363         * If supplied value(s), any resource references at the specified paths will have their
364         * resource versions encoded instead of being automatically stripped during the encoding
365         * process. This setting has no effect on the parsing process.
366         * <p>
367         * This method provides a finer-grained level of control than {@link #setStripVersionsFromReferences(Boolean)}
368         * and any paths specified by this method will be encoded even if {@link #setStripVersionsFromReferences(Boolean)}
369         * has been set to <code>true</code> (which is the default)
370         * </p>
371         *
372         * @param thePaths A collection of paths for which the resource versions will not be removed automatically
373         *                 when serializing, e.g. "Patient.managingOrganization" or "AuditEvent.object.reference". Note that
374         *                 only resource name and field names with dots separating is allowed here (no repetition
375         *                 indicators, FluentPath expressions, etc.). Set to <code>null</code> to use the value
376         *                 set in the {@link ParserOptions}
377         * @return Returns a reference to <code>this</code> parser so that method calls can be chained together
378         * @see #setStripVersionsFromReferences(Boolean)
379         * @see ParserOptions
380         */
381        IParser setDontStripVersionsFromReferencesAtPaths(Collection<String> thePaths);
382
383}