001/*-
002 * #%L
003 * HAPI FHIR - Core Library
004 * %%
005 * Copyright (C) 2014 - 2025 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.repository;
021
022import ca.uhn.fhir.context.FhirContext;
023import ca.uhn.fhir.i18n.Msg;
024import ca.uhn.fhir.model.api.IQueryParameterType;
025import ca.uhn.fhir.rest.api.MethodOutcome;
026import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
027import ca.uhn.fhir.rest.server.exceptions.ForbiddenOperationException;
028import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
029import ca.uhn.fhir.rest.server.exceptions.NotImplementedOperationException;
030import com.google.common.annotations.Beta;
031import com.google.common.collect.Multimap;
032import com.google.common.collect.Multimaps;
033import jakarta.annotation.Nonnull;
034import org.hl7.fhir.instance.model.api.IBaseBundle;
035import org.hl7.fhir.instance.model.api.IBaseConformance;
036import org.hl7.fhir.instance.model.api.IBaseParameters;
037import org.hl7.fhir.instance.model.api.IBaseResource;
038import org.hl7.fhir.instance.model.api.IIdType;
039
040import java.util.Collections;
041import java.util.List;
042import java.util.Map;
043
044/**
045 * <p>
046 * This API is under-going active development, so it should be considered beta-level.
047 * </p>
048 *
049 * <p>
050 * This interface is a Java rendition of the FHIR REST API. All FHIR operations are defined at the
051 * HTTP level, which is convenient from the specification point-of-view since FHIR is built on top
052 * of web standards. This does mean that a few HTTP specific considerations, such as transmitting
053 * side-band information through the HTTP headers, bleeds into this API.
054 * </p>
055 *
056 * <p>
057 * One particularly odd case are FHIR Bundle links. The specification describes these as opaque to
058 * the end-user, so a given FHIR repository implementation must be able to resolve those directly.
059 * See {@link IRepository#link(Class, String)}
060 * </p>
061 *
062 * <p>
063 * This interface also chooses to ignore return headers for most cases, preferring to return the
064 * Java objects directly. In cases where this is not possible, or the additional headers are crucial
065 * information, HAPI's {@link MethodOutcome} is used.
066 * </p>
067 *
068 * <p>
069 * Implementations of this interface should prefer to throw the exceptions derived from
070 * {@link ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException}
071 *
072 * All operations may throw {@link AuthenticationException}, {@link ForbiddenOperationException}, or
073 * {@link InternalErrorException} in addition to operation-specific exceptions.
074 * </p>
075 *
076 * <p>
077 * If a given operation is not supported, implementations should throw an
078 * {@link NotImplementedOperationException}. The capabilities operation, if supported, should return
079 * the set of supported interactions. If capabilities is not supported, the components in this
080 * repository will try to invoke operations with "sensible" defaults. For example, by using the
081 * standard FHIR search parameters. Discussion is on-going to determine what a "sensible" minimal
082 * level of support for interactions should be.
083 * </p>
084 *
085 * @see <a href="https://www.hl7.org/fhir/http.html">FHIR REST API</a>
086 */
087@Beta
088public interface IRepository {
089
090        // CRUD starts here
091
092        /**
093         * Reads a resource from the repository
094         *
095         * @see <a href="https://www.hl7.org/fhir/http.html#read">FHIR read</a>
096         * @see <a href="https://www.hl7.org/fhir/http.html#vread">FHIR vRead</a>
097         *
098         * @param <T> a Resource type
099         * @param <I> an Id type
100         * @param resourceType the class of the Resource type to read
101         * @param id the id of the Resource to read
102         * @return the Resource
103         */
104        default <T extends IBaseResource, I extends IIdType> T read(Class<T> resourceType, I id) {
105                return this.read(resourceType, id, Collections.emptyMap());
106        }
107
108        /**
109         * Reads a Resource from the repository
110         *
111         * @see <a href="https://www.hl7.org/fhir/http.html#read">FHIR read</a>
112         * @see <a href="https://www.hl7.org/fhir/http.html#vread">FHIR vRead</a>
113         *
114         * @param <T> a Resource type
115         * @param <I> an Id type
116         * @param resourceType the class of the Resource type to read
117         * @param id the id of the Resource to read
118         * @param headers headers for this request, typically key-value pairs of HTTP headers
119         * @return the Resource
120         */
121        <T extends IBaseResource, I extends IIdType> T read(Class<T> resourceType, I id, Map<String, String> headers);
122
123        /**
124         * Creates a Resource in the repository
125         *
126         * @see <a href="https://www.hl7.org/fhir/http.html#create">FHIR create</a>
127         *
128         * @param <T> a Resource type
129         * @param resource the Resource to create
130         * @return a MethodOutcome with the id of the created Resource
131         */
132        default <T extends IBaseResource> MethodOutcome create(T resource) {
133                return this.create(resource, Collections.emptyMap());
134        }
135
136        /**
137         * Creates a Resource in the repository
138         *
139         * @see <a href="https://www.hl7.org/fhir/http.html#create">FHIR create</a>
140         *
141         * @param <T> a Resource type
142         * @param resource the Resource to create
143         * @param headers headers for this request, typically key-value pairs of HTTP headers
144         * @return a MethodOutcome with the id of the created Resource
145         */
146        <T extends IBaseResource> MethodOutcome create(T resource, Map<String, String> headers);
147
148        /**
149         * Patches a Resource in the repository
150         *
151         * @see <a href="https://www.hl7.org/fhir/http.html#patch">FHIR patch</a>
152         *
153         * @param <I> an Id type
154         * @param <P> a Parameters type
155         * @param id the id of the Resource to patch
156         * @param patchParameters parameters describing the patches to apply
157         * @return a MethodOutcome with the id of the patched resource
158         */
159        default <I extends IIdType, P extends IBaseParameters> MethodOutcome patch(I id, P patchParameters) {
160                return this.patch(id, patchParameters, Collections.emptyMap());
161        }
162
163        /**
164         * Patches a Resource in the repository
165         *
166         * @see <a href="https://www.hl7.org/fhir/http.html#patch">FHIR patch</a>
167         *
168         * @param <I> an Id type
169         * @param <P> a Parameters type
170         * @param id the id of the Resource to patch
171         * @param patchParameters parameters describing the patches to apply
172         * @param headers headers for this request, typically key-value pairs of HTTP headers
173         * @return a MethodOutcome with the id of the patched resource
174         */
175        default <I extends IIdType, P extends IBaseParameters> MethodOutcome patch(
176                        I id, P patchParameters, Map<String, String> headers) {
177                return throwNotImplementedOperationException("patch is not supported by this repository");
178        }
179
180        /**
181         * Updates a Resource in the repository
182         *
183         * @see <a href="https://www.hl7.org/fhir/http.html#update">FHIR update</a>
184         *
185         * @param <T> a Resource type
186         * @param resource the Resource to update
187         * @return a MethodOutcome with the id of the updated Resource
188         */
189        default <T extends IBaseResource> MethodOutcome update(T resource) {
190                return this.update(resource, Collections.emptyMap());
191        }
192
193        /**
194         * Updates a Resource in the repository
195         *
196         * @see <a href="https://www.hl7.org/fhir/http.html#update">FHIR update</a>
197         *
198         * @param <T> a Resource type
199         * @param resource the Resource to update
200         * @param headers headers for this request, typically key-value pairs of HTTP headers
201         * @return a MethodOutcome with the id of the updated Resource
202         */
203        <T extends IBaseResource> MethodOutcome update(T resource, Map<String, String> headers);
204
205        /**
206         * Deletes a Resource in the repository
207         *
208         * @see <a href="https://www.hl7.org/fhir/http.html#delete">FHIR delete</a>
209         *
210         * @param <T> a Resource type
211         * @param <I> an Id type
212         * @param resourceType the class of the Resource type to delete
213         * @param id the id of the Resource to delete
214         * @return a MethodOutcome with the id of the deleted resource
215         */
216        default <T extends IBaseResource, I extends IIdType> MethodOutcome delete(Class<T> resourceType, I id) {
217                return this.delete(resourceType, id, Collections.emptyMap());
218        }
219
220        /**
221         * Deletes a Resource in the repository
222         *
223         * @see <a href="https://www.hl7.org/fhir/http.html#delete">FHIR delete</a>
224         *
225         * @param <T> a Resource type
226         * @param <I> an Id type
227         * @param resourceType the class of the Resource type to delete
228         * @param id the id of the Resource to delete
229         * @param headers headers for this request, typically key-value pairs of HTTP headers
230         * @return a MethodOutcome with the id of the deleted resource
231         */
232        <T extends IBaseResource, I extends IIdType> MethodOutcome delete(
233                        Class<T> resourceType, I id, Map<String, String> headers);
234
235        // Querying starts here
236
237        /**
238         * Searches this repository
239         *
240         * @see <a href="https://www.hl7.org/fhir/http.html#search">FHIR search</a>
241         *
242         * @param <B> a Bundle type
243         * @param <T> a Resource type
244         * @param bundleType the class of the Bundle type to return
245         * @param resourceType the class of the Resource type to search
246         * @param searchParameters the searchParameters for this search
247         * @return a Bundle with the results of the search
248         */
249        default <B extends IBaseBundle, T extends IBaseResource> B search(
250                        Class<B> bundleType, Class<T> resourceType, Multimap<String, List<IQueryParameterType>> searchParameters) {
251                return this.search(bundleType, resourceType, searchParameters, Collections.emptyMap());
252        }
253
254        /**
255         * Searches this repository
256         *
257         * @see <a href="https://www.hl7.org/fhir/http.html#search">FHIR search</a>
258         *
259         * @param <B> a Bundle type
260         * @param <T> a Resource type
261         * @param bundleType the class of the Bundle type to return
262         * @param resourceType the class of the Resource type to search
263         * @param searchParameters the searchParameters for this search
264         * @return a Bundle with the results of the search
265         */
266        default <B extends IBaseBundle, T extends IBaseResource> B search(
267                        Class<B> bundleType, Class<T> resourceType, Map<String, List<IQueryParameterType>> searchParameters) {
268                return this.search(bundleType, resourceType, searchParameters, Collections.emptyMap());
269        }
270
271        /**
272         * Searches this repository
273         *
274         * @see <a href="https://www.hl7.org/fhir/http.html#search">FHIR search</a>
275         *
276         * @param <B> a Bundle type
277         * @param <T> a Resource type
278         * @param bundleType the class of the Bundle type to return
279         * @param resourceType the class of the Resource type to search
280         * @param searchParameters the searchParameters for this search
281         * @param headers headers for this request, typically key-value pairs of HTTP headers
282         * @return a Bundle with the results of the search
283         */
284        <B extends IBaseBundle, T extends IBaseResource> B search(
285                        Class<B> bundleType,
286                        Class<T> resourceType,
287                        Multimap<String, List<IQueryParameterType>> searchParameters,
288                        Map<String, String> headers);
289
290        /**
291         * Searches this repository
292         *
293         * @see <a href="https://www.hl7.org/fhir/http.html#search">FHIR search</a>
294         *
295         * @param <B> a Bundle type
296         * @param <T> a Resource type
297         * @param bundleType the class of the Bundle type to return
298         * @param resourceType the class of the Resource type to search
299         * @param searchParameters the searchParameters for this search
300         * @param headers headers for this request, typically key-value pairs of HTTP headers
301         * @return a Bundle with the results of the search
302         */
303        default <B extends IBaseBundle, T extends IBaseResource> B search(
304                        Class<B> bundleType,
305                        Class<T> resourceType,
306                        Map<String, List<IQueryParameterType>> searchParameters,
307                        Map<String, String> headers) {
308                return this.search(bundleType, resourceType, Multimaps.forMap(searchParameters), headers);
309        }
310
311        // Paging starts here
312
313        /**
314         * Reads a Bundle from a link on this repository
315         * This is typically used for paging during searches
316         *
317         * @see <a href="https://www.hl7.org/fhir/bundle-definitions.html#Bundle.link">FHIR Bundle
318         *      link</a>
319         *
320         * @param <B> a Bundle type
321         * @param url the url of the Bundle to load
322         * @return a Bundle
323         */
324        default <B extends IBaseBundle> B link(Class<B> bundleType, String url) {
325                return this.link(bundleType, url, Collections.emptyMap());
326        }
327
328        /**
329         * Reads a Bundle from a link on this repository
330         * This is typically used for paging during searches
331         *
332         * @see <a href="https://www.hl7.org/fhir/bundle-definitions.html#Bundle.link">FHIR Bundle
333         *      link</a>
334         *
335         * @param <B> a Bundle type
336         * @param url the url of the Bundle to load
337         * @param headers headers for this request, typically key-value pairs of HTTP headers
338         * @return a Bundle
339         */
340        default <B extends IBaseBundle> B link(Class<B> bundleType, String url, Map<String, String> headers) {
341                return throwNotImplementedOperationException("link is not supported by this repository");
342        }
343
344        // Metadata starts here
345
346        /**
347         * Returns the CapabilityStatement/Conformance metadata for this repository
348         *
349         * @see <a href="https://www.hl7.org/fhir/http.html#capabilities">FHIR capabilities</a>
350         *
351         * @param <C> a CapabilityStatement/Conformance type
352         * @param resourceType the class of the CapabilityStatement/Conformance to return
353         * @return a CapabilityStatement/Conformance with the repository's metadata
354         */
355        default <C extends IBaseConformance> C capabilities(Class<C> resourceType) {
356                return this.capabilities(resourceType, Collections.emptyMap());
357        }
358
359        /**
360         * Returns the CapabilityStatement/Conformance metadata for this repository
361         *
362         * @see <a href="https://www.hl7.org/fhir/http.html#capabilities">FHIR capabilities</a>
363         *
364         * @param <C> a CapabilityStatement/Conformance type
365         * @param resourceType the class of the CapabilityStatement/Conformance to return
366         * @param headers headers for this request, typically key-value pairs of HTTP headers
367         * @return a CapabilityStatement/Conformance with the repository's metadata
368         */
369        default <C extends IBaseConformance> C capabilities(Class<C> resourceType, Map<String, String> headers) {
370                return throwNotImplementedOperationException("capabilities is not supported by this repository");
371        }
372
373        // Transactions starts here
374
375        /**
376         * Performs a transaction or batch on this repository
377         *
378         * @see <a href="https://www.hl7.org/fhir/http.html#transaction">FHIR transaction</a>
379         *
380         * @param <B> a Bundle type
381         * @param transaction a Bundle with the transaction/batch
382         * @return a Bundle with the results of the transaction/batch
383         */
384        default <B extends IBaseBundle> B transaction(B transaction) {
385                return this.transaction(transaction, Collections.emptyMap());
386        }
387
388        /**
389         * Performs a transaction or batch on this repository
390         *
391         * @see <a href="https://www.hl7.org/fhir/http.html#transaction">FHIR transaction</a>
392         *
393         * @param <B> a Bundle type
394         * @param transaction a Bundle with the transaction/batch
395         * @param headers headers for this request, typically key-value pairs of HTTP headers
396         * @return a Bundle with the results of the transaction/batch
397         */
398        default <B extends IBaseBundle> B transaction(B transaction, Map<String, String> headers) {
399                return throwNotImplementedOperationException("transaction is not supported by this repository");
400        }
401
402        // Operations starts here
403
404        /**
405         * Invokes a server-level operation on this repository that returns a Resource
406         *
407         * @see <a href="https://www.hl7.org/fhir/operations.html">FHIR operations</a>
408         *
409         * @param <R> a Resource type to return
410         * @param <P> a Parameters type for operation parameters
411         * @param name the name of the operation to invoke
412         * @param parameters the operation parameters
413         * @param returnType the class of the Resource the operation returns
414         * @return the results of the operation
415         */
416        default <R extends IBaseResource, P extends IBaseParameters> R invoke(
417                        String name, P parameters, Class<R> returnType) {
418                return this.invoke(name, parameters, returnType, Collections.emptyMap());
419        }
420
421        /**
422         * Invokes a server-level operation on this repository that returns a Resource
423         *
424         * @see <a href="https://www.hl7.org/fhir/operations.html">FHIR operations</a>
425         *
426         * @param <R> a Resource type to return
427         * @param <P> a Parameters type for operation parameters
428         * @param name the name of the operation to invoke
429         * @param parameters the operation parameters
430         * @param returnType the class of the Resource the operation returns
431         * @param headers headers for this request, typically key-value pairs of HTTP headers
432         * @return the results of the operation
433         */
434        default <R extends IBaseResource, P extends IBaseParameters> R invoke(
435                        String name, P parameters, Class<R> returnType, Map<String, String> headers) {
436                return throwNotImplementedOperationException("server-level invoke is not supported by this repository");
437        }
438
439        /**
440         * Invokes a server-level operation on this repository
441         *
442         * @see <a href="https://www.hl7.org/fhir/operations.html">FHIR operations</a>
443         *
444         * @param <P> a Parameters type for operation parameters
445         * @param name the name of the operation to invoke
446         * @param parameters the operation parameters
447         * @return a MethodOutcome with a status code
448         */
449        default <P extends IBaseParameters> MethodOutcome invoke(String name, P parameters) {
450                return this.invoke(name, parameters, Collections.emptyMap());
451        }
452
453        /**
454         * Invokes a server-level operation on this repository
455         *
456         * @see <a href="https://www.hl7.org/fhir/operations.html">FHIR operations</a>
457         *
458         * @param <P> a Parameters type for operation parameters
459         * @param name the name of the operation to invoke
460         * @param parameters the operation parameters
461         * @param headers headers for this request, typically key-value pairs of HTTP headers
462         * @return a MethodOutcome with a status code
463         */
464        default <P extends IBaseParameters> MethodOutcome invoke(String name, P parameters, Map<String, String> headers) {
465                return throwNotImplementedOperationException("server-level invoke is not supported by this repository");
466        }
467
468        /**
469         * Invokes a type-level operation on this repository that returns a Resource
470         *
471         * @see <a href="https://www.hl7.org/fhir/operations.html">FHIR operations</a>
472         *
473         * @param <R> a Resource type to return
474         * @param <P> a Parameters type for operation parameters
475         * @param <T> a Resource type to do the invocation for
476         * @param resourceType the class of the Resource to do the invocation for
477         * @param name the name of the operation to invoke
478         * @param parameters the operation parameters
479         * @param returnType the class of the Resource the operation returns
480         * @return the results of the operation
481         */
482        default <R extends IBaseResource, P extends IBaseParameters, T extends IBaseResource> R invoke(
483                        Class<T> resourceType, String name, P parameters, Class<R> returnType) {
484                return this.invoke(resourceType, name, parameters, returnType, Collections.emptyMap());
485        }
486
487        /**
488         * Invokes a type-level operation on this repository that returns a Resource
489         *
490         * @see <a href="https://www.hl7.org/fhir/operations.html">FHIR operations</a>
491         *
492         * @param <R> a Resource type to return
493         * @param <P> a Parameters type for operation parameters
494         * @param <T> a Resource type to do the invocation for
495         * @param resourceType the class of the Resource to do the invocation for
496         * @param name the name of the operation to invoke
497         * @param parameters the operation parameters
498         * @param headers headers for this request, typically key-value pairs of HTTP headers
499         * @param returnType the class of the Resource the operation returns
500         * @return the results of the operation
501         */
502        default <R extends IBaseResource, P extends IBaseParameters, T extends IBaseResource> R invoke(
503                        Class<T> resourceType, String name, P parameters, Class<R> returnType, Map<String, String> headers) {
504                return throwNotImplementedOperationException("type-level invoke is not supported by this repository");
505        }
506
507        /**
508         * Invokes a type-level operation on this repository
509         *
510         * @see <a href="https://www.hl7.org/fhir/operations.html">FHIR operations</a>
511         *
512         * @param <P> a Parameters type for operation parameters
513         * @param <T> a Resource type to do the invocation for
514         * @param resourceType the class of the Resource to do the invocation for
515         * @param name the name of the operation to invoke
516         * @param parameters the operation parameters
517         * @return a MethodOutcome with a status code
518         */
519        default <P extends IBaseParameters, T extends IBaseResource> MethodOutcome invoke(
520                        Class<T> resourceType, String name, P parameters) {
521                return this.invoke(resourceType, name, parameters, Collections.emptyMap());
522        }
523
524        /**
525         * Invokes a type-level operation on this repository
526         *
527         * @see <a href="https://www.hl7.org/fhir/operations.html">FHIR operations</a>
528         *
529         * @param <P> a Parameters type for operation parameters
530         * @param <T> a Resource type to do the invocation for
531         * @param resourceType the class of the Resource to do the invocation for
532         * @param name the name of the operation to invoke
533         * @param parameters the operation parameters
534         * @param headers headers for this request, typically key-value pairs of HTTP headers
535         * @return a MethodOutcome with a status code
536         */
537        default <P extends IBaseParameters, T extends IBaseResource> MethodOutcome invoke(
538                        Class<T> resourceType, String name, P parameters, Map<String, String> headers) {
539                return throwNotImplementedOperationException("type-level invoke is not supported by this repository");
540        }
541
542        /**
543         * Invokes an instance-level operation on this repository that returns a Resource
544         *
545         * @see <a href="https://www.hl7.org/fhir/operations.html">FHIR operations</a>
546         *
547         * @param <R> a Resource type to return
548         * @param <P> a Parameters type for operation parameters
549         * @param <I> an Id type
550         * @param id the id of the Resource to do the invocation on
551         * @param name the name of the operation to invoke
552         * @param parameters the operation parameters
553         * @param returnType the class of the Resource the operation returns
554         * @return the results of the operation
555         */
556        default <R extends IBaseResource, P extends IBaseParameters, I extends IIdType> R invoke(
557                        I id, String name, P parameters, Class<R> returnType) {
558                return this.invoke(id, name, parameters, returnType, Collections.emptyMap());
559        }
560
561        /**
562         * Invokes an instance-level operation on this repository that returns a Resource
563         *
564         * @see <a href="https://www.hl7.org/fhir/operations.html">FHIR operations</a>
565         *
566         * @param <R> a Resource type to return
567         * @param <P> a Parameters type for operation parameters
568         * @param <I> an Id type
569         * @param id the id of the Resource to do the invocation on
570         * @param name the name of the operation to invoke
571         * @param parameters the operation parameters
572         * @param returnType the class of the Resource the operation returns
573         * @param headers headers for this request, typically key-value pairs of HTTP headers
574         * @return the results of the operation
575         */
576        default <R extends IBaseResource, P extends IBaseParameters, I extends IIdType> R invoke(
577                        I id, String name, P parameters, Class<R> returnType, Map<String, String> headers) {
578                return throwNotImplementedOperationException("instance-level invoke is not supported by this repository");
579        }
580
581        /**
582         * Invokes an instance-level operation on this repository
583         *
584         * @see <a href="https://www.hl7.org/fhir/operations.html">FHIR operations</a>
585         *
586         * @param <P> a Parameters type for operation parameters
587         * @param <I> an Id type
588         * @param id the id of the Resource to do the invocation on
589         * @param name the name of the operation to invoke
590         * @param parameters the operation parameters
591         * @return a MethodOutcome with a status code
592         */
593        default <P extends IBaseParameters, I extends IIdType> MethodOutcome invoke(I id, String name, P parameters) {
594                return this.invoke(id, name, parameters, Collections.emptyMap());
595        }
596
597        /**
598         * Invokes an instance-level operation on this repository
599         *
600         * @see <a href="https://www.hl7.org/fhir/operations.html">FHIR operations</a>
601         *
602         * @param <P> a Parameters type for operation parameters
603         * @param <I> an Id type
604         * @param id the id of the Resource to do the invocation on
605         * @param name the name of the operation to invoke
606         * @param parameters the operation parameters
607         * @param headers headers for this request, typically key-value pairs of HTTP headers
608         * @return a MethodOutcome with a status code
609         */
610        default <P extends IBaseParameters, I extends IIdType> MethodOutcome invoke(
611                        I id, String name, P parameters, Map<String, String> headers) {
612                return throwNotImplementedOperationException("instance-level invoke is not supported by this repository");
613        }
614
615        // History starts here
616
617        /**
618         * Returns a Bundle with server-level history for this repository
619         *
620         * @see <a href="https://www.hl7.org/fhir/http.html#history">FHIR history</a>
621         *
622         * @param <B> a Bundle type to return
623         * @param <P> a Parameters type for input parameters
624         * @param parameters the parameters for this history interaction
625         * @param returnType the class of the Bundle type to return
626         * @return a Bundle with the server history
627         */
628        default <B extends IBaseBundle, P extends IBaseParameters> B history(P parameters, Class<B> returnType) {
629                return this.history(parameters, returnType, Collections.emptyMap());
630        }
631
632        /**
633         * Returns a Bundle with server-level history for this repository
634         *
635         * @see <a href="https://www.hl7.org/fhir/http.html#history">FHIR history</a>
636         *
637         * @param <B> a Bundle type to return
638         * @param <P> a Parameters type for input parameters
639         * @param parameters the parameters for this history interaction
640         * @param returnType the class of the Bundle type to return
641         * @param headers headers for this request, typically key-value pairs of HTTP headers
642         * @return a Bundle with the server history
643         */
644        default <B extends IBaseBundle, P extends IBaseParameters> B history(
645                        P parameters, Class<B> returnType, Map<String, String> headers) {
646                return throwNotImplementedOperationException("server-level history is not supported by this repository");
647        }
648
649        /**
650         * Returns a Bundle with type-level history for this repository
651         *
652         * @see <a href="https://www.hl7.org/fhir/http.html#history">FHIR history</a>
653         *
654         * @param <B> a Bundle type to return
655         * @param <P> a Parameters type for input parameters
656         * @param <T> a Resource type to produce history for
657         * @param resourceType the class of the Resource type to produce history for
658         * @param parameters the parameters for this history interaction
659         * @param returnType the class of the Bundle type to return
660         * @return a Bundle with the type history
661         */
662        default <B extends IBaseBundle, P extends IBaseParameters, T extends IBaseResource> B history(
663                        Class<T> resourceType, P parameters, Class<B> returnType) {
664                return this.history(resourceType, parameters, returnType, Collections.emptyMap());
665        }
666
667        /**
668         * Returns a Bundle with type-level history for this repository
669         *
670         * @see <a href="https://www.hl7.org/fhir/http.html#history">FHIR history</a>
671         *
672         * @param <B> a Bundle type to return
673         * @param <P> a Parameters type for input parameters
674         * @param <T> a Resource type to produce history for
675         * @param resourceType the class of the Resource type to produce history for
676         * @param parameters the parameters for this history interaction
677         * @param returnType the class of the Bundle type to return
678         * @param headers headers for this request, typically key-value pairs of HTTP headers
679         * @return a Bundle with the type history
680         */
681        default <B extends IBaseBundle, P extends IBaseParameters, T extends IBaseResource> B history(
682                        Class<T> resourceType, P parameters, Class<B> returnType, Map<String, String> headers) {
683                return throwNotImplementedOperationException("type-level history is not supported by this repository");
684        }
685
686        /**
687         * Returns a Bundle with instance-level history
688         *
689         * @see <a href="https://www.hl7.org/fhir/http.html#history">FHIR history</a>
690         *
691         * @param <B> a Bundle type to return
692         * @param <P> a Parameters type for input parameters
693         * @param <I> an Id type for the Resource to produce history for
694         * @param id the id of the Resource type to produce history for
695         * @param parameters the parameters for this history interaction
696         * @param returnType the class of the Bundle type to return
697         * @return a Bundle with the instance history
698         */
699        default <B extends IBaseBundle, P extends IBaseParameters, I extends IIdType> B history(
700                        I id, P parameters, Class<B> returnType) {
701                return this.history(id, parameters, returnType, Collections.emptyMap());
702        }
703
704        /**
705         * Returns a Bundle with instance-level history
706         *
707         * @see <a href="https://www.hl7.org/fhir/http.html#history">FHIR history</a>
708         *
709         * @param <B> a Bundle type to return
710         * @param <P> a Parameters type for input parameters
711         * @param <I> an Id type for the Resource to produce history for
712         * @param id the id of the Resource type to produce history for
713         * @param parameters the parameters for this history interaction
714         * @param returnType the class of the Bundle type to return
715         * @param headers headers for this request, typically key-value pairs of HTTP headers
716         * @return a Bundle with the instance history
717         */
718        default <B extends IBaseBundle, P extends IBaseParameters, I extends IIdType> B history(
719                        I id, P parameters, Class<B> returnType, Map<String, String> headers) {
720                return throwNotImplementedOperationException("instance-level history is not supported by this repository");
721        }
722
723        /**
724         * Returns the {@link FhirContext} used by the repository
725         * <p>
726         * Practically, implementing FHIR functionality with the HAPI toolset requires a FhirContext. In
727         * particular for things like version independent code. Ideally, a user could which FHIR version a
728         * repository was configured for using things like the CapabilityStatement. In practice, that's
729         * not widely implemented (yet) and it's expensive to create a new context with every call. We
730         * will probably revisit this in the future.
731         *
732         * @return a FhirContext
733         */
734        @Nonnull
735        FhirContext fhirContext();
736
737        private static <T> T throwNotImplementedOperationException(String theMessage) {
738                throw new NotImplementedOperationException(Msg.code(2542) + theMessage);
739        }
740}