View raw Markdown
type: resourceresource: extension-operationdefinition-allowed-type

extension-operationdefinition-allowed-type

Introduction

Scope and Usage

The OperationDefinition resource provides a formal computable definition of an operation or a named query. The OperationDefinition serves two principal purposes:

See below for further information about these, and about how operations and named queries are executed.

Boundaries and Relationships

OperationDefinitions are published to define operations that servers can implement in a common fashion. The FHIR specification itself describes some (see below), and other organizations (including IHE, national programs, jurisdictions and vendors) are able to publish additional OperationDefinitions.

OperationDefinition resources are referred to from two different places:

OperationDefinitions can be used to define a custom query (kind = query, discussed below) which functions as a special kind of search. This is different to a SearchParameter because a custom query may define multiple parameters and can define of complex search behavior beyond what SearchParameter can specify. It also typically overrides the behavior of the query functionality, while search parameters can only act as additional filters.

Notes

Derived OperationDefinitions

OperationDefinitions can describe entirely new operations, but they can also describe a restricted implementation of an existing operation, e.g. when a server implements some but not all the features of an operation defined in another specification. These are called derived operation definitions.

An OperationDefinition does by declaring a base as shown in the example:

{ "resourceType" : "OperationDefinition", "id" : "example", "url" : "http://hl7.org/fhir/OperationDefinition/example", "name" : "PopulateQuestionnaire", // snip "code" : "populate", "base" : "http://hl7.org/fhir/OperationDefinition/Questionnaire-populate" // snip }

When constraining an existing operation like this, operation definitions can make optional parameters required or not used, introduce new parameters (required or optional), clarify documentation, and even change the code for the operation (see next section). The derived operation can't change the nature of the operation itself, nor can it change add types to parameters or prohibit mandatory parameters.

When deriving from another operation, the following rules SHOULD be followed. Note that these rules are asserted as SHOULD rather than SHALL only because they were introduced after the resource became normative. Systems that fail to follow these rules are likely to result in unsafe interoperability.

Request for ballot feedback: We would like the 'SHOULD' assertions above to become 'SHALL' assertions. We are invoking our usual implementer outreach process to find out whether anyone else objects, but please file tickets for any rules you do not believe can be enforced that way.

OperationDefinition Code

Operations are invoked by their code, not their name. The name is descriptive, for code generation, e.g. ValueSetExpansion, while the code is what is used in a URL e.g. http://example.org/fhir/ValueSet/$expand. When defining operations, for maximum compatibility, use only lowercase ASCII characters. See Naming Rules & Guidelines for the internal HL7 rules around codes, which are useful additional advice for all implementers.

It is possible for two different organizations to create different operation definitions with the same code or, perhaps more likely, to define equivalent operations that have the same code but incompatible approaches in their parameter lists. Note that HL7 will never define multiple operations with the same code.

It is also possible, though unlikely, that a server will be required to support both of these operations. If this is the case, the server is able to do this by giving one of them a new code and referring to it by definition in the capability statement. To illustrate this, assume that two different organizations, "orgA" and "orgB", both define an operation with a code dothis, and the definitions are incompatible. OrgA publishes its operation definition at http://orga.com/fhir/dothis.xml, and OrgB publishes its operation at http://fhir.orgb.com/meta/OperationDefinition/dothis. The server is able to implement both. Its capability statement will say:

<CapabilityStatement xmlns="http://hl7.org/fhir">

<rest>

&lt;operation&gt;
  &lt;name value="dothis"/&gt;
  &lt;definition&gt;
    &lt;reference value="http://orga.com/fhir/dothis.xml"/&gt;
  &lt;/definition&gt;
&lt;/operation&gt;
&lt;operation&gt;
  &lt;name value="dothis2"/&gt;
  &lt;definition&gt;
    &lt;reference value="http://fhir.orgb.com/meta/OperationDefinition/dothis"/&gt;
  &lt;/definition&gt;
&lt;/operation&gt;
<!-- snip -->

</rest>

</CapabilityStatement>

If a general purpose cross server client is looking for the implementation of the http://fhir.orgb.com/meta/OperationDefinition/dothis operation and wants to be robust against this name clash problem, instead of simply executing the $dothis operation, it can look at the server's CapabilityStatement for the underlying definition URI and then execute with the name given in the capability statement.

Note to implementers: it would be more consistent if CapabilityStatement.rest.operation.name was actually called "code", since it relates to OperationDefinition.code, but the confusion this can cause wasn't appreciated until the resource was normative.

Describing Operation Parameters

There are 2 ways to describe the input and output parameters for an operation:

The parameters is a simple list of possible parameters, along with cardinalities and types. The profiles allow a more complete set of validation rules to be provided, such as constraints, additional bindings etc., and to provide a richer set of documentation (examples, mappings, etc.). OperationDefinitions SHALL always define the parameters using OperationDefinition.parameter in the resource, and MAY also provide profiles for the parameters. If present, the profiles SHALL NOT disagree with the parameters defined for the operation.

As an example, consider an operation that defines 3 parameters, 2 in and 1 out:

In Parameters:
Name
a
An integer parameter

| | b | 0..1 | Patient | | |

A patient parameter

| | Out Parameters: | | Name | Cardinality | Type | Binding | Profile | Documentation | | c | 1..1 | decimal | | |

A result parameter

|

In addition to specifying the operation parameters directly, an operation definition can also provide a profile:

"inputProfile" : "http://example.org/StructureDefinition/op.x.in.profile"

This profile would describe a parameters resource with 2 parameters (using slicing), with the same details as the table above. The operation definition would still list the parameters directly to save applications consuming the definition (e.g. to produce an OpenAPI document) from parsing and interpreting the profile.

When profiles are used, they SHALL be profiles on the Parameter resource (even if the expectation is that parameters will often be sent as part of the URL). The elements must be aligned as follows:

Executing Operations

OperationDefinitions with kind = operation are executed as defined in the Operations Framework.

Executing Named Queries

Named queries (OperationDefinitions with kind = query) are executed by performing a search with the value of the search parameter "_query" set to the name provided in the definition. Named queries are a kind of search: both client and server must conform to all the requirements of search, including regarding the content of the result bundle. From a client's perspective, it's really just a kind of search, though it may have a completely separate processing pipeline. Named queries cannot be invoked using the $[operationname] mechanism.

If the named query is to be performed over the RESTful API, all the parameters must be simple search parameters, so that they can be represented directly in the URL without tricky encoding issues. Named queries always have a single output parameter named "result" of type Bundle.

The order of parameters doesn't matter; a _query parameter anywhere in the query means the entire query will be handled according to the named query OperationDefinition. Parameters may repeat if permitted by the OperationDefinition (or for unlisted common search parameters, as specified in this specification).

For named queries, all the standard search parameters are automatically in scope. Specifically, all common search parameters (e.g. _id, _text, _count, _sort, etc.) as well as search parameters that pertain to the resources returned by the operation (e.g. name for Patient or Organization) are allowed. "In scope" doesn't mean all servers will support them. If a server wishes to declare which search parameters it supports for a given named query, it must explicitly list these in its OperationDefinition (which might be a server-specific derived OperationDefinition).

Passing Resources to Operations

There are two ways to pass resources to an operation: directly or by reference. The definition of an operation distinguishes between these two, since they have very different behaviors and consequences.

As an example, take the ValueSet.$expand operation. This operation takes a ValueSet as a direct parameter. The type of the parameter is defined as 'ValueSet'. In a Parameters resource, it would be represented like this:

<parameter> <name value="valueset"/> <resource> <ValueSet>

  &lt;/ValueSet&gt;
&lt;/resource&gt;

</parameter>

or, in JSON:

"parameter": [ { "name": "valueset", "resource": { "resourceType": "ValueSet", // ValueSet contents } } ]

Other parameters are passed by reference. For example, the PlanDefinition.$apply operation takes more than one parameters of type Reference - subject, encounter and organization. The expectation is that the server performing the operation will resolve those references as part of the operation execution. In a parameters resource, the subject parameter would be represented like this:

<parameter> <name value="subject"/> <valueReference> <reference value="Patient/123"/> </valueReference> </parameter>

or, in JSON:

"parameter": [ { "name": "subject", "valueReference" : { "reference" : "Patient/123" } } ]

Some operations can take either form; in that case, two distinct parameters must be defined: one for a resource as a direct parameter, and one for a reference.

Determining System Compatibility

A client can determine the compatibility of the server by processing its capability statement and ensuring that the server implements the specific operation definitions and parameters required by the client. The client can then report a useful error to the user rather than allowing mystifying operational errors to occur.

However, there are fundamental limitations to this approach because there are many aspects of these operations that are not (or cannot be) defined in a formal fashion using OperationDefinition, for example, co-occurrence constraints among parameters.

In the same sense, a 3rd party tool can examine a server's CapabilityStatement and a client's definition of an acceptable server to determine whether those two system are interoperable or not.

Dynamically Generating Forms

Finally, it is possible to generate user interface forms automatically from the OperationDefinition. The documentation in the OperationDefinition.description and OperationDefinition.parameter.documentation should be sufficient to allow moderately technical users to guess at the correct content of the form. For this reason, highly technical documentation should go in OperationDefinition.comment.

It is anticipated that this would be used to automate development processes, rather than to generate end-user forms: such users will usually need more support than can be offered in a generated form.

Operations defined as part of this Specification

<%operationslist%>

StructureDefinition

Elements (Simplified)

Mappings

Mapping Exceptions

operationdefinition-definition-mapping-exceptions.xml

Divergent Elements

The determination of when to create a new version of a resource (same url, new version) vs. defining a new artifact is up to the author. Considerations for making this decision are found in Technical and Business Versions.

In some cases, the resource can no longer be found at the stated url, but the url itself cannot change. Implementations can use the meta.source element to indicate where the current master source of the resource can be found. | resource=Can be a urn:uuid: or a urn:oid: but real http: addresses are preferred. Multiple instances may share the same URL if they have a distinct version.

The determination of when to create a new version of a resource (same url, new version) vs. defining a new artifact is up to the author. Considerations for making this decision are found in Technical and Business Versions.

In some cases, the resource can no longer be found at the stated url, but the url itself cannot change. Implementations can use the meta.source element to indicate where the current master source of the resource can be found.

DEPRECATION NOTE: For consistency, implementations are encouraged to migrate to using the new 'jurisdiction' code in the useContext element. (I.e. useContext.code indicating http://terminology.hl7.org/CodeSystem/usage-context-type#jurisdiction and useContext.valueCodeableConcept indicating the jurisdiction.). | resource=It may be possible for the operation definition to be used in jurisdictions other than those for which it was originally designed or intended.

DEPRECATION NOTE: For consistency, implementations are encouraged to migrate to using the new 'jurisdiction' code in the useContext element. (I.e. useContext.code indicating http://terminology.hl7.org/CodeSystem/usage-context-type#jurisdiction and useContext.valueCodeableConcept indicating the jurisdiction.)

Unmapped Elements

operationdefinition-fivews-mapping-exceptions.xml

Unmapped Elements