Smile CDR can apply ConceptMap $translate mappings directly to a FHIR resource before it is persisted, adding the translated coding alongside the original.
This is a mapping-on-the-way-in approach: the translated code is added to the resource before it is stored, so downstream consumers see standardized codes immediately. The original coding is preserved unchanged. This contrasts with FHIR Response Terminology Enhancement, which applies mappings on the way out without modifying stored data.
In-place translation targets a single, fixed mapping:
Observation.codeis translated to LOINC (http://loinc.org). The resource type and target system are hard-coded.
For each create or update of an Observation:
Observation.code (the CodeableConcept translated in place).CodeableConcept already contains a coding in LOINC. If so, translation is considered complete and no action is taken.Coding elements in Observation.code.$translate operation using that coding's system and code, targeting LOINC.Coding to the CodeableConcept alongside the original, which is preserved unchanged.A $translate result is treated as a match when ConceptMap returns at least one mapping whose equivalence is not unmatched or disjoint. The first such mapping is used (results are not re-ranked). An equivalent mapping is the ideal case; other equivalences (equal, wider, narrower, subsumes, specializes, inexact, relatedto) are also accepted, with the usual caveat that a non-equivalent mapping may broaden or narrow meaning. If multiple ConceptMaps could apply, ConceptMap-based selection follows the standard $translate resolution rules — this service does not impose its own ranking.
| Feature | Direction | Modifies Stored Data | Use Case |
|---|---|---|---|
| Response Terminology Enhancement | On the way out | No | Return standardized codes to clients without altering stored resources |
| Terminology Mapping ($translate) | On demand | No | Manual or programmatic ConceptMap lookups |
| In-Place Code Translation | On the way in | Yes (when enabled as a storage interceptor) | Adds ConceptMap-based LOINC codings to Observation.code before storage |
In-place translation can be activated in two ways: automatically for all stored Observations via module configuration, or explicitly inside a Camel route. Both produce identical translation behaviour.
When enabled in the FHIR Storage module configuration, every Observation create and update has its Observation.code translated to LOINC before it is persisted. No code or Camel route changes are required.
Translation runs at the storage pre-storage stage:
STORAGE_PRESTORAGE_RESOURCE_CREATED — fires before a new resource is persistedSTORAGE_PRESTORAGE_RESOURCE_UPDATED — fires before an existing resource is updatedResources other than Observation pass through unchanged.
| Setting | Default | Description |
|---|---|---|
inplace_translate.interceptor.enabled | false | When true, Observation.code is automatically translated to LOINC on every create and update at module startup. |
inplaceTranslateProcessorThe inplaceTranslateProcessor is a built-in Smile Camel processor that applies in-place translation inside a Camel route. It receives an IBaseResource as the exchange body, translates its codings to the specified target system, and places the (possibly modified) resource back onto the exchange body.
smile:persistence/inplaceTranslateProcessor?targetSystem=http://loinc.orgIBaseResource — the FHIR resource whose codings should be translatedIBaseResource — the resource after translation (original codings preserved; translated coding added if found)| Parameter | Required | Description |
|---|---|---|
targetSystem | Yes | The target code system URI (e.g., http://loinc.org) |
The following Camel route reads Observations from a Kafka topic, applies in-place LOINC translation, and stores the result:
<routes xmlns="http://camel.apache.org/schema/spring">
<route id="inplace-translate-observation">
<from uri="kafka:observations-in?brokers=localhost:9092&groupId=translate-group&maxPollRecords=1&allowManualCommit=true&autoCommitEnable=false"/>
<!-- Translate codings to LOINC in-place -->
<to uri="smile:persistence/inplaceTranslateProcessor?targetSystem=http://loinc.org"/>
<!-- Persist the (possibly translated) resource -->
<to uri="smile:persistence/singleResourceProcessor"/>
<to uri="smile:clustermgr/kafkaManualCommit"/>
</route>
</routes>
Use this approach when translation is part of an explicit Camel integration route, or when you want fine-grained control over which resources are translated and when.
| Automatic Translation | Camel Processor | |
|---|---|---|
| Activation | Module config (inplace_translate.interceptor.enabled=true) | Explicit <to uri="smile:persistence/inplaceTranslateProcessor?..."/> in a route |
| Scope | All Observation create/update operations | Only resources that pass through the configured route |
| Control | Automatic — applies to all callers | Fine-grained per-route control |
| Best for | Blanket translation policy across all ingestion paths | Integration pipelines with explicit flow |
When in-place translation cannot find a ConceptMap mapping for a coding, Smile CDR can optionally dispatch the unmapped code to a missing-translation suggestion pipeline that asks a configured provider to suggest candidate codings.
The provider extension point is an internal SPI and is not a supported public API. Two providers ship built in: a non-production
mockfor wiring validation and awciprovider backed by the West Coast Informatics automap service.
flowchart TD
A[Observation create/update] --> B{Observation.code already LOINC?}
B -- yes --> Z[Persist unchanged]
B -- no --> C[ConceptMap $translate to LOINC]
C -- match --> D[Add LOINC coding alongside original] --> Z2[Persist translated]
C -- no match --> E{missing_translation_suggestion.enabled?}
E -- no --> Z3[Persist unchanged]
E -- yes --> F[Create / dedupe FHIR Task for unmapped code]
F --> G[Task Subscription delivers to broker channel]
G --> H[Task coordinator loads the source resource from the Task focus]
H --> H2[Coordinator invokes active provider]
H2 --> I[Write candidate codings onto the Task]
The FHIR Task representing an unmapped code transitions as follows:
stateDiagram-v2
[*] --> requested: Task created for unmapped code
requested --> ready: provider returned candidates, written to Task
requested --> failed: source resource unresolvable, or provider error
ready --> in_progress: operator selects a candidate coding
in_progress --> completed: ConceptMap updated, bulk patch submitted
in_progress --> failed: required selection inputs missing
requested --> cancelled: operator cancels
While a requested Task is being processed, the coordinator briefly sets it to the transient FHIR received status before it reaches ready or failed. This status is not a stable resting state — it may be observed momentarily by UI/webadmin observers polling the Task but is not a distinct step operators act on.
The source resource (the Task's focus reference) is required for suggestion processing. If it has been deleted or cannot be resolved by the time the Task is processed, the Task transitions directly to failed, the same as a provider error.
The suggestion pipeline is gated by two settings on the FHIR Storage module:
| Setting | Default | Description |
|---|---|---|
inplace_translate.missing_translation_suggestion.enabled | false | When true, codings that in-place translation cannot map via ConceptMap $translate are dispatched to the configured provider asynchronously through a FHIR Task. When false, unmapped codings are left untouched and no Task is ever created. |
missing_translation_suggestion.provider.active_name | (empty) | The name of the provider to use. Only consulted when missing_translation_suggestion.enabled is true; when that flag is on and this is blank, startup fails with a ConfigurationException. When set to a value that does not match any discovered provider, startup also fails with a ConfigurationException listing the known providers. |
mock ProviderA mock provider ships with Smile CDR for end-to-end wiring validation only. It becomes active only if you explicitly set missing_translation_suggestion.provider.active_name=mock. When active it ignores the request and always returns the same fixed list of five LOINC candidate codings with decreasing confidence (12345-6 at 0.95, 23456-7 at 0.80, 34567-8 at 0.65, 45678-9 at 0.50, 56789-0 at 0.35).
Do not select the mock provider in production. It is a placeholder and always returns the same stub result regardless of the input code.
wci ProviderA wci provider integrates with the West Coast Informatics (WCI) automap service. When active (missing_translation_suggestion.provider.active_name=wci), it builds a mapping request from the unmapped code's source system and code plus a WCI entity type derived from the source resource — the resource type, refined by the resource's category where one is defined (for example, an Observation categorized as vital-signs is submitted as a vital-sign term rather than the default lab result). It posts the request to the WCI service and maps the response into candidate codings. Candidates whose system does not match the requested target system are dropped, as are candidates below the confidence threshold; the remainder are ordered by confidence descending and capped at five.
The
wciprovider's configuration is hardcoded: the WCI service base URL ishttp://localhost:8080, the minimum confidence threshold is0.75, and at most5candidates are returned. The provider does not stand up or manage the WCI service itself — a reachable WCI instance must already be running.
If the source resource's type has no WCI entity-type mapping, or the WCI service is unreachable, returns a non-2xx status, or returns an unparseable body, the suggestion Task is recorded as failed.
| Feature | Trigger | Modifies Stored Data | Uses ConceptMap |
|---|---|---|---|
| Response Terminology Enhancement | On the way out | No | Yes |
| Terminology Mapping ($translate) | On demand | No | Yes |
| In-Place Code Translation | On the way in | Yes (when enabled) | Yes |
| Missing Translation Suggestion | Async, after ConceptMap miss | No (suggestions written to a Task) | No |
You are about to leave the Smile Digital Health documentation and navigate to the Open Source HAPI-FHIR Documentation.