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