001/*
002 * #%L
003 * HAPI FHIR - Core Library
004 * %%
005 * Copyright (C) 2014 - 2024 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 ca.uhn.fhir.util.CollectionUtil;
028import jakarta.annotation.Nonnull;
029import jakarta.annotation.Nullable;
030import org.hl7.fhir.instance.model.api.IAnyResource;
031import org.hl7.fhir.instance.model.api.IBase;
032import org.hl7.fhir.instance.model.api.IBaseResource;
033import org.hl7.fhir.instance.model.api.IIdType;
034
035import java.io.IOException;
036import java.io.InputStream;
037import java.io.Reader;
038import java.io.Writer;
039import java.util.Collection;
040import java.util.List;
041import java.util.Set;
042
043/**
044 * A parser, which can be used to convert between HAPI FHIR model/structure objects, and their respective String wire
045 * formats, in either XML or JSON.
046 * <p>
047 * Thread safety: <b>Parsers are not guaranteed to be thread safe</b>. Create a new parser instance for every thread or
048 * every message being parsed/encoded.
049 * </p>
050 */
051public interface IParser {
052
053        /**
054         * Encodes a resource using the parser's given encoding format.
055         *
056         * @param theResource The resource to encode. Must not be null.
057         * @return A string representation of the encoding
058         * @throws DataFormatException If any invalid elements within the contents to be encoded prevent successful encoding.
059         */
060        String encodeResourceToString(IBaseResource theResource) throws DataFormatException;
061
062        /**
063         * Encodes a resource using the parser's given encoding format.
064         *
065         * @param theResource The resource to encode. Must not be null.
066         * @param theWriter   The writer to write to.
067         * @throws DataFormatException If any invalid elements within the contents to be encoded prevent successful encoding.
068         */
069        void encodeResourceToWriter(IBaseResource theResource, Writer theWriter) throws IOException, DataFormatException;
070
071        /**
072         * Encodes any FHIR element to a string.
073         * If a {@link IBaseResource resource object} is passed in, the resource will be encoded using standard FHIR
074         * encoding rules. If a {@link org.hl7.fhir.instance.model.api.IPrimitiveType primitive datatype} is passed in,
075         * the string value of the primitive type is encoded. Any extensions on the primitive type are not encoded.
076         * If any other object is passed in, a fragment is encoded. The format of the fragment depends on the encoding:
077         * <ul>
078         *    <li><b>JSON</b>: The fragment is output as a simple JSON object, exactly as it would appear within an encoded resource.</li>
079         *    <li><b>XML</b>: The fragment is output as an XML element as it would appear within an encoded resource, however it is wrapped in an element called <code>&lt;element&gt;</code> in order to avoid producing a document with multiple root tags.</li>
080         *    <li><b>RDF/Turtle</b>: This mode is not supported and will throw an {@link ca.uhn.fhir.rest.server.exceptions.InternalErrorException}</li>
081         * </ul>
082         *
083         * @since 6.8.0
084         */
085        String encodeToString(IBase theElement) throws DataFormatException;
086
087        /**
088         * Encodes any FHIR element to a writer.
089         * If a {@link IBaseResource resource object} is passed in, the resource will be encoded using standard FHIR
090         * encoding rules. If a {@link org.hl7.fhir.instance.model.api.IPrimitiveType primitive datatype} is passed in,
091         * the string value of the primitive type is encoded. Any extensions on the primitive type are not encoded.
092         * If any other object is passed in, a fragment is encoded. The format of the fragment depends on the encoding:
093         * <ul>
094         *    <li><b>JSON</b>: The fragment is output as a simple JSON object, exactly as it would appear within an encoded resource.</li>
095         *    <li><b>XML</b>: The fragment is output as an XML element as it would appear within an encoded resource, however it is wrapped in an element called <code>&lt;element&gt;</code> in order to avoid producing a document with multiple root tags.</li>
096         *    <li><b>RDF/Turtle</b>: This mode is not supported and will throw an {@link ca.uhn.fhir.rest.server.exceptions.InternalErrorException}</li>
097         * </ul>
098         *
099         * @since 6.8.0
100         */
101        void encodeToWriter(IBase theElement, Writer theWriter) throws DataFormatException, IOException;
102
103        /**
104         * If not set to null (as is the default) this ID will be used as the ID in any
105         * resources encoded by this parser
106         */
107        IIdType getEncodeForceResourceId();
108
109        /**
110         * When encoding, force this resource ID to be encoded as the resource ID
111         */
112        @SuppressWarnings("UnusedReturnValue")
113        IParser setEncodeForceResourceId(IIdType theForceResourceId);
114
115        /**
116         * Which encoding does this parser instance produce?
117         */
118        EncodingEnum getEncoding();
119
120        /**
121         * Gets the preferred types, as set using {@link #setPreferTypes(List)}
122         *
123         * @return Returns the preferred types, or <code>null</code>
124         * @see #setPreferTypes(List)
125         */
126        List<Class<? extends IBaseResource>> getPreferTypes();
127
128        /**
129         * If set, when parsing resources the parser will try to use the given types when possible, in
130         * the order that they are provided (from highest to lowest priority). For example, if a custom
131         * type which declares to implement the Patient resource is passed in here, and the
132         * parser is parsing a Bundle containing a Patient resource, the parser will use the given
133         * custom type.
134         * <p>
135         * This feature is related to, but not the same as the
136         * {@link FhirContext#setDefaultTypeForProfile(String, Class)} feature.
137         * <code>setDefaultTypeForProfile</code> is used to specify a type to be used
138         * when a resource explicitly declares support for a given profile. This
139         * feature specifies a type to be used irrespective of the profile declaration
140         * in the metadata statement.
141         * </p>
142         *
143         * @param thePreferTypes The preferred types, or <code>null</code>
144         */
145        void setPreferTypes(List<Class<? extends IBaseResource>> thePreferTypes);
146
147        /**
148         * Returns true if resource IDs should be omitted
149         *
150         * @see #setOmitResourceId(boolean)
151         * @since 1.1
152         */
153        boolean isOmitResourceId();
154
155        /**
156         * If set to <code>true</code> (default is <code>false</code>) the ID of any resources being encoded will not be
157         * included in the output. Note that this does not apply to contained resources, only to root resources. In other
158         * words, if this is set to <code>true</code>, contained resources will still have local IDs but the outer/containing
159         * ID will not have an ID.
160         * <p>
161         * If the resource being encoded is a Bundle or Parameters resource, this setting only applies to the
162         * outer resource being encoded, not any resources contained within.
163         * </p>
164         *
165         * @param theOmitResourceId Should resource IDs be omitted
166         * @return Returns a reference to <code>this</code> parser so that method calls can be chained together
167         * @since 1.1
168         */
169        IParser setOmitResourceId(boolean theOmitResourceId);
170
171        /**
172         * If set to <code>true<code> (which is the default), resource references containing a version
173         * will have the version removed when the resource is encoded. This is generally good behaviour because
174         * in most situations, references from one resource to another should be to the resource by ID, not
175         * by ID and version. In some cases though, it may be desirable to preserve the version in resource
176         * links. In that case, this value should be set to <code>false</code>.
177         *
178         * @return Returns the parser instance's configuration setting for stripping versions from resource references when
179         * encoding. This method will return <code>null</code> if no value is set, in which case
180         * the value from the {@link ParserOptions} will be used (default is <code>true</code>)
181         * @see ParserOptions
182         */
183        Boolean getStripVersionsFromReferences();
184
185        /**
186         * If set to <code>true<code> (which is the default), resource references containing a version
187         * will have the version removed when the resource is encoded. This is generally good behaviour because
188         * in most situations, references from one resource to another should be to the resource by ID, not
189         * by ID and version. In some cases though, it may be desirable to preserve the version in resource
190         * links. In that case, this value should be set to <code>false</code>.
191         * <p>
192         * This method provides the ability to globally disable reference encoding. If finer-grained
193         * control is needed, use {@link #setDontStripVersionsFromReferencesAtPaths(String...)}
194         * </p>
195         *
196         * @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}
197         * @return Returns a reference to <code>this</code> parser so that method calls can be chained together
198         * @see #setDontStripVersionsFromReferencesAtPaths(String...)
199         * @see ParserOptions
200         */
201        IParser setStripVersionsFromReferences(Boolean theStripVersionsFromReferences);
202
203        /**
204         * Is the parser in "summary mode"? See {@link #setSummaryMode(boolean)} for information
205         *
206         * @see #setSummaryMode(boolean) for information
207         */
208        boolean isSummaryMode();
209
210        /**
211         * If set to <code>true</code> (default is <code>false</code>) only elements marked by the FHIR specification as
212         * being "summary elements" will be included.
213         * <p>
214         * It is possible to modify the default summary mode element inclusions
215         * for this parser instance by invoking {@link #setEncodeElements(Set)}
216         * or {@link #setDontEncodeElements(Collection)}. It is also possible to
217         * modify the default summary mode element inclusions for all parsers
218         * generated for a given {@link FhirContext} by accessing
219         * {@link FhirContext#getParserOptions()} followed by
220         * {@link ParserOptions#setEncodeElementsForSummaryMode(Collection)} and/or
221         * {@link ParserOptions#setDontEncodeElementsForSummaryMode(Collection)}.
222         * </p>
223         * <p>
224         * For compatibility reasons with other frameworks, when encoding a
225         * <code>CapabilityStatement</code> resource in summary mode, extensions
226         * are always encoded, even though the FHIR Specification does not consider
227         * them to be summary elements.
228         * </p>
229         *
230         * @return Returns a reference to <code>this</code> parser so that method calls can be chained together
231         */
232        IParser setSummaryMode(boolean theSummaryMode);
233
234        /**
235         * Parses a resource
236         *
237         * @param theResourceType The resource type to use. This can be used to explicitly specify a class which extends a built-in type
238         *                        (e.g. a custom type extending the default Patient class)
239         * @param theReader       The reader to parse input from. Note that the Reader will not be closed by the parser upon completion.
240         * @return A parsed resource
241         * @throws DataFormatException If the resource can not be parsed because the data is not recognized or invalid for any reason
242         */
243        <T extends IBaseResource> T parseResource(Class<T> theResourceType, Reader theReader) throws DataFormatException;
244
245        /**
246         * Parses a resource
247         *
248         * @param theResourceType The resource type to use. This can be used to explicitly specify a class which extends a built-in type
249         *                        (e.g. a custom type extending the default Patient class)
250         * @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.
251         * @return A parsed resource
252         * @throws DataFormatException If the resource can not be parsed because the data is not recognized or invalid for any reason
253         */
254        <T extends IBaseResource> T parseResource(Class<T> theResourceType, InputStream theInputStream)
255                        throws DataFormatException;
256
257        /**
258         * Parses a resource
259         *
260         * @param theResourceType The resource type to use. This can be used to explicitly specify a class which extends a built-in type
261         *                        (e.g. a custom type extending the default Patient class)
262         * @param theString       The string to parse
263         * @return A parsed resource
264         * @throws DataFormatException If the resource can not be parsed because the data is not recognized or invalid for any reason
265         */
266        <T extends IBaseResource> T parseResource(Class<T> theResourceType, String theString) throws DataFormatException;
267
268        /**
269         * Parses a resource
270         *
271         * @param theReader The reader to parse input from. Note that the Reader will not be closed by the parser upon completion.
272         * @return A parsed resource. Note that the returned object will be an instance of {@link IResource} or
273         * {@link IAnyResource} depending on the specific FhirContext which created this parser.
274         * @throws DataFormatException If the resource can not be parsed because the data is not recognized or invalid for any reason
275         */
276        IBaseResource parseResource(Reader theReader) throws ConfigurationException, DataFormatException;
277
278        /**
279         * Parses a resource
280         *
281         * @param theInputStream The InputStream to parse input from (charset is assumed to be UTF-8).
282         *                       Note that the stream will not be closed by the parser upon completion.
283         * @return A parsed resource. Note that the returned object will be an instance of {@link IResource} or
284         * {@link IAnyResource} depending on the specific FhirContext which created this parser.
285         * @throws DataFormatException If the resource can not be parsed because the data is not recognized or invalid for any reason
286         */
287        IBaseResource parseResource(InputStream theInputStream) throws ConfigurationException, DataFormatException;
288
289        /**
290         * Parses a resource
291         *
292         * @param theMessageString The string to parse
293         * @return A parsed resource. Note that the returned object will be an instance of {@link IResource} or
294         * {@link IAnyResource} depending on the specific FhirContext which created this parser.
295         * @throws DataFormatException If the resource can not be parsed because the data is not recognized or invalid for any reason
296         */
297        IBaseResource parseResource(String theMessageString) throws ConfigurationException, DataFormatException;
298
299        /**
300         * If provided, specifies the elements which should NOT be encoded. Valid values for this
301         * field would include:
302         * <ul>
303         * <li><b>Patient</b> - Don't encode patient and all its children</li>
304         * <li><b>Patient.name</b> - Don't encode the patient's name</li>
305         * <li><b>Patient.name.family</b> - Don't encode the patient's family name</li>
306         * <li><b>*.text</b> - Don't encode the text element on any resource (only the very first position may contain a
307         * wildcard)</li>
308         * </ul>
309         * <p>
310         * Note: If {@link #setSummaryMode(boolean)} is set to <code>true</code>, then any
311         * elements specified using this method will be excluded even if they are
312         * summary elements.
313         * </p>
314         * <p>
315         * DSTU2 note: Note that values including meta, such as <code>Patient.meta</code>
316         * will work for DSTU2 parsers, but values with sub-elements on meta such
317         * as <code>Patient.meta.lastUpdated</code> will only work in
318         * DSTU3+ mode.
319         * </p>
320         *
321         * @param theDontEncodeElements The elements to not encode, or <code>null</code>
322         * @see #setEncodeElements(Set)
323         * @see ParserOptions#setDontEncodeElementsForSummaryMode(Collection)
324         */
325        IParser setDontEncodeElements(@Nullable Collection<String> theDontEncodeElements);
326
327        /**
328         * If provided, specifies the elements which should NOT be encoded. Valid values for this
329         * field would include:
330         * <ul>
331         * <li><b>Patient</b> - Don't encode patient and all its children</li>
332         * <li><b>Patient.name</b> - Don't encode the patient's name</li>
333         * <li><b>Patient.name.family</b> - Don't encode the patient's family name</li>
334         * <li><b>*.text</b> - Don't encode the text element on any resource (only the very first position may contain a
335         * wildcard)</li>
336         * </ul>
337         * <p>
338         * DSTU2 note: Note that values including meta, such as <code>Patient.meta</code>
339         * will work for DSTU2 parsers, but values with sub-elements on meta such
340         * as <code>Patient.meta.lastUpdated</code> will only work in
341         * DSTU3+ mode.
342         * </p>
343         *
344         * @param theDontEncodeElements The elements to not encode. Can be an empty list, but must not be <code>null</code>.
345         * @see #setDontEncodeElements(Collection)
346         * @see ParserOptions#setDontEncodeElementsForSummaryMode(Collection)
347         * @since 7.4.0
348         */
349        default IParser setDontEncodeElements(@Nonnull String... theDontEncodeElements) {
350                return setDontEncodeElements(CollectionUtil.newSet(theDontEncodeElements));
351        }
352
353        /**
354         * If provided, specifies the elements which should be encoded, to the exclusion of all others. Valid values for this
355         * field would include:
356         * <ul>
357         * <li><b>Patient</b> - Encode patient and all its children</li>
358         * <li><b>Patient.name</b> - Encode only the patient's name</li>
359         * <li><b>Patient.name.family</b> - Encode only the patient's family name</li>
360         * <li><b>*.text</b> - Encode the text element on any resource (only the very first position may contain a
361         * wildcard)</li>
362         * <li><b>*.(mandatory)</b> - This is a special case which causes any mandatory fields (min > 0) to be encoded</li>
363         * </ul>
364         * <p>
365         * Note: If {@link #setSummaryMode(boolean)} is set to <code>true</code>, then any
366         * elements specified using this method will be included even if they are not
367         * summary elements.
368         * </p>
369         *
370         * @param theEncodeElements The elements to encode, or <code>null</code>
371         * @see #setDontEncodeElements(Collection)
372         * @see #setEncodeElements(String...)
373         * @see ParserOptions#setEncodeElementsForSummaryMode(Collection)
374         */
375        IParser setEncodeElements(@Nullable Set<String> theEncodeElements);
376
377        /**
378         * If provided, specifies the elements which should be encoded, to the exclusion of all others. Valid values for this
379         * field would include:
380         * <ul>
381         * <li><b>Patient</b> - Encode patient and all its children</li>
382         * <li><b>Patient.name</b> - Encode only the patient's name</li>
383         * <li><b>Patient.name.family</b> - Encode only the patient's family name</li>
384         * <li><b>*.text</b> - Encode the text element on any resource (only the very first position may contain a
385         * wildcard)</li>
386         * <li><b>*.(mandatory)</b> - This is a special case which causes any mandatory fields (min > 0) to be encoded</li>
387         * </ul>
388         * <p>
389         * Note: If {@link #setSummaryMode(boolean)} is set to <code>true</code>, then any
390         * elements specified using this method will be included even if they are not
391         * summary elements.
392         * </p>
393         *
394         * @param theEncodeElements The elements to encode. Can be an empty list, but must not be <code>null</code>.
395         * @since 7.4.0
396         * @see #setEncodeElements(Set)
397         * @see ParserOptions#setEncodeElementsForSummaryMode(String...)
398         */
399        default IParser setEncodeElements(@Nonnull String... theEncodeElements) {
400                return setEncodeElements(CollectionUtil.newSet(theEncodeElements));
401        }
402
403        /**
404         * If set to <code>true</code> (default is false), the values supplied
405         * to {@link #setEncodeElements(Set)} will not be applied to the root
406         * resource (typically a Bundle), but will be applied to any sub-resources
407         * contained within it (i.e. search result resources in that bundle)
408         */
409        boolean isEncodeElementsAppliesToChildResourcesOnly();
410
411        /**
412         * If set to <code>true</code> (default is false), the values supplied
413         * to {@link #setEncodeElements(Set)} will not be applied to the root
414         * resource (typically a Bundle), but will be applied to any sub-resources
415         * contained within it (i.e. search result resources in that bundle)
416         */
417        void setEncodeElementsAppliesToChildResourcesOnly(boolean theEncodeElementsAppliesToChildResourcesOnly);
418
419        /**
420         * Registers an error handler which will be invoked when any parse errors are found
421         *
422         * @param theErrorHandler The error handler to set. Must not be null.
423         */
424        IParser setParserErrorHandler(IParserErrorHandler theErrorHandler);
425
426        /**
427         * Sets the "pretty print" flag, meaning that the parser will encode resources with human-readable spacing and
428         * newlines between elements instead of condensing output as much as possible.
429         *
430         * @param thePrettyPrint The flag
431         * @return Returns an instance of <code>this</code> parser so that method calls can be chained together
432         */
433        IParser setPrettyPrint(boolean thePrettyPrint);
434
435        /**
436         * Sets the server's base URL used by this parser. If a value is set, resource references will be turned into
437         * relative references if they are provided as absolute URLs but have a base matching the given base.
438         *
439         * @param theUrl The base URL, e.g. "<a href="http://example.com/base">http://example.com/base</a>"
440         * @return Returns an instance of <code>this</code> parser so that method calls can be chained together
441         */
442        IParser setServerBaseUrl(String theUrl);
443
444        /**
445         * If set to <code>true</code> (which is the default), the Bundle.entry.fullUrl will override the Bundle.entry.resource's
446         * resource id if the fullUrl is defined. This behavior happens when parsing the source data into a Bundle object. Set this
447         * to <code>false</code> if this is not the desired behavior (e.g. the client code wishes to perform additional
448         * validation checks between the fullUrl and the resource id).
449         *
450         * @param theOverrideResourceIdWithBundleEntryFullUrl Set this to <code>false</code> to prevent the parser from overriding resource ids with the
451         *                                                    Bundle.entry.fullUrl (or <code>null</code> to apply the default setting from the {@link ParserOptions})
452         * @return Returns a reference to <code>this</code> parser so that method calls can be chained together
453         * @see ParserOptions
454         */
455        IParser setOverrideResourceIdWithBundleEntryFullUrl(Boolean theOverrideResourceIdWithBundleEntryFullUrl);
456
457        /**
458         * If set to <code>true</code> (default is <code>false</code>), narratives will not be included in the encoded
459         * values.
460         */
461        IParser setSuppressNarratives(boolean theSuppressNarratives);
462
463        /**
464         * Returns the value supplied to {@link IParser#setDontStripVersionsFromReferencesAtPaths(String...)}
465         * or <code>null</code> if no value has been set for this parser (in which case the default from
466         * the {@link ParserOptions} will be used).
467         *
468         * @see #setDontStripVersionsFromReferencesAtPaths(String...)
469         * @see #setStripVersionsFromReferences(Boolean)
470         * @see ParserOptions
471         */
472        Set<String> getDontStripVersionsFromReferencesAtPaths();
473
474        /**
475         * If supplied value(s), any resource references at the specified paths will have their
476         * resource versions encoded instead of being automatically stripped during the encoding
477         * process. This setting has no effect on the parsing process.
478         * <p>
479         * This method provides a finer-grained level of control than {@link #setStripVersionsFromReferences(Boolean)}
480         * and any paths specified by this method will be encoded even if {@link #setStripVersionsFromReferences(Boolean)}
481         * has been set to <code>true</code> (which is the default)
482         * </p>
483         *
484         * @param thePaths A collection of paths for which the resource versions will not be removed automatically
485         *                 when serializing, e.g. "Patient.managingOrganization" or "AuditEvent.object.reference". Note that
486         *                 only resource name and field names with dots separating is allowed here (no repetition
487         *                 indicators, FluentPath expressions, etc.). Set to <code>null</code> to use the value
488         *                 set in the {@link ParserOptions}
489         * @return Returns a reference to <code>this</code> parser so that method calls can be chained together
490         * @see #setStripVersionsFromReferences(Boolean)
491         * @see ParserOptions
492         */
493        IParser setDontStripVersionsFromReferencesAtPaths(String... thePaths);
494
495        /**
496         * If supplied value(s), any resource references at the specified paths will have their
497         * resource versions encoded instead of being automatically stripped during the encoding
498         * process. This setting has no effect on the parsing process.
499         * <p>
500         * This method provides a finer-grained level of control than {@link #setStripVersionsFromReferences(Boolean)}
501         * and any paths specified by this method will be encoded even if {@link #setStripVersionsFromReferences(Boolean)}
502         * has been set to <code>true</code> (which is the default)
503         * </p>
504         *
505         * @param thePaths A collection of paths for which the resource versions will not be removed automatically
506         *                 when serializing, e.g. "Patient.managingOrganization" or "AuditEvent.object.reference". Note that
507         *                 only resource name and field names with dots separating is allowed here (no repetition
508         *                 indicators, FluentPath expressions, etc.). Set to <code>null</code> to use the value
509         *                 set in the {@link ParserOptions}
510         * @return Returns a reference to <code>this</code> parser so that method calls can be chained together
511         * @see #setStripVersionsFromReferences(Boolean)
512         * @see ParserOptions
513         */
514        IParser setDontStripVersionsFromReferencesAtPaths(Collection<String> thePaths);
515}