ca.uhn.fhir.repository.Repository Maven / Gradle / Ivy
/*-
* #%L
* HAPI FHIR - Core Library
* %%
* Copyright (C) 2014 - 2024 Smile CDR, Inc.
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
package ca.uhn.fhir.repository;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.i18n.Msg;
import ca.uhn.fhir.model.api.IQueryParameterType;
import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
import ca.uhn.fhir.rest.server.exceptions.ForbiddenOperationException;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.NotImplementedOperationException;
import com.google.common.annotations.Beta;
import org.hl7.fhir.instance.model.api.IBaseBundle;
import org.hl7.fhir.instance.model.api.IBaseConformance;
import org.hl7.fhir.instance.model.api.IBaseParameters;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
*
* This API is under-going active development, so it should be considered beta-level.
*
*
*
* This interface is a Java rendition of the FHIR REST API. All FHIR operations are defined at the
* HTTP level, which is convenient from the specification point-of-view since FHIR is built on top
* of web standards. This does mean that a few HTTP specific considerations, such as transmitting
* side-band information through the HTTP headers, bleeds into this API.
*
*
*
* One particularly odd case are FHIR Bundle links. The specification describes these as opaque to
* the end-user, so a given FHIR repository implementation must be able to resolve those directly.
* See {@link Repository#link(Class, String)}
*
*
*
* This interface also chooses to ignore return headers for most cases, preferring to return the
* Java objects directly. In cases where this is not possible, or the additional headers are crucial
* information, HAPI's {@link MethodOutcome} is used.
*
*
*
* Implementations of this interface should prefer to throw the exceptions derived from
* {@link ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException}
*
* All operations may throw {@link AuthenticationException}, {@link ForbiddenOperationException}, or
* {@link InternalErrorException} in addition to operation-specific exceptions.
*
*
*
* If a given operation is not supported, implementations should throw an
* {@link NotImplementedOperationException}. The capabilities operation, if supported, should return
* the set of supported interactions. If capabilities is not supported, the components in this
* repository will try to invoke operations with "sensible" defaults. For example, by using the
* standard FHIR search parameters. Discussion is on-going to determine what a "sensible" minimal
* level of support for interactions should be.
*
*
* @see FHIR REST API
*/
@Beta
public interface Repository {
// CRUD starts here
/**
* Reads a resource from the repository
*
* @see FHIR read
* @see FHIR vRead
*
* @param a Resource type
* @param an Id type
* @param resourceType the class of the Resource type to read
* @param id the id of the Resource to read
* @return the Resource
*/
default T read(Class resourceType, I id) {
return this.read(resourceType, id, Collections.emptyMap());
}
/**
* Reads a Resource from the repository
*
* @see FHIR read
* @see FHIR vRead
*
* @param a Resource type
* @param an Id type
* @param resourceType the class of the Resource type to read
* @param id the id of the Resource to read
* @param headers headers for this request, typically key-value pairs of HTTP headers
* @return the Resource
*/
T read(Class resourceType, I id, Map headers);
/**
* Creates a Resource in the repository
*
* @see FHIR create
*
* @param a Resource type
* @param resource the Resource to create
* @return a MethodOutcome with the id of the created Resource
*/
default MethodOutcome create(T resource) {
return this.create(resource, Collections.emptyMap());
}
/**
* Creates a Resource in the repository
*
* @see FHIR create
*
* @param a Resource type
* @param resource the Resource to create
* @param headers headers for this request, typically key-value pairs of HTTP headers
* @return a MethodOutcome with the id of the created Resource
*/
MethodOutcome create(T resource, Map 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);
}
}