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><element></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><element></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}