headers);
+
+ /**
+ * Patches a Resource in the repository
+ *
+ * @see FHIR patch
+ *
+ * @param an Id type
+ * @param a Parameters type
+ * @param id the id of the Resource to patch
+ * @param patchParameters parameters describing the patches to apply
+ * @return a MethodOutcome with the id of the patched resource
+ */
+ default MethodOutcome patch(I id, P patchParameters) {
+ return this.patch(id, patchParameters, Collections.emptyMap());
+ }
+
+ /**
+ * Patches a Resource in the repository
+ *
+ * @see FHIR patch
+ *
+ * @param an Id type
+ * @param
a Parameters type
+ * @param id the id of the Resource to patch
+ * @param patchParameters parameters describing the patches to apply
+ * @param headers headers for this request, typically key-value pairs of HTTP headers
+ * @return a MethodOutcome with the id of the patched resource
+ */
+ default MethodOutcome patch(
+ I id, P patchParameters, Map headers) {
+ return throwNotImplementedOperationException("patch is not supported by this repository");
+ }
+
+ /**
+ * Updates a Resource in the repository
+ *
+ * @see FHIR update
+ *
+ * @param a Resource type
+ * @param resource the Resource to update
+ * @return a MethodOutcome with the id of the updated Resource
+ */
+ default MethodOutcome update(T resource) {
+ return this.update(resource, Collections.emptyMap());
+ }
+
+ /**
+ * Updates a Resource in the repository
+ *
+ * @see FHIR update
+ *
+ * @param a Resource type
+ * @param resource the Resource to update
+ * @param headers headers for this request, typically key-value pairs of HTTP headers
+ * @return a MethodOutcome with the id of the updated Resource
+ */
+ MethodOutcome update(T resource, Map headers);
+
+ /**
+ * Deletes a Resource in the repository
+ *
+ * @see FHIR delete
+ *
+ * @param a Resource type
+ * @param an Id type
+ * @param resourceType the class of the Resource type to delete
+ * @param id the id of the Resource to delete
+ * @return a MethodOutcome with the id of the deleted resource
+ */
+ default MethodOutcome delete(Class resourceType, I id) {
+ return this.delete(resourceType, id, Collections.emptyMap());
+ }
+
+ /**
+ * Deletes a Resource in the repository
+ *
+ * @see FHIR delete
+ *
+ * @param a Resource type
+ * @param an Id type
+ * @param resourceType the class of the Resource type to delete
+ * @param id the id of the Resource to delete
+ * @param headers headers for this request, typically key-value pairs of HTTP headers
+ * @return a MethodOutcome with the id of the deleted resource
+ */
+ MethodOutcome delete(
+ Class resourceType, I id, Map headers);
+
+ // Querying starts here
+
+ /**
+ * Searches this repository
+ *
+ * @see FHIR search
+ *
+ * @param a Bundle type
+ * @param a Resource type
+ * @param bundleType the class of the Bundle type to return
+ * @param resourceType the class of the Resource type to search
+ * @param searchParameters the searchParameters for this search
+ * @return a Bundle with the results of the search
+ */
+ default B search(
+ Class bundleType, Class resourceType, Map> searchParameters) {
+ return this.search(bundleType, resourceType, searchParameters, Collections.emptyMap());
+ }
+
+ /**
+ * Searches this repository
+ *
+ * @see FHIR search
+ *
+ * @param a Bundle type
+ * @param a Resource type
+ * @param bundleType the class of the Bundle type to return
+ * @param resourceType the class of the Resource type to search
+ * @param searchParameters the searchParameters for this search
+ * @param headers headers for this request, typically key-value pairs of HTTP headers
+ * @return a Bundle with the results of the search
+ */
+ B search(
+ Class bundleType,
+ Class resourceType,
+ Map> searchParameters,
+ Map headers);
+
+ // Paging starts here
+
+ /**
+ * Reads a Bundle from a link on this repository
+ *
+ * This is typically used for paging during searches
+ *
+ * @see FHIR Bundle
+ * link
+ *
+ * @param a Bundle type
+ * @param url the url of the Bundle to load
+ * @return a Bundle
+ */
+ default B link(Class bundleType, String url) {
+ return this.link(bundleType, url, Collections.emptyMap());
+ }
+
+ /**
+ * Reads a Bundle from a link on this repository
+ *
+ * This is typically used for paging during searches
+ *
+ * @see FHIR Bundle
+ * link
+ *
+ * @param a Bundle type
+ * @param url the url of the Bundle to load
+ * @param headers headers for this request, typically key-value pairs of HTTP headers
+ * @return a Bundle
+ */
+ default B link(Class bundleType, String url, Map headers) {
+ return throwNotImplementedOperationException("link is not supported by this repository");
+ }
+
+ // Metadata starts here
+
+ /**
+ * Returns the CapabilityStatement/Conformance metadata for this repository
+ *
+ * @see FHIR capabilities
+ *
+ * @param a CapabilityStatement/Conformance type
+ * @param resourceType the class of the CapabilityStatement/Conformance to return
+ * @return a CapabilityStatement/Conformance with the repository's metadata
+ */
+ default C capabilities(Class resourceType) {
+ return this.capabilities(resourceType, Collections.emptyMap());
+ }
+
+ /**
+ * Returns the CapabilityStatement/Conformance metadata for this repository
+ *
+ * @see FHIR capabilities
+ *
+ * @param a CapabilityStatement/Conformance type
+ * @param resourceType the class of the CapabilityStatement/Conformance to return
+ * @param headers headers for this request, typically key-value pairs of HTTP headers
+ * @return a CapabilityStatement/Conformance with the repository's metadata
+ */
+ default C capabilities(Class resourceType, Map headers) {
+ return throwNotImplementedOperationException("capabilities is not supported by this repository");
+ }
+
+ // Transactions starts here
+
+ /**
+ * Performs a transaction or batch on this repository
+ *
+ * @see FHIR transaction
+ *
+ * @param a Bundle type
+ * @param transaction a Bundle with the transaction/batch
+ * @return a Bundle with the results of the transaction/batch
+ */
+ default B transaction(B transaction) {
+ return this.transaction(transaction, Collections.emptyMap());
+ }
+
+ /**
+ * Performs a transaction or batch on this repository
+ *
+ * @see FHIR transaction
+ *
+ * @param a Bundle type
+ * @param transaction a Bundle with the transaction/batch
+ * @param headers headers for this request, typically key-value pairs of HTTP headers
+ * @return a Bundle with the results of the transaction/batch
+ */
+ default B transaction(B transaction, Map headers) {
+ return throwNotImplementedOperationException("transaction is not supported by this repository");
+ }
+
+ // Operations starts here
+
+ /**
+ * Invokes a server-level operation on this repository that returns a Resource
+ *
+ * @see FHIR operations
+ *
+ * @param a Resource type to return
+ * @param a Parameters type for operation parameters
+ * @param name the name of the operation to invoke
+ * @param parameters the operation parameters
+ * @param returnType the class of the Resource the operation returns
+ * @return the results of the operation
+ */
+ default R invoke(
+ String name, P parameters, Class returnType) {
+ return this.invoke(name, parameters, returnType, Collections.emptyMap());
+ }
+
+ /**
+ * Invokes a server-level operation on this repository that returns a Resource
+ *
+ * @see FHIR operations
+ *
+ * @param a Resource type to return
+ * @param a Parameters type for operation parameters
+ * @param name the name of the operation to invoke
+ * @param parameters the operation parameters
+ * @param returnType the class of the Resource the operation returns
+ * @param headers headers for this request, typically key-value pairs of HTTP headers
+ * @return the results of the operation
+ */
+ default R invoke(
+ String name, P parameters, Class returnType, Map headers) {
+ return throwNotImplementedOperationException("server-level invoke is not supported by this repository");
+ }
+
+ /**
+ * Invokes a server-level operation on this repository
+ *
+ * @see FHIR operations
+ *
+ * @param a Parameters type for operation parameters
+ * @param name the name of the operation to invoke
+ * @param parameters the operation parameters
+ * @return a MethodOutcome with a status code
+ */
+ default
MethodOutcome invoke(String name, P parameters) {
+ return this.invoke(name, parameters, Collections.emptyMap());
+ }
+
+ /**
+ * Invokes a server-level operation on this repository
+ *
+ * @see FHIR operations
+ *
+ * @param
a Parameters type for operation parameters
+ * @param name the name of the operation to invoke
+ * @param parameters the operation parameters
+ * @param headers headers for this request, typically key-value pairs of HTTP headers
+ * @return a MethodOutcome with a status code
+ */
+ default
MethodOutcome invoke(String name, P parameters, Map headers) {
+ return throwNotImplementedOperationException("server-level invoke is not supported by this repository");
+ }
+
+ /**
+ * Invokes a type-level operation on this repository that returns a Resource
+ *
+ * @see FHIR operations
+ *
+ * @param a Resource type to return
+ * @param a Parameters type for operation parameters
+ * @param a Resource type to do the invocation for
+ * @param resourceType the class of the Resource to do the invocation for
+ * @param name the name of the operation to invoke
+ * @param parameters the operation parameters
+ * @param returnType the class of the Resource the operation returns
+ * @return the results of the operation
+ */
+ default R invoke(
+ Class resourceType, String name, P parameters, Class returnType) {
+ return this.invoke(resourceType, name, parameters, returnType, Collections.emptyMap());
+ }
+
+ /**
+ * Invokes a type-level operation on this repository that returns a Resource
+ *
+ * @see FHIR operations
+ *
+ * @param a Resource type to return
+ * @param a Parameters type for operation parameters
+ * @param a Resource type to do the invocation for
+ * @param resourceType the class of the Resource to do the invocation for
+ * @param name the name of the operation to invoke
+ * @param parameters the operation parameters
+ * @param headers headers for this request, typically key-value pairs of HTTP headers
+ * @param returnType the class of the Resource the operation returns
+ * @return the results of the operation
+ */
+ R invoke(
+ Class resourceType, String name, P parameters, Class returnType, Map headers);
+
+ /**
+ * Invokes a type-level operation on this repository
+ *
+ * @see FHIR operations
+ *
+ * @param a Parameters type for operation parameters
+ * @param a Resource type to do the invocation for
+ * @param resourceType the class of the Resource to do the invocation for
+ * @param name the name of the operation to invoke
+ * @param parameters the operation parameters
+ * @return a MethodOutcome with a status code
+ */
+ default MethodOutcome invoke(
+ Class resourceType, String name, P parameters) {
+ return this.invoke(resourceType, name, parameters, Collections.emptyMap());
+ }
+
+ /**
+ * Invokes a type-level operation on this repository
+ *
+ * @see FHIR operations
+ *
+ * @param a Parameters type for operation parameters
+ * @param a Resource type to do the invocation for
+ * @param resourceType the class of the Resource to do the invocation for
+ * @param name the name of the operation to invoke
+ * @param parameters the operation parameters
+ * @param headers headers for this request, typically key-value pairs of HTTP headers
+ * @return a MethodOutcome with a status code
+ */
+ default MethodOutcome invoke(
+ Class resourceType, String name, P parameters, Map headers) {
+ return throwNotImplementedOperationException("type-level invoke is not supported by this repository");
+ }
+
+ /**
+ * Invokes an instance-level operation on this repository that returns a Resource
+ *
+ * @see FHIR operations
+ *
+ * @param a Resource type to return
+ * @param a Parameters type for operation parameters
+ * @param an Id type
+ * @param id the id of the Resource to do the invocation on
+ * @param name the name of the operation to invoke
+ * @param parameters the operation parameters
+ * @param returnType the class of the Resource the operation returns
+ * @return the results of the operation
+ */
+ default R invoke(
+ I id, String name, P parameters, Class returnType) {
+ return this.invoke(id, name, parameters, returnType, Collections.emptyMap());
+ }
+
+ /**
+ * Invokes an instance-level operation on this repository that returns a Resource
+ *
+ * @see FHIR operations
+ *
+ * @param a Resource type to return
+ * @param a Parameters type for operation parameters
+ * @param an Id type
+ * @param id the id of the Resource to do the invocation on
+ * @param name the name of the operation to invoke
+ * @param parameters the operation parameters
+ * @param returnType the class of the Resource the operation returns
+ * @param headers headers for this request, typically key-value pairs of HTTP headers
+ * @return the results of the operation
+ */
+ R invoke(
+ I id, String name, P parameters, Class returnType, Map headers);
+
+ /**
+ * Invokes an instance-level operation on this repository
+ *
+ * @see FHIR operations
+ *
+ * @param a Parameters type for operation parameters
+ * @param an Id type
+ * @param id the id of the Resource to do the invocation on
+ * @param name the name of the operation to invoke
+ * @param parameters the operation parameters
+ * @return a MethodOutcome with a status code
+ */
+ default
MethodOutcome invoke(I id, String name, P parameters) {
+ return this.invoke(id, name, parameters, Collections.emptyMap());
+ }
+
+ /**
+ * Invokes an instance-level operation on this repository
+ *
+ * @see FHIR operations
+ *
+ * @param
a Parameters type for operation parameters
+ * @param an Id type
+ * @param id the id of the Resource to do the invocation on
+ * @param name the name of the operation to invoke
+ * @param parameters the operation parameters
+ * @param headers headers for this request, typically key-value pairs of HTTP headers
+ * @return a MethodOutcome with a status code
+ */
+ default
MethodOutcome invoke(
+ I id, String name, P parameters, Map headers) {
+ return throwNotImplementedOperationException("instance-level invoke is not supported by this repository");
+ }
+
+ // History starts here
+
+ /**
+ * Returns a Bundle with server-level history for this repository
+ *
+ * @see FHIR history
+ *
+ * @param a Bundle type to return
+ * @param a Parameters type for input parameters
+ * @param parameters the parameters for this history interaction
+ * @param returnType the class of the Bundle type to return
+ * @return a Bundle with the server history
+ */
+ default B history(P parameters, Class returnType) {
+ return this.history(parameters, returnType, Collections.emptyMap());
+ }
+
+ /**
+ * Returns a Bundle with server-level history for this repository
+ *
+ * @see FHIR history
+ *
+ * @param a Bundle type to return
+ * @param
a Parameters type for input parameters
+ * @param parameters the parameters for this history interaction
+ * @param returnType the class of the Bundle type to return
+ * @param headers headers for this request, typically key-value pairs of HTTP headers
+ * @return a Bundle with the server history
+ */
+ default B history(
+ P parameters, Class returnType, Map headers) {
+ return throwNotImplementedOperationException("server-level history is not supported by this repository");
+ }
+
+ /**
+ * Returns a Bundle with type-level history for this repository
+ *
+ * @see FHIR history
+ *
+ * @param a Bundle type to return
+ * @param a Parameters type for input parameters
+ * @param a Resource type to produce history for
+ * @param resourceType the class of the Resource type to produce history for
+ * @param parameters the parameters for this history interaction
+ * @param returnType the class of the Bundle type to return
+ * @return a Bundle with the type history
+ */
+ default B history(
+ Class resourceType, P parameters, Class returnType) {
+ return this.history(resourceType, parameters, returnType, Collections.emptyMap());
+ }
+
+ /**
+ * Returns a Bundle with type-level history for this repository
+ *
+ * @see FHIR history
+ *
+ * @param a Bundle type to return
+ * @param a Parameters type for input parameters
+ * @param a Resource type to produce history for
+ * @param resourceType the class of the Resource type to produce history for
+ * @param parameters the parameters for this history interaction
+ * @param returnType the class of the Bundle type to return
+ * @param headers headers for this request, typically key-value pairs of HTTP headers
+ * @return a Bundle with the type history
+ */
+ default B history(
+ Class resourceType, P parameters, Class returnType, Map headers) {
+ return throwNotImplementedOperationException("type-level history is not supported by this repository");
+ }
+
+ /**
+ * Returns a Bundle with instance-level history
+ *
+ * @see FHIR history
+ *
+ * @param a Bundle type to return
+ * @param a Parameters type for input parameters
+ * @param an Id type for the Resource to produce history for
+ * @param id the id of the Resource type to produce history for
+ * @param parameters the parameters for this history interaction
+ * @param returnType the class of the Bundle type to return
+ * @return a Bundle with the instance history
+ */
+ default B history(
+ I id, P parameters, Class returnType) {
+ return this.history(id, parameters, returnType, Collections.emptyMap());
+ }
+
+ /**
+ * Returns a Bundle with instance-level history
+ *
+ * @see FHIR history
+ *
+ * @param a Bundle type to return
+ * @param
a Parameters type for input parameters
+ * @param an Id type for the Resource to produce history for
+ * @param id the id of the Resource type to produce history for
+ * @param parameters the parameters for this history interaction
+ * @param returnType the class of the Bundle type to return
+ * @param headers headers for this request, typically key-value pairs of HTTP headers
+ * @return a Bundle with the instance history
+ */
+ default B history(
+ I id, P parameters, Class returnType, Map headers) {
+ return throwNotImplementedOperationException("instance-level history is not supported by this repository");
+ }
+
+ /**
+ * Returns the {@link FhirContext} used by the repository
+ *
+ * Practically, implementing FHIR functionality with the HAPI toolset requires a FhirContext. In
+ * particular for things like version independent code. Ideally, a user could which FHIR version a
+ * repository was configured for using things like the CapabilityStatement. In practice, that's
+ * not widely implemented (yet) and it's expensive to create a new context with every call. We
+ * will probably revisit this in the future.
+ *
+ * @return a FhirContext
+ */
+ FhirContext fhirContext();
+
+ private static T throwNotImplementedOperationException(String theMessage) {
+ throw new NotImplementedOperationException(Msg.code(2542) + theMessage);
+ }
+}
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/7_4_0/6140-common-data-access-api.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/7_4_0/6140-common-data-access-api.yaml
new file mode 100644
index 00000000000..bfca99df2f5
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/7_4_0/6140-common-data-access-api.yaml
@@ -0,0 +1,7 @@
+---
+type: change
+issue: 6140
+title: "An prototype interface to abstract data access across different types
+ of FHIR repositories (e.g. remote REST, local JPA) has been added to the `hapi-fhir-base` project.
+ Implementations of this interface will follow in future HAPI releases, and it will continue to evolve
+ as it's validated through implementation."