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