diff --git a/.fern/metadata.json b/.fern/metadata.json
index 2d8e4bf..872c578 100644
--- a/.fern/metadata.json
+++ b/.fern/metadata.json
@@ -1,5 +1,5 @@
{
- "cliVersion": "5.49.0",
+ "cliVersion": "5.49.1",
"generatorName": "fernapi/fern-java-sdk",
"generatorVersion": "4.9.2",
"generatorConfig": {
@@ -10,10 +10,10 @@
"enable-wire-tests": true,
"publish-to": "central"
},
- "originGitCommit": "5084e3096e5bd89bf2e86ea44d96e3407f6f5c6b",
+ "originGitCommit": "788cec0a9a7651caf2b106634631d487dfa16704",
"originGitCommitIsDirty": true,
"invokedBy": "ci",
"requestedVersion": "AUTO",
"ciProvider": "unknown",
- "sdkVersion": "17.3.0"
+ "sdkVersion": "17.4.0"
}
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index ac6c355..9f65502 100644
--- a/build.gradle
+++ b/build.gradle
@@ -48,7 +48,7 @@ java {
group = 'com.phenoml.maven'
-version = '17.3.0'
+version = '17.4.0'
jar {
dependsOn(":generatePomFileForMavenPublication")
@@ -79,7 +79,7 @@ publishing {
maven(MavenPublication) {
groupId = 'com.phenoml.maven'
artifactId = 'phenoml-java-sdk'
- version = '17.3.0'
+ version = '17.4.0'
from components.java
pom {
name = 'phenoml'
diff --git a/changelog.md b/changelog.md
index f52f854..dd6a01c 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,3 +1,13 @@
+## [17.4.0] - 2026-06-15
+### Added
+- **`ConditionOccurrenceRow.getVisitOccurrenceId()`**, **`DrugExposureRow.getVisitOccurrenceId()`**, **`MeasurementRow.getVisitOccurrenceId()`**, **`ObservationRow.getVisitOccurrenceId()`**, and **`ProcedureOccurrenceRow.getVisitOccurrenceId()`** — new optional accessor linking each clinical OMOP row back to its `visit_occurrence` row.
+- **`MeasurementRow.getOperatorConceptId()`** — new optional accessor carrying the OMOP "Meas Value Operator" standard concept (`<`, `<=`, `>`, `>=`) parsed from a FHIR `valueQuantity.comparator` or numeric-string value; `0` when no operator is present.
+
+### Changed
+- **`MappingEntry.getTargetCode()`** — value semantics updated: now the standard concept's own code for `ALREADY_STANDARD`, `MAPPED`, and `UNCHECKED` rows; empty for `UNMAPPED` rows.
+- **`Summary`** — count-field docs clarify each total is counted once per resolved concept (not per coding), unlike `mappings`, which has one entry per coding.
+- **`PhenomlClient.fhir2Omop().create(...)` Javadoc** — clarifies that a clinical `concept_id` of `0` covers both `UNMAPPED` and `UNCHECKED`, and that `operator_concept_id` is the one non-zero non-resolved concept on measurement rows.
+
## [17.3.0] - 2026-06-15
### Added
- **`PhenomlClient.fhir2Omop().create()`** — new method (sync and async) posting a FHIR R4 resource or Bundle to `POST /fhir2omop/create` and returning typed OMOP CDM v5.4 rows in both `resolved` and `structural` modes.
diff --git a/code-examples.json b/code-examples.json
index f59a195..48af205 100644
--- a/code-examples.json
+++ b/code-examples.json
@@ -2,8 +2,8 @@
"metadata": {
"language": "java",
"packageName": "com.phenoml.maven:phenoml-java-sdk",
- "sdkVersion": "17.3.0",
- "specCommit": "5084e3096e5bd89bf2e86ea44d96e3407f6f5c6b",
+ "sdkVersion": "17.4.0",
+ "specCommit": "788cec0a9a7651caf2b106634631d487dfa16704",
"generatorName": "fernapi/fern-java-sdk"
},
"renderRules": {
@@ -2298,6 +2298,7 @@
"source_code": "44054006",
"source_name": "Type 2 diabetes mellitus",
"target_vocabulary": "SNOMED",
+ "target_code": "44054006",
"target_name": "Type 2 diabetes mellitus",
"mapping_status": "ALREADY_STANDARD"
},
@@ -2310,6 +2311,7 @@
"source_code": "860975",
"source_name": "metformin hydrochloride 500 MG",
"target_vocabulary": "RXNORM",
+ "target_code": "860975",
"target_name": "metformin hydrochloride 500 MG",
"mapping_status": "ALREADY_STANDARD"
}
diff --git a/reference.md b/reference.md
index 6164712..4792978 100644
--- a/reference.md
+++ b/reference.md
@@ -3043,12 +3043,15 @@ to the row it produced), `dropped` (resources that could not be shaped
into a row), `vocab_version` (the OMOP vocabulary release codes were
resolved against), and a small `summary` of the resolution outcomes.
-A `concept_id` of `0` means "no matching standard concept" (OMOP
-semantics) and is reported, not omitted — a coding with no match is
-`UNMAPPED`. Only the primary clinical coding is resolved;
+A `concept_id` of `0` is reported, not omitted (OMOP "no matching
+concept" semantics): it covers both a coding with no standard match
+(`UNMAPPED`) and an unverified suggestion for a text-only resource
+(`UNCHECKED`). Only the primary clinical coding is resolved, so
`gender`/`race`/`ethnicity`/`visit`/`value`/`unit` `concept_id`s are
-always `0`. Each `*_source_value` carries the verbatim FHIR coding
-(`system#code`), and `*_type_concept_id` is set to `32817` (EHR).
+always `0`; the one populated non-resolved concept is measurement
+`operator_concept_id`, set from a value comparator (`<`, `<=`, `>`, `>=`)
+rather than the resolver. Each `*_source_value` carries the verbatim FHIR
+coding (`system#code`), and `*_type_concept_id` is set to `32817` (EHR).
Medication codes are resolved whether they appear inline
(`medicationCodeableConcept`) or via a `medicationReference` to a contained,
diff --git a/src/main/java/com/phenoml/api/core/ClientOptions.java b/src/main/java/com/phenoml/api/core/ClientOptions.java
index 41183a7..89f6871 100644
--- a/src/main/java/com/phenoml/api/core/ClientOptions.java
+++ b/src/main/java/com/phenoml/api/core/ClientOptions.java
@@ -38,10 +38,10 @@ private ClientOptions(
this.headers.putAll(headers);
this.headers.putAll(new HashMap() {
{
- put("User-Agent", "com.phenoml.maven:phenoml-java-sdk/17.3.0");
+ put("User-Agent", "com.phenoml.maven:phenoml-java-sdk/17.4.0");
put("X-Fern-Language", "JAVA");
put("X-Fern-SDK-Name", "com.phenoml.fern:api-sdk");
- put("X-Fern-SDK-Version", "17.3.0");
+ put("X-Fern-SDK-Version", "17.4.0");
}
});
this.headerSuppliers = headerSuppliers;
diff --git a/src/main/java/com/phenoml/api/resources/fhir2omop/AsyncFhir2OmopClient.java b/src/main/java/com/phenoml/api/resources/fhir2omop/AsyncFhir2OmopClient.java
index 01d7fed..907d42a 100644
--- a/src/main/java/com/phenoml/api/resources/fhir2omop/AsyncFhir2OmopClient.java
+++ b/src/main/java/com/phenoml/api/resources/fhir2omop/AsyncFhir2OmopClient.java
@@ -36,12 +36,15 @@ public AsyncRawFhir2OmopClient withRawResponse() {
* to the row it produced), dropped (resources that could not be shaped
* into a row), vocab_version (the OMOP vocabulary release codes were
* resolved against), and a small summary of the resolution outcomes.
- * A concept_id of 0 means "no matching standard concept" (OMOP
- * semantics) and is reported, not omitted — a coding with no match is
- * UNMAPPED. Only the primary clinical coding is resolved;
+ *
A concept_id of 0 is reported, not omitted (OMOP "no matching
+ * concept" semantics): it covers both a coding with no standard match
+ * (UNMAPPED) and an unverified suggestion for a text-only resource
+ * (UNCHECKED). Only the primary clinical coding is resolved, so
* gender/race/ethnicity/visit/value/unit concept_ids are
- * always 0. Each *_source_value carries the verbatim FHIR coding
- * (system#code), and *_type_concept_id is set to 32817 (EHR).
+ * always 0; the one populated non-resolved concept is measurement
+ * operator_concept_id, set from a value comparator (<, <=, >, >=)
+ * rather than the resolver. Each *_source_value carries the verbatim FHIR
+ * coding (system#code), and *_type_concept_id is set to 32817 (EHR).
* Medication codes are resolved whether they appear inline
* (medicationCodeableConcept) or via a medicationReference to a contained,
* relative (Type/id), or bundle-entry (urn:uuid) Medication resource.
@@ -65,12 +68,15 @@ public CompletableFuture create(CreateOmopRequest request) {
* to the row it produced), dropped (resources that could not be shaped
* into a row), vocab_version (the OMOP vocabulary release codes were
* resolved against), and a small summary of the resolution outcomes.
- * A concept_id of 0 means "no matching standard concept" (OMOP
- * semantics) and is reported, not omitted — a coding with no match is
- * UNMAPPED. Only the primary clinical coding is resolved;
+ *
A concept_id of 0 is reported, not omitted (OMOP "no matching
+ * concept" semantics): it covers both a coding with no standard match
+ * (UNMAPPED) and an unverified suggestion for a text-only resource
+ * (UNCHECKED). Only the primary clinical coding is resolved, so
* gender/race/ethnicity/visit/value/unit concept_ids are
- * always 0. Each *_source_value carries the verbatim FHIR coding
- * (system#code), and *_type_concept_id is set to 32817 (EHR).
+ * always 0; the one populated non-resolved concept is measurement
+ * operator_concept_id, set from a value comparator (<, <=, >, >=)
+ * rather than the resolver. Each *_source_value carries the verbatim FHIR
+ * coding (system#code), and *_type_concept_id is set to 32817 (EHR).
* Medication codes are resolved whether they appear inline
* (medicationCodeableConcept) or via a medicationReference to a contained,
* relative (Type/id), or bundle-entry (urn:uuid) Medication resource.
diff --git a/src/main/java/com/phenoml/api/resources/fhir2omop/AsyncRawFhir2OmopClient.java b/src/main/java/com/phenoml/api/resources/fhir2omop/AsyncRawFhir2OmopClient.java
index 99d71da..a6f3f84 100644
--- a/src/main/java/com/phenoml/api/resources/fhir2omop/AsyncRawFhir2OmopClient.java
+++ b/src/main/java/com/phenoml/api/resources/fhir2omop/AsyncRawFhir2OmopClient.java
@@ -47,12 +47,15 @@ public AsyncRawFhir2OmopClient(ClientOptions clientOptions) {
* to the row it produced), dropped (resources that could not be shaped
* into a row), vocab_version (the OMOP vocabulary release codes were
* resolved against), and a small summary of the resolution outcomes.
- * A concept_id of 0 means "no matching standard concept" (OMOP
- * semantics) and is reported, not omitted — a coding with no match is
- * UNMAPPED. Only the primary clinical coding is resolved;
+ *
A concept_id of 0 is reported, not omitted (OMOP "no matching
+ * concept" semantics): it covers both a coding with no standard match
+ * (UNMAPPED) and an unverified suggestion for a text-only resource
+ * (UNCHECKED). Only the primary clinical coding is resolved, so
* gender/race/ethnicity/visit/value/unit concept_ids are
- * always 0. Each *_source_value carries the verbatim FHIR coding
- * (system#code), and *_type_concept_id is set to 32817 (EHR).
+ * always 0; the one populated non-resolved concept is measurement
+ * operator_concept_id, set from a value comparator (<, <=, >, >=)
+ * rather than the resolver. Each *_source_value carries the verbatim FHIR
+ * coding (system#code), and *_type_concept_id is set to 32817 (EHR).
* Medication codes are resolved whether they appear inline
* (medicationCodeableConcept) or via a medicationReference to a contained,
* relative (Type/id), or bundle-entry (urn:uuid) Medication resource.
@@ -76,12 +79,15 @@ public CompletableFuture> create(C
* to the row it produced), dropped (resources that could not be shaped
* into a row), vocab_version (the OMOP vocabulary release codes were
* resolved against), and a small summary of the resolution outcomes.
- * A concept_id of 0 means "no matching standard concept" (OMOP
- * semantics) and is reported, not omitted — a coding with no match is
- * UNMAPPED. Only the primary clinical coding is resolved;
+ *
A concept_id of 0 is reported, not omitted (OMOP "no matching
+ * concept" semantics): it covers both a coding with no standard match
+ * (UNMAPPED) and an unverified suggestion for a text-only resource
+ * (UNCHECKED). Only the primary clinical coding is resolved, so
* gender/race/ethnicity/visit/value/unit concept_ids are
- * always 0. Each *_source_value carries the verbatim FHIR coding
- * (system#code), and *_type_concept_id is set to 32817 (EHR).
+ * always 0; the one populated non-resolved concept is measurement
+ * operator_concept_id, set from a value comparator (<, <=, >, >=)
+ * rather than the resolver. Each *_source_value carries the verbatim FHIR
+ * coding (system#code), and *_type_concept_id is set to 32817 (EHR).
* Medication codes are resolved whether they appear inline
* (medicationCodeableConcept) or via a medicationReference to a contained,
* relative (Type/id), or bundle-entry (urn:uuid) Medication resource.
diff --git a/src/main/java/com/phenoml/api/resources/fhir2omop/Fhir2OmopClient.java b/src/main/java/com/phenoml/api/resources/fhir2omop/Fhir2OmopClient.java
index 40decc3..8f44914 100644
--- a/src/main/java/com/phenoml/api/resources/fhir2omop/Fhir2OmopClient.java
+++ b/src/main/java/com/phenoml/api/resources/fhir2omop/Fhir2OmopClient.java
@@ -35,12 +35,15 @@ public RawFhir2OmopClient withRawResponse() {
* to the row it produced), dropped (resources that could not be shaped
* into a row), vocab_version (the OMOP vocabulary release codes were
* resolved against), and a small summary of the resolution outcomes.
- * A concept_id of 0 means "no matching standard concept" (OMOP
- * semantics) and is reported, not omitted — a coding with no match is
- * UNMAPPED. Only the primary clinical coding is resolved;
+ *
A concept_id of 0 is reported, not omitted (OMOP "no matching
+ * concept" semantics): it covers both a coding with no standard match
+ * (UNMAPPED) and an unverified suggestion for a text-only resource
+ * (UNCHECKED). Only the primary clinical coding is resolved, so
* gender/race/ethnicity/visit/value/unit concept_ids are
- * always 0. Each *_source_value carries the verbatim FHIR coding
- * (system#code), and *_type_concept_id is set to 32817 (EHR).
+ * always 0; the one populated non-resolved concept is measurement
+ * operator_concept_id, set from a value comparator (<, <=, >, >=)
+ * rather than the resolver. Each *_source_value carries the verbatim FHIR
+ * coding (system#code), and *_type_concept_id is set to 32817 (EHR).
* Medication codes are resolved whether they appear inline
* (medicationCodeableConcept) or via a medicationReference to a contained,
* relative (Type/id), or bundle-entry (urn:uuid) Medication resource.
@@ -64,12 +67,15 @@ public CreateOmopResponse create(CreateOmopRequest request) {
* to the row it produced), dropped (resources that could not be shaped
* into a row), vocab_version (the OMOP vocabulary release codes were
* resolved against), and a small summary of the resolution outcomes.
- * A concept_id of 0 means "no matching standard concept" (OMOP
- * semantics) and is reported, not omitted — a coding with no match is
- * UNMAPPED. Only the primary clinical coding is resolved;
+ *
A concept_id of 0 is reported, not omitted (OMOP "no matching
+ * concept" semantics): it covers both a coding with no standard match
+ * (UNMAPPED) and an unverified suggestion for a text-only resource
+ * (UNCHECKED). Only the primary clinical coding is resolved, so
* gender/race/ethnicity/visit/value/unit concept_ids are
- * always 0. Each *_source_value carries the verbatim FHIR coding
- * (system#code), and *_type_concept_id is set to 32817 (EHR).
+ * always 0; the one populated non-resolved concept is measurement
+ * operator_concept_id, set from a value comparator (<, <=, >, >=)
+ * rather than the resolver. Each *_source_value carries the verbatim FHIR
+ * coding (system#code), and *_type_concept_id is set to 32817 (EHR).
* Medication codes are resolved whether they appear inline
* (medicationCodeableConcept) or via a medicationReference to a contained,
* relative (Type/id), or bundle-entry (urn:uuid) Medication resource.
diff --git a/src/main/java/com/phenoml/api/resources/fhir2omop/RawFhir2OmopClient.java b/src/main/java/com/phenoml/api/resources/fhir2omop/RawFhir2OmopClient.java
index a485e4b..5f16e04 100644
--- a/src/main/java/com/phenoml/api/resources/fhir2omop/RawFhir2OmopClient.java
+++ b/src/main/java/com/phenoml/api/resources/fhir2omop/RawFhir2OmopClient.java
@@ -43,12 +43,15 @@ public RawFhir2OmopClient(ClientOptions clientOptions) {
* to the row it produced), dropped (resources that could not be shaped
* into a row), vocab_version (the OMOP vocabulary release codes were
* resolved against), and a small summary of the resolution outcomes.
- * A concept_id of 0 means "no matching standard concept" (OMOP
- * semantics) and is reported, not omitted — a coding with no match is
- * UNMAPPED. Only the primary clinical coding is resolved;
+ *
A concept_id of 0 is reported, not omitted (OMOP "no matching
+ * concept" semantics): it covers both a coding with no standard match
+ * (UNMAPPED) and an unverified suggestion for a text-only resource
+ * (UNCHECKED). Only the primary clinical coding is resolved, so
* gender/race/ethnicity/visit/value/unit concept_ids are
- * always 0. Each *_source_value carries the verbatim FHIR coding
- * (system#code), and *_type_concept_id is set to 32817 (EHR).
+ * always 0; the one populated non-resolved concept is measurement
+ * operator_concept_id, set from a value comparator (<, <=, >, >=)
+ * rather than the resolver. Each *_source_value carries the verbatim FHIR
+ * coding (system#code), and *_type_concept_id is set to 32817 (EHR).
* Medication codes are resolved whether they appear inline
* (medicationCodeableConcept) or via a medicationReference to a contained,
* relative (Type/id), or bundle-entry (urn:uuid) Medication resource.
@@ -72,12 +75,15 @@ public PhenomlClientHttpResponse create(CreateOmopRequest re
* to the row it produced), dropped (resources that could not be shaped
* into a row), vocab_version (the OMOP vocabulary release codes were
* resolved against), and a small summary of the resolution outcomes.
- * A concept_id of 0 means "no matching standard concept" (OMOP
- * semantics) and is reported, not omitted — a coding with no match is
- * UNMAPPED. Only the primary clinical coding is resolved;
+ *
A concept_id of 0 is reported, not omitted (OMOP "no matching
+ * concept" semantics): it covers both a coding with no standard match
+ * (UNMAPPED) and an unverified suggestion for a text-only resource
+ * (UNCHECKED). Only the primary clinical coding is resolved, so
* gender/race/ethnicity/visit/value/unit concept_ids are
- * always 0. Each *_source_value carries the verbatim FHIR coding
- * (system#code), and *_type_concept_id is set to 32817 (EHR).
+ * always 0; the one populated non-resolved concept is measurement
+ * operator_concept_id, set from a value comparator (<, <=, >, >=)
+ * rather than the resolver. Each *_source_value carries the verbatim FHIR
+ * coding (system#code), and *_type_concept_id is set to 32817 (EHR).
* Medication codes are resolved whether they appear inline
* (medicationCodeableConcept) or via a medicationReference to a contained,
* relative (Type/id), or bundle-entry (urn:uuid) Medication resource.
diff --git a/src/main/java/com/phenoml/api/resources/fhir2omop/types/ConditionOccurrenceRow.java b/src/main/java/com/phenoml/api/resources/fhir2omop/types/ConditionOccurrenceRow.java
index 03e9283..babf04b 100644
--- a/src/main/java/com/phenoml/api/resources/fhir2omop/types/ConditionOccurrenceRow.java
+++ b/src/main/java/com/phenoml/api/resources/fhir2omop/types/ConditionOccurrenceRow.java
@@ -34,6 +34,8 @@ public final class ConditionOccurrenceRow {
private final Optional conditionTypeConceptId;
+ private final Optional visitOccurrenceId;
+
private final Optional conditionSourceValue;
private final Optional conditionSourceConceptId;
@@ -50,6 +52,7 @@ private ConditionOccurrenceRow(
Optional conditionStartDatetime,
Optional conditionEndDate,
Optional conditionTypeConceptId,
+ Optional visitOccurrenceId,
Optional conditionSourceValue,
Optional conditionSourceConceptId,
Optional conditionStatusSourceValue,
@@ -61,6 +64,7 @@ private ConditionOccurrenceRow(
this.conditionStartDatetime = conditionStartDatetime;
this.conditionEndDate = conditionEndDate;
this.conditionTypeConceptId = conditionTypeConceptId;
+ this.visitOccurrenceId = visitOccurrenceId;
this.conditionSourceValue = conditionSourceValue;
this.conditionSourceConceptId = conditionSourceConceptId;
this.conditionStatusSourceValue = conditionStatusSourceValue;
@@ -102,6 +106,11 @@ public Optional getConditionTypeConceptId() {
return conditionTypeConceptId;
}
+ @JsonProperty("visit_occurrence_id")
+ public Optional getVisitOccurrenceId() {
+ return visitOccurrenceId;
+ }
+
@JsonProperty("condition_source_value")
public Optional getConditionSourceValue() {
return conditionSourceValue;
@@ -136,6 +145,7 @@ private boolean equalTo(ConditionOccurrenceRow other) {
&& conditionStartDatetime.equals(other.conditionStartDatetime)
&& conditionEndDate.equals(other.conditionEndDate)
&& conditionTypeConceptId.equals(other.conditionTypeConceptId)
+ && visitOccurrenceId.equals(other.visitOccurrenceId)
&& conditionSourceValue.equals(other.conditionSourceValue)
&& conditionSourceConceptId.equals(other.conditionSourceConceptId)
&& conditionStatusSourceValue.equals(other.conditionStatusSourceValue);
@@ -151,6 +161,7 @@ public int hashCode() {
this.conditionStartDatetime,
this.conditionEndDate,
this.conditionTypeConceptId,
+ this.visitOccurrenceId,
this.conditionSourceValue,
this.conditionSourceConceptId,
this.conditionStatusSourceValue);
@@ -181,6 +192,8 @@ public static final class Builder {
private Optional conditionTypeConceptId = Optional.empty();
+ private Optional visitOccurrenceId = Optional.empty();
+
private Optional conditionSourceValue = Optional.empty();
private Optional conditionSourceConceptId = Optional.empty();
@@ -200,6 +213,7 @@ public Builder from(ConditionOccurrenceRow other) {
conditionStartDatetime(other.getConditionStartDatetime());
conditionEndDate(other.getConditionEndDate());
conditionTypeConceptId(other.getConditionTypeConceptId());
+ visitOccurrenceId(other.getVisitOccurrenceId());
conditionSourceValue(other.getConditionSourceValue());
conditionSourceConceptId(other.getConditionSourceConceptId());
conditionStatusSourceValue(other.getConditionStatusSourceValue());
@@ -283,6 +297,17 @@ public Builder conditionTypeConceptId(Long conditionTypeConceptId) {
return this;
}
+ @JsonSetter(value = "visit_occurrence_id", nulls = Nulls.SKIP)
+ public Builder visitOccurrenceId(Optional visitOccurrenceId) {
+ this.visitOccurrenceId = visitOccurrenceId;
+ return this;
+ }
+
+ public Builder visitOccurrenceId(Long visitOccurrenceId) {
+ this.visitOccurrenceId = Optional.ofNullable(visitOccurrenceId);
+ return this;
+ }
+
@JsonSetter(value = "condition_source_value", nulls = Nulls.SKIP)
public Builder conditionSourceValue(Optional conditionSourceValue) {
this.conditionSourceValue = conditionSourceValue;
@@ -325,6 +350,7 @@ public ConditionOccurrenceRow build() {
conditionStartDatetime,
conditionEndDate,
conditionTypeConceptId,
+ visitOccurrenceId,
conditionSourceValue,
conditionSourceConceptId,
conditionStatusSourceValue,
diff --git a/src/main/java/com/phenoml/api/resources/fhir2omop/types/DrugExposureRow.java b/src/main/java/com/phenoml/api/resources/fhir2omop/types/DrugExposureRow.java
index 4b77b60..c82620c 100644
--- a/src/main/java/com/phenoml/api/resources/fhir2omop/types/DrugExposureRow.java
+++ b/src/main/java/com/phenoml/api/resources/fhir2omop/types/DrugExposureRow.java
@@ -38,6 +38,8 @@ public final class DrugExposureRow {
private final Optional sig;
+ private final Optional visitOccurrenceId;
+
private final Optional drugSourceValue;
private final Optional drugSourceConceptId;
@@ -54,6 +56,7 @@ private DrugExposureRow(
Optional drugTypeConceptId,
Optional stopReason,
Optional sig,
+ Optional visitOccurrenceId,
Optional drugSourceValue,
Optional drugSourceConceptId,
Map additionalProperties) {
@@ -66,6 +69,7 @@ private DrugExposureRow(
this.drugTypeConceptId = drugTypeConceptId;
this.stopReason = stopReason;
this.sig = sig;
+ this.visitOccurrenceId = visitOccurrenceId;
this.drugSourceValue = drugSourceValue;
this.drugSourceConceptId = drugSourceConceptId;
this.additionalProperties = additionalProperties;
@@ -116,6 +120,11 @@ public Optional getSig() {
return sig;
}
+ @JsonProperty("visit_occurrence_id")
+ public Optional getVisitOccurrenceId() {
+ return visitOccurrenceId;
+ }
+
@JsonProperty("drug_source_value")
public Optional getDrugSourceValue() {
return drugSourceValue;
@@ -147,6 +156,7 @@ private boolean equalTo(DrugExposureRow other) {
&& drugTypeConceptId.equals(other.drugTypeConceptId)
&& stopReason.equals(other.stopReason)
&& sig.equals(other.sig)
+ && visitOccurrenceId.equals(other.visitOccurrenceId)
&& drugSourceValue.equals(other.drugSourceValue)
&& drugSourceConceptId.equals(other.drugSourceConceptId);
}
@@ -163,6 +173,7 @@ public int hashCode() {
this.drugTypeConceptId,
this.stopReason,
this.sig,
+ this.visitOccurrenceId,
this.drugSourceValue,
this.drugSourceConceptId);
}
@@ -196,6 +207,8 @@ public static final class Builder {
private Optional sig = Optional.empty();
+ private Optional visitOccurrenceId = Optional.empty();
+
private Optional drugSourceValue = Optional.empty();
private Optional drugSourceConceptId = Optional.empty();
@@ -215,6 +228,7 @@ public Builder from(DrugExposureRow other) {
drugTypeConceptId(other.getDrugTypeConceptId());
stopReason(other.getStopReason());
sig(other.getSig());
+ visitOccurrenceId(other.getVisitOccurrenceId());
drugSourceValue(other.getDrugSourceValue());
drugSourceConceptId(other.getDrugSourceConceptId());
return this;
@@ -319,6 +333,17 @@ public Builder sig(String sig) {
return this;
}
+ @JsonSetter(value = "visit_occurrence_id", nulls = Nulls.SKIP)
+ public Builder visitOccurrenceId(Optional visitOccurrenceId) {
+ this.visitOccurrenceId = visitOccurrenceId;
+ return this;
+ }
+
+ public Builder visitOccurrenceId(Long visitOccurrenceId) {
+ this.visitOccurrenceId = Optional.ofNullable(visitOccurrenceId);
+ return this;
+ }
+
@JsonSetter(value = "drug_source_value", nulls = Nulls.SKIP)
public Builder drugSourceValue(Optional drugSourceValue) {
this.drugSourceValue = drugSourceValue;
@@ -352,6 +377,7 @@ public DrugExposureRow build() {
drugTypeConceptId,
stopReason,
sig,
+ visitOccurrenceId,
drugSourceValue,
drugSourceConceptId,
additionalProperties);
diff --git a/src/main/java/com/phenoml/api/resources/fhir2omop/types/MappingEntry.java b/src/main/java/com/phenoml/api/resources/fhir2omop/types/MappingEntry.java
index 1b6d07c..73bbb33 100644
--- a/src/main/java/com/phenoml/api/resources/fhir2omop/types/MappingEntry.java
+++ b/src/main/java/com/phenoml/api/resources/fhir2omop/types/MappingEntry.java
@@ -121,12 +121,10 @@ public Optional getTargetVocabulary() {
}
/**
- * @return The standard concept's code, when present. Populated only for an
- * UNCHECKED suggestion (where the API normalized a text-only resource
- * to a suggested code); omitted for codings resolved through concept
- * resolution (ALREADY_STANDARD / MAPPED / UNMAPPED), which are
- * identified by target_vocabulary, target_name, and the row's
- * *_concept_id rather than by code.
+ * @return The standard concept's own code: the source code itself for an
+ * ALREADY_STANDARD row, the standard concept's code for a MAPPED row,
+ * or the suggested code for an UNCHECKED row. Omitted for UNMAPPED
+ * rows.
*/
@JsonProperty("target_code")
public Optional getTargetCode() {
@@ -348,12 +346,10 @@ public Builder targetVocabulary(String targetVocabulary) {
}
/**
- * The standard concept's code, when present. Populated only for an
- * UNCHECKED suggestion (where the API normalized a text-only resource
- * to a suggested code); omitted for codings resolved through concept
- * resolution (ALREADY_STANDARD / MAPPED / UNMAPPED), which are
- * identified by target_vocabulary, target_name, and the row's
- * *_concept_id rather than by code.
+ * The standard concept's own code: the source code itself for an
+ * ALREADY_STANDARD row, the standard concept's code for a MAPPED row,
+ * or the suggested code for an UNCHECKED row. Omitted for UNMAPPED
+ * rows.
*/
@JsonSetter(value = "target_code", nulls = Nulls.SKIP)
public Builder targetCode(Optional targetCode) {
diff --git a/src/main/java/com/phenoml/api/resources/fhir2omop/types/MeasurementRow.java b/src/main/java/com/phenoml/api/resources/fhir2omop/types/MeasurementRow.java
index ccf5225..ecbb2dd 100644
--- a/src/main/java/com/phenoml/api/resources/fhir2omop/types/MeasurementRow.java
+++ b/src/main/java/com/phenoml/api/resources/fhir2omop/types/MeasurementRow.java
@@ -34,6 +34,8 @@ public final class MeasurementRow {
private final Optional valueAsNumber;
+ private final Optional operatorConceptId;
+
private final Optional valueAsConceptId;
private final Optional unitConceptId;
@@ -42,6 +44,8 @@ public final class MeasurementRow {
private final Optional rangeHigh;
+ private final Optional visitOccurrenceId;
+
private final Optional measurementSourceValue;
private final Optional measurementSourceConceptId;
@@ -60,10 +64,12 @@ private MeasurementRow(
Optional measurementDatetime,
Optional measurementTypeConceptId,
Optional valueAsNumber,
+ Optional operatorConceptId,
Optional valueAsConceptId,
Optional unitConceptId,
Optional rangeLow,
Optional rangeHigh,
+ Optional visitOccurrenceId,
Optional measurementSourceValue,
Optional measurementSourceConceptId,
Optional unitSourceValue,
@@ -76,10 +82,12 @@ private MeasurementRow(
this.measurementDatetime = measurementDatetime;
this.measurementTypeConceptId = measurementTypeConceptId;
this.valueAsNumber = valueAsNumber;
+ this.operatorConceptId = operatorConceptId;
this.valueAsConceptId = valueAsConceptId;
this.unitConceptId = unitConceptId;
this.rangeLow = rangeLow;
this.rangeHigh = rangeHigh;
+ this.visitOccurrenceId = visitOccurrenceId;
this.measurementSourceValue = measurementSourceValue;
this.measurementSourceConceptId = measurementSourceConceptId;
this.unitSourceValue = unitSourceValue;
@@ -122,6 +130,14 @@ public Optional getValueAsNumber() {
return valueAsNumber;
}
+ /**
+ * @return OMOP "Meas Value Operator" standard concept qualifying value_as_number (<, <=, >, >=), parsed from a numeric-string value or a FHIR valueQuantity.comparator. 0 when no operator (a bare number).
+ */
+ @JsonProperty("operator_concept_id")
+ public Optional getOperatorConceptId() {
+ return operatorConceptId;
+ }
+
@JsonProperty("value_as_concept_id")
public Optional getValueAsConceptId() {
return valueAsConceptId;
@@ -142,6 +158,11 @@ public Optional getRangeHigh() {
return rangeHigh;
}
+ @JsonProperty("visit_occurrence_id")
+ public Optional getVisitOccurrenceId() {
+ return visitOccurrenceId;
+ }
+
@JsonProperty("measurement_source_value")
public Optional getMeasurementSourceValue() {
return measurementSourceValue;
@@ -181,10 +202,12 @@ private boolean equalTo(MeasurementRow other) {
&& measurementDatetime.equals(other.measurementDatetime)
&& measurementTypeConceptId.equals(other.measurementTypeConceptId)
&& valueAsNumber.equals(other.valueAsNumber)
+ && operatorConceptId.equals(other.operatorConceptId)
&& valueAsConceptId.equals(other.valueAsConceptId)
&& unitConceptId.equals(other.unitConceptId)
&& rangeLow.equals(other.rangeLow)
&& rangeHigh.equals(other.rangeHigh)
+ && visitOccurrenceId.equals(other.visitOccurrenceId)
&& measurementSourceValue.equals(other.measurementSourceValue)
&& measurementSourceConceptId.equals(other.measurementSourceConceptId)
&& unitSourceValue.equals(other.unitSourceValue)
@@ -201,10 +224,12 @@ public int hashCode() {
this.measurementDatetime,
this.measurementTypeConceptId,
this.valueAsNumber,
+ this.operatorConceptId,
this.valueAsConceptId,
this.unitConceptId,
this.rangeLow,
this.rangeHigh,
+ this.visitOccurrenceId,
this.measurementSourceValue,
this.measurementSourceConceptId,
this.unitSourceValue,
@@ -236,6 +261,8 @@ public static final class Builder {
private Optional valueAsNumber = Optional.empty();
+ private Optional operatorConceptId = Optional.empty();
+
private Optional valueAsConceptId = Optional.empty();
private Optional unitConceptId = Optional.empty();
@@ -244,6 +271,8 @@ public static final class Builder {
private Optional rangeHigh = Optional.empty();
+ private Optional visitOccurrenceId = Optional.empty();
+
private Optional measurementSourceValue = Optional.empty();
private Optional measurementSourceConceptId = Optional.empty();
@@ -265,10 +294,12 @@ public Builder from(MeasurementRow other) {
measurementDatetime(other.getMeasurementDatetime());
measurementTypeConceptId(other.getMeasurementTypeConceptId());
valueAsNumber(other.getValueAsNumber());
+ operatorConceptId(other.getOperatorConceptId());
valueAsConceptId(other.getValueAsConceptId());
unitConceptId(other.getUnitConceptId());
rangeLow(other.getRangeLow());
rangeHigh(other.getRangeHigh());
+ visitOccurrenceId(other.getVisitOccurrenceId());
measurementSourceValue(other.getMeasurementSourceValue());
measurementSourceConceptId(other.getMeasurementSourceConceptId());
unitSourceValue(other.getUnitSourceValue());
@@ -353,6 +384,20 @@ public Builder valueAsNumber(Double valueAsNumber) {
return this;
}
+ /**
+ * OMOP "Meas Value Operator" standard concept qualifying value_as_number (<, <=, >, >=), parsed from a numeric-string value or a FHIR valueQuantity.comparator. 0 when no operator (a bare number).
+ */
+ @JsonSetter(value = "operator_concept_id", nulls = Nulls.SKIP)
+ public Builder operatorConceptId(Optional operatorConceptId) {
+ this.operatorConceptId = operatorConceptId;
+ return this;
+ }
+
+ public Builder operatorConceptId(Long operatorConceptId) {
+ this.operatorConceptId = Optional.ofNullable(operatorConceptId);
+ return this;
+ }
+
@JsonSetter(value = "value_as_concept_id", nulls = Nulls.SKIP)
public Builder valueAsConceptId(Optional valueAsConceptId) {
this.valueAsConceptId = valueAsConceptId;
@@ -397,6 +442,17 @@ public Builder rangeHigh(Double rangeHigh) {
return this;
}
+ @JsonSetter(value = "visit_occurrence_id", nulls = Nulls.SKIP)
+ public Builder visitOccurrenceId(Optional visitOccurrenceId) {
+ this.visitOccurrenceId = visitOccurrenceId;
+ return this;
+ }
+
+ public Builder visitOccurrenceId(Long visitOccurrenceId) {
+ this.visitOccurrenceId = Optional.ofNullable(visitOccurrenceId);
+ return this;
+ }
+
@JsonSetter(value = "measurement_source_value", nulls = Nulls.SKIP)
public Builder measurementSourceValue(Optional measurementSourceValue) {
this.measurementSourceValue = measurementSourceValue;
@@ -450,10 +506,12 @@ public MeasurementRow build() {
measurementDatetime,
measurementTypeConceptId,
valueAsNumber,
+ operatorConceptId,
valueAsConceptId,
unitConceptId,
rangeLow,
rangeHigh,
+ visitOccurrenceId,
measurementSourceValue,
measurementSourceConceptId,
unitSourceValue,
diff --git a/src/main/java/com/phenoml/api/resources/fhir2omop/types/ObservationRow.java b/src/main/java/com/phenoml/api/resources/fhir2omop/types/ObservationRow.java
index d8ea202..86f2408 100644
--- a/src/main/java/com/phenoml/api/resources/fhir2omop/types/ObservationRow.java
+++ b/src/main/java/com/phenoml/api/resources/fhir2omop/types/ObservationRow.java
@@ -40,6 +40,8 @@ public final class ObservationRow {
private final Optional unitConceptId;
+ private final Optional visitOccurrenceId;
+
private final Optional observationSourceValue;
private final Optional observationSourceConceptId;
@@ -61,6 +63,7 @@ private ObservationRow(
Optional valueAsString,
Optional valueAsConceptId,
Optional unitConceptId,
+ Optional visitOccurrenceId,
Optional observationSourceValue,
Optional observationSourceConceptId,
Optional unitSourceValue,
@@ -76,6 +79,7 @@ private ObservationRow(
this.valueAsString = valueAsString;
this.valueAsConceptId = valueAsConceptId;
this.unitConceptId = unitConceptId;
+ this.visitOccurrenceId = visitOccurrenceId;
this.observationSourceValue = observationSourceValue;
this.observationSourceConceptId = observationSourceConceptId;
this.unitSourceValue = unitSourceValue;
@@ -133,6 +137,11 @@ public Optional getUnitConceptId() {
return unitConceptId;
}
+ @JsonProperty("visit_occurrence_id")
+ public Optional getVisitOccurrenceId() {
+ return visitOccurrenceId;
+ }
+
@JsonProperty("observation_source_value")
public Optional getObservationSourceValue() {
return observationSourceValue;
@@ -175,6 +184,7 @@ private boolean equalTo(ObservationRow other) {
&& valueAsString.equals(other.valueAsString)
&& valueAsConceptId.equals(other.valueAsConceptId)
&& unitConceptId.equals(other.unitConceptId)
+ && visitOccurrenceId.equals(other.visitOccurrenceId)
&& observationSourceValue.equals(other.observationSourceValue)
&& observationSourceConceptId.equals(other.observationSourceConceptId)
&& unitSourceValue.equals(other.unitSourceValue)
@@ -194,6 +204,7 @@ public int hashCode() {
this.valueAsString,
this.valueAsConceptId,
this.unitConceptId,
+ this.visitOccurrenceId,
this.observationSourceValue,
this.observationSourceConceptId,
this.unitSourceValue,
@@ -231,6 +242,8 @@ public static final class Builder {
private Optional unitConceptId = Optional.empty();
+ private Optional visitOccurrenceId = Optional.empty();
+
private Optional observationSourceValue = Optional.empty();
private Optional observationSourceConceptId = Optional.empty();
@@ -255,6 +268,7 @@ public Builder from(ObservationRow other) {
valueAsString(other.getValueAsString());
valueAsConceptId(other.getValueAsConceptId());
unitConceptId(other.getUnitConceptId());
+ visitOccurrenceId(other.getVisitOccurrenceId());
observationSourceValue(other.getObservationSourceValue());
observationSourceConceptId(other.getObservationSourceConceptId());
unitSourceValue(other.getUnitSourceValue());
@@ -372,6 +386,17 @@ public Builder unitConceptId(Long unitConceptId) {
return this;
}
+ @JsonSetter(value = "visit_occurrence_id", nulls = Nulls.SKIP)
+ public Builder visitOccurrenceId(Optional visitOccurrenceId) {
+ this.visitOccurrenceId = visitOccurrenceId;
+ return this;
+ }
+
+ public Builder visitOccurrenceId(Long visitOccurrenceId) {
+ this.visitOccurrenceId = Optional.ofNullable(visitOccurrenceId);
+ return this;
+ }
+
@JsonSetter(value = "observation_source_value", nulls = Nulls.SKIP)
public Builder observationSourceValue(Optional observationSourceValue) {
this.observationSourceValue = observationSourceValue;
@@ -428,6 +453,7 @@ public ObservationRow build() {
valueAsString,
valueAsConceptId,
unitConceptId,
+ visitOccurrenceId,
observationSourceValue,
observationSourceConceptId,
unitSourceValue,
diff --git a/src/main/java/com/phenoml/api/resources/fhir2omop/types/ProcedureOccurrenceRow.java b/src/main/java/com/phenoml/api/resources/fhir2omop/types/ProcedureOccurrenceRow.java
index 0631b91..48b7924 100644
--- a/src/main/java/com/phenoml/api/resources/fhir2omop/types/ProcedureOccurrenceRow.java
+++ b/src/main/java/com/phenoml/api/resources/fhir2omop/types/ProcedureOccurrenceRow.java
@@ -32,6 +32,8 @@ public final class ProcedureOccurrenceRow {
private final Optional procedureTypeConceptId;
+ private final Optional visitOccurrenceId;
+
private final Optional procedureSourceValue;
private final Optional procedureSourceConceptId;
@@ -45,6 +47,7 @@ private ProcedureOccurrenceRow(
Optional procedureDate,
Optional procedureDatetime,
Optional procedureTypeConceptId,
+ Optional visitOccurrenceId,
Optional procedureSourceValue,
Optional procedureSourceConceptId,
Map additionalProperties) {
@@ -54,6 +57,7 @@ private ProcedureOccurrenceRow(
this.procedureDate = procedureDate;
this.procedureDatetime = procedureDatetime;
this.procedureTypeConceptId = procedureTypeConceptId;
+ this.visitOccurrenceId = visitOccurrenceId;
this.procedureSourceValue = procedureSourceValue;
this.procedureSourceConceptId = procedureSourceConceptId;
this.additionalProperties = additionalProperties;
@@ -89,6 +93,11 @@ public Optional getProcedureTypeConceptId() {
return procedureTypeConceptId;
}
+ @JsonProperty("visit_occurrence_id")
+ public Optional getVisitOccurrenceId() {
+ return visitOccurrenceId;
+ }
+
@JsonProperty("procedure_source_value")
public Optional getProcedureSourceValue() {
return procedureSourceValue;
@@ -117,6 +126,7 @@ private boolean equalTo(ProcedureOccurrenceRow other) {
&& procedureDate.equals(other.procedureDate)
&& procedureDatetime.equals(other.procedureDatetime)
&& procedureTypeConceptId.equals(other.procedureTypeConceptId)
+ && visitOccurrenceId.equals(other.visitOccurrenceId)
&& procedureSourceValue.equals(other.procedureSourceValue)
&& procedureSourceConceptId.equals(other.procedureSourceConceptId);
}
@@ -130,6 +140,7 @@ public int hashCode() {
this.procedureDate,
this.procedureDatetime,
this.procedureTypeConceptId,
+ this.visitOccurrenceId,
this.procedureSourceValue,
this.procedureSourceConceptId);
}
@@ -157,6 +168,8 @@ public static final class Builder {
private Optional procedureTypeConceptId = Optional.empty();
+ private Optional visitOccurrenceId = Optional.empty();
+
private Optional procedureSourceValue = Optional.empty();
private Optional procedureSourceConceptId = Optional.empty();
@@ -173,6 +186,7 @@ public Builder from(ProcedureOccurrenceRow other) {
procedureDate(other.getProcedureDate());
procedureDatetime(other.getProcedureDatetime());
procedureTypeConceptId(other.getProcedureTypeConceptId());
+ visitOccurrenceId(other.getVisitOccurrenceId());
procedureSourceValue(other.getProcedureSourceValue());
procedureSourceConceptId(other.getProcedureSourceConceptId());
return this;
@@ -244,6 +258,17 @@ public Builder procedureTypeConceptId(Long procedureTypeConceptId) {
return this;
}
+ @JsonSetter(value = "visit_occurrence_id", nulls = Nulls.SKIP)
+ public Builder visitOccurrenceId(Optional visitOccurrenceId) {
+ this.visitOccurrenceId = visitOccurrenceId;
+ return this;
+ }
+
+ public Builder visitOccurrenceId(Long visitOccurrenceId) {
+ this.visitOccurrenceId = Optional.ofNullable(visitOccurrenceId);
+ return this;
+ }
+
@JsonSetter(value = "procedure_source_value", nulls = Nulls.SKIP)
public Builder procedureSourceValue(Optional procedureSourceValue) {
this.procedureSourceValue = procedureSourceValue;
@@ -274,6 +299,7 @@ public ProcedureOccurrenceRow build() {
procedureDate,
procedureDatetime,
procedureTypeConceptId,
+ visitOccurrenceId,
procedureSourceValue,
procedureSourceConceptId,
additionalProperties);
diff --git a/src/main/java/com/phenoml/api/resources/fhir2omop/types/Summary.java b/src/main/java/com/phenoml/api/resources/fhir2omop/types/Summary.java
index c67e947..5f018ef 100644
--- a/src/main/java/com/phenoml/api/resources/fhir2omop/types/Summary.java
+++ b/src/main/java/com/phenoml/api/resources/fhir2omop/types/Summary.java
@@ -44,7 +44,7 @@ private Summary(
}
/**
- * @return Codings already a standard OMOP concept.
+ * @return Coded concepts already a standard OMOP concept (ALREADY_STANDARD).
*/
@JsonProperty("codes_already_standard")
public Optional getCodesAlreadyStandard() {
@@ -52,7 +52,7 @@ public Optional getCodesAlreadyStandard() {
}
/**
- * @return Codings mapped or suggested to a standard concept (MAPPED or UNCHECKED).
+ * @return Coded concepts mapped or suggested to a standard concept (MAPPED or UNCHECKED).
*/
@JsonProperty("codes_normalized")
public Optional getCodesNormalized() {
@@ -60,7 +60,7 @@ public Optional getCodesNormalized() {
}
/**
- * @return Codings with no standard concept found.
+ * @return Coded concepts with no standard concept found (UNMAPPED).
*/
@JsonProperty("codes_unmapped")
public Optional getCodesUnmapped() {
@@ -131,7 +131,7 @@ public Builder from(Summary other) {
}
/**
- * Codings already a standard OMOP concept.
+ * Coded concepts already a standard OMOP concept (ALREADY_STANDARD).
*/
@JsonSetter(value = "codes_already_standard", nulls = Nulls.SKIP)
public Builder codesAlreadyStandard(Optional codesAlreadyStandard) {
@@ -145,7 +145,7 @@ public Builder codesAlreadyStandard(Integer codesAlreadyStandard) {
}
/**
- * Codings mapped or suggested to a standard concept (MAPPED or UNCHECKED).
+ * Coded concepts mapped or suggested to a standard concept (MAPPED or UNCHECKED).
*/
@JsonSetter(value = "codes_normalized", nulls = Nulls.SKIP)
public Builder codesNormalized(Optional codesNormalized) {
@@ -159,7 +159,7 @@ public Builder codesNormalized(Integer codesNormalized) {
}
/**
- * Codings with no standard concept found.
+ * Coded concepts with no standard concept found (UNMAPPED).
*/
@JsonSetter(value = "codes_unmapped", nulls = Nulls.SKIP)
public Builder codesUnmapped(Optional codesUnmapped) {
diff --git a/src/main/resources/openapi/openapi.json b/src/main/resources/openapi/openapi.json
index 3cb0654..3924b6b 100644
--- a/src/main/resources/openapi/openapi.json
+++ b/src/main/resources/openapi/openapi.json
@@ -2,7 +2,7 @@
"openapi": "3.0.3",
"info": {
"title": "Phenoml API",
- "version": "5084e3096e5bd89bf2e86ea44d96e3407f6f5c6b"
+ "version": "788cec0a9a7651caf2b106634631d487dfa16704"
},
"x-services": [
{
@@ -3021,7 +3021,7 @@
"post": {
"operationId": "fhir2omop_create",
"summary": "Map FHIR resources to OMOP CDM v5.4",
- "description": "Maps a FHIR R4 resource or Bundle into OMOP Common Data Model v5.4 rows\n(person, visit_occurrence, condition_occurrence, drug_exposure,\nprocedure_occurrence, measurement, observation).\n\nEach resource's primary clinical coding is resolved to a standard OMOP\n`concept_id`. Alongside the OMOP rows grouped by table (`tables`), the\nresponse carries `mappings` (how each source coding resolved, linked back\nto the row it produced), `dropped` (resources that could not be shaped\ninto a row), `vocab_version` (the OMOP vocabulary release codes were\nresolved against), and a small `summary` of the resolution outcomes.\n\nA `concept_id` of `0` means \"no matching standard concept\" (OMOP\nsemantics) and is reported, not omitted \u2014 a coding with no match is\n`UNMAPPED`. Only the primary clinical coding is resolved;\n`gender`/`race`/`ethnicity`/`visit`/`value`/`unit` `concept_id`s are\nalways `0`. Each `*_source_value` carries the verbatim FHIR coding\n(`system#code`), and `*_type_concept_id` is set to `32817` (EHR).\n\nMedication codes are resolved whether they appear inline\n(`medicationCodeableConcept`) or via a `medicationReference` to a contained,\nrelative (`Type/id`), or bundle-entry (`urn:uuid`) `Medication` resource.\nResources that cannot be shaped into a row \u2014 a medication with no usable\ncode, resolvable reference, or display, or any clinical resource whose\nsubject/patient reference cannot be tied to a person \u2014 are reported under\n`dropped` rather than emitted as blank rows. The\nbundle must contain at least one Patient resource.\n",
+ "description": "Maps a FHIR R4 resource or Bundle into OMOP Common Data Model v5.4 rows\n(person, visit_occurrence, condition_occurrence, drug_exposure,\nprocedure_occurrence, measurement, observation).\n\nEach resource's primary clinical coding is resolved to a standard OMOP\n`concept_id`. Alongside the OMOP rows grouped by table (`tables`), the\nresponse carries `mappings` (how each source coding resolved, linked back\nto the row it produced), `dropped` (resources that could not be shaped\ninto a row), `vocab_version` (the OMOP vocabulary release codes were\nresolved against), and a small `summary` of the resolution outcomes.\n\nA `concept_id` of `0` is reported, not omitted (OMOP \"no matching\nconcept\" semantics): it covers both a coding with no standard match\n(`UNMAPPED`) and an unverified suggestion for a text-only resource\n(`UNCHECKED`). Only the primary clinical coding is resolved, so\n`gender`/`race`/`ethnicity`/`visit`/`value`/`unit` `concept_id`s are\nalways `0`; the one populated non-resolved concept is measurement\n`operator_concept_id`, set from a value comparator (`<`, `<=`, `>`, `>=`)\nrather than the resolver. Each `*_source_value` carries the verbatim FHIR\ncoding (`system#code`), and `*_type_concept_id` is set to `32817` (EHR).\n\nMedication codes are resolved whether they appear inline\n(`medicationCodeableConcept`) or via a `medicationReference` to a contained,\nrelative (`Type/id`), or bundle-entry (`urn:uuid`) `Medication` resource.\nResources that cannot be shaped into a row \u2014 a medication with no usable\ncode, resolvable reference, or display, or any clinical resource whose\nsubject/patient reference cannot be tied to a person \u2014 are reported under\n`dropped` rather than emitted as blank rows. The\nbundle must contain at least one Patient resource.\n",
"requestBody": {
"required": true,
"content": {
@@ -3113,7 +3113,7 @@
"examples": {
"mapping_result": {
"summary": "Mapping result",
- "description": "The example bundle mapped to OMOP. Both source codes are already\nstandard, so each clinical row carries its own OMOP `concept_id`\nwith `ALREADY_STANDARD` status. `target_code` is omitted for a\nresolved concept \u2014 it is identified by `target_vocabulary` and\n`target_name` (and the row's `*_concept_id`). Illustrative\n`concept_id` values.\n",
+ "description": "The example bundle mapped to OMOP. Both source codes are already\nstandard, so each clinical row carries its own OMOP `concept_id`\nwith `ALREADY_STANDARD` status and a `target_code` equal to the\nsource code. Illustrative `concept_id` values.\n",
"value": {
"success": true,
"message": "FHIR resources mapped to OMOP CDM v5.4",
@@ -3167,6 +3167,7 @@
"source_code": "44054006",
"source_name": "Type 2 diabetes mellitus",
"target_vocabulary": "SNOMED",
+ "target_code": "44054006",
"target_name": "Type 2 diabetes mellitus",
"mapping_status": "ALREADY_STANDARD"
},
@@ -3179,6 +3180,7 @@
"source_code": "860975",
"source_name": "metformin hydrochloride 500 MG",
"target_vocabulary": "RXNORM",
+ "target_code": "860975",
"target_name": "metformin hydrochloride 500 MG",
"mapping_status": "ALREADY_STANDARD"
}
@@ -8738,6 +8740,10 @@
"type": "integer",
"format": "int64"
},
+ "visit_occurrence_id": {
+ "type": "integer",
+ "format": "int64"
+ },
"condition_source_value": {
"type": "string"
},
@@ -8784,6 +8790,10 @@
"sig": {
"type": "string"
},
+ "visit_occurrence_id": {
+ "type": "integer",
+ "format": "int64"
+ },
"drug_source_value": {
"type": "string"
},
@@ -8818,6 +8828,10 @@
"type": "integer",
"format": "int64"
},
+ "visit_occurrence_id": {
+ "type": "integer",
+ "format": "int64"
+ },
"procedure_source_value": {
"type": "string"
},
@@ -8856,6 +8870,11 @@
"type": "number",
"format": "double"
},
+ "operator_concept_id": {
+ "type": "integer",
+ "format": "int64",
+ "description": "OMOP \"Meas Value Operator\" standard concept qualifying value_as_number (<, <=, >, >=), parsed from a numeric-string value or a FHIR valueQuantity.comparator. 0 when no operator (a bare number)."
+ },
"value_as_concept_id": {
"type": "integer",
"format": "int64"
@@ -8872,6 +8891,10 @@
"type": "number",
"format": "double"
},
+ "visit_occurrence_id": {
+ "type": "integer",
+ "format": "int64"
+ },
"measurement_source_value": {
"type": "string"
},
@@ -8927,6 +8950,10 @@
"type": "integer",
"format": "int64"
},
+ "visit_occurrence_id": {
+ "type": "integer",
+ "format": "int64"
+ },
"observation_source_value": {
"type": "string"
},
@@ -8974,7 +9001,7 @@
},
"target_code": {
"type": "string",
- "description": "The standard concept's code, when present. Populated only for an\n`UNCHECKED` suggestion (where the API normalized a text-only resource\nto a suggested code); omitted for codings resolved through concept\nresolution (`ALREADY_STANDARD` / `MAPPED` / `UNMAPPED`), which are\nidentified by `target_vocabulary`, `target_name`, and the row's\n`*_concept_id` rather than by code.\n"
+ "description": "The standard concept's own code: the source code itself for an\nALREADY_STANDARD row, the standard concept's code for a MAPPED row,\nor the suggested code for an UNCHECKED row. Omitted for UNMAPPED\nrows.\n"
},
"target_name": {
"type": "string"
@@ -8990,19 +9017,19 @@
},
"fhir2omop_Summary": {
"type": "object",
- "description": "The request's data-quality headline: how the coded concepts split across\nresolution outcomes, and the share that was not already in a target\nstandard vocabulary.\n",
+ "description": "The request's data-quality headline: how the coded concepts split across\nresolution outcomes, and the share that was not already in a target\nstandard vocabulary. Each coded resource is counted once (per resolved\nconcept), even when it carried several codings \u2014 unlike `mappings`, which\nhas one entry per coding.\n",
"properties": {
"codes_already_standard": {
"type": "integer",
- "description": "Codings already a standard OMOP concept."
+ "description": "Coded concepts already a standard OMOP concept (ALREADY_STANDARD)."
},
"codes_normalized": {
"type": "integer",
- "description": "Codings mapped or suggested to a standard concept (MAPPED or UNCHECKED)."
+ "description": "Coded concepts mapped or suggested to a standard concept (MAPPED or UNCHECKED)."
},
"codes_unmapped": {
"type": "integer",
- "description": "Codings with no standard concept found."
+ "description": "Coded concepts with no standard concept found (UNMAPPED)."
},
"off_vocab_rate": {
"type": "number",
diff --git a/src/test/resources/wire-tests/Fhir2OmopWireTest_testCreate_response.json b/src/test/resources/wire-tests/Fhir2OmopWireTest_testCreate_response.json
index e2e5afd..5498547 100644
--- a/src/test/resources/wire-tests/Fhir2OmopWireTest_testCreate_response.json
+++ b/src/test/resources/wire-tests/Fhir2OmopWireTest_testCreate_response.json
@@ -63,7 +63,7 @@
"source_code": "44054006",
"source_name": "Type 2 diabetes mellitus",
"target_vocabulary": "SNOMED",
- "target_code": "target_code",
+ "target_code": "44054006",
"target_name": "Type 2 diabetes mellitus",
"mapping_status": "ALREADY_STANDARD",
"note": "note"
@@ -77,7 +77,7 @@
"source_code": "860975",
"source_name": "metformin hydrochloride 500 MG",
"target_vocabulary": "RXNORM",
- "target_code": "target_code",
+ "target_code": "860975",
"target_name": "metformin hydrochloride 500 MG",
"mapping_status": "ALREADY_STANDARD",
"note": "note"