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