Skip to content

Commit

Permalink
Parse domain specific types, add conversion config to archie-utils
Browse files Browse the repository at this point in the history
  • Loading branch information
pieterbos committed Jan 4, 2021
1 parent efa90f9 commit be673b1
Show file tree
Hide file tree
Showing 17 changed files with 277 additions and 140 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,8 @@ The following features are experimental. This means its working or API will like
Starting from version 0.7, Archie can import ADL 1.4 files, and convert them to ADL 2. To do so, do the following:

```java
ADL14ConversionConfiguration conversionConfiguration = new ADL14ConversionConfiguration();
//this is the default configuration. You can implement your own if you want to
ADL14ConversionConfiguration conversionConfiguration = OpenEHRADL14ConversionConfiguration.getConfig();
ADL14Converter converter = new ADL14Converter(BuiltinReferenceModels.getMetaModels(), conversionConfiguration);

List<Archetype> archetypes = new ArrayList<>();
Expand Down Expand Up @@ -498,7 +499,7 @@ The conversion log can be serialized to a file for storage using Jackson, so it

### Conversion Configuration

You may have noticed an instance of `ADL14ConversionConfiguration` in the previous example. In this configuration the mapping from term codes as used in ADL 1.4 to term URIs as used in ADL 2 can be specified. See the `ConversionConfigForTest.java` file for an example on how this works, and how this can be serialized to a file, and the file `/tools/src/test/java/com/nedap/archie/adl14/configuration.json` for an example of a simple serialized configuration that contains sane defaults for snomed, loinc and openehr URIs.
You may have noticed an instance of `ADL14ConversionConfiguration` in the previous example. In this configuration the mapping from term codes as used in ADL 1.4 to term URIs as used in ADL 2 can be specified. The archie-utils package provides a default configuration in the class `OpenEHRADL14ConversionConfiguration`. It is possible to supply your own, see the default implementation on how this works, and how this can be serialized to a file, and the file `/archie-utils/src/main/resources/adl14conversionconfiguration.json` for an example of a simple serialized configuration that contains sane defaults for snomed, loinc and openehr URIs.

If you leave the configuration empty, the converter will fall back to a default URI conversion.

Expand Down

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion archie-utils/build.gradle
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
description = "Utils for the Archie OpenEHR library"
description = "OpenEHR-RM specific utils for the Archie OpenEHR library"

dependencies {
compile project(':base')
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
package com.nedap.archie.adl14;


import com.nedap.archie.json.JacksonUtil;

import java.io.IOException;
import java.io.InputStream;

public class ConversionConfigForTest {

public class OpenEHRADL14ConversionConfiguration {

public static ADL14ConversionConfiguration getConfig() throws IOException {

try(InputStream stream = ConversionConfigForTest.class.getResourceAsStream("configuration.json")) {
try(InputStream stream = OpenEHRADL14ConversionConfiguration.class.getResourceAsStream("/adl14conversionconfiguration.json")) {
return JacksonUtil.getObjectMapper().readValue(stream, ADL14ConversionConfiguration.class);
}

}

}
25 changes: 25 additions & 0 deletions archie-utils/src/main/resources/adl14conversionconfiguration.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"terminology_conversion_templates": [
{
"terminology_id": "snomedct",
"template": "http://snomed.info/id/$code_string"
},
{
"terminology_id": "snomed-ct",
"template": "http://snomed.info/id/$code_string"
},
{
"terminology_id": "snomed",
"template": "http://snomed.info/id/$code_string"
},
{
"terminology_id": "openehr",
"template": "http://openehr.org/id/$code_string"
},
{
"terminology_id": "loinc",
"template": "http://loinc.org/id/$code_string"
}

]
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
import com.nedap.archie.base.Cardinality;
import com.nedap.archie.base.Interval;
import com.nedap.archie.base.MultiplicityInterval;
import com.nedap.archie.base.terminology.TerminologyCode;

public class IntervalConverter {
public class BaseTypesConverter {

public static Cardinality convertCardinality(CARDINALITY cardinality14) {
if(cardinality14 == null) {
Expand Down Expand Up @@ -52,4 +53,11 @@ public static com.nedap.archie.base.Interval<Double> convertInterval(IntervalOfR
range.isUpperIncluded() == null ? true : range.isUpperIncluded());
}

public static TerminologyCode convert(CODEPHRASE definingCode) {
if(definingCode == null) {
return null;
}
return TerminologyCode.createFromString(definingCode.getTerminologyId().getValue(), null, definingCode.getCodeString());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
import com.nedap.archie.aom.Template;
import com.nedap.archie.aom.TemplateOverlay;

import static com.nedap.archie.opt14.IntervalConverter.convertCardinality;
import static com.nedap.archie.opt14.IntervalConverter.convertMultiplicity;
import static com.nedap.archie.opt14.BaseTypesConverter.convertCardinality;
import static com.nedap.archie.opt14.BaseTypesConverter.convertMultiplicity;
import static com.nedap.archie.opt14.PrimitiveConverter.convertPrimitive;

public class DefinitionConverter {
Expand All @@ -30,7 +30,7 @@ private CComplexObject convert(CCOMPLEXOBJECT cComplexObject14) {
CComplexObject cComplexObject = new CComplexObject();
cComplexObject.setNodeId(cComplexObject14.getNodeId());
cComplexObject.setRmTypeName(cComplexObject14.getRmTypeName());
cComplexObject.setOccurrences(IntervalConverter.convertMultiplicity(cComplexObject14.getOccurrences()));
cComplexObject.setOccurrences(BaseTypesConverter.convertMultiplicity(cComplexObject14.getOccurrences()));

for (CATTRIBUTE attribute14 : cComplexObject14.getAttributes()) {
cComplexObject.addAttribute(convert(attribute14));
Expand Down Expand Up @@ -81,7 +81,7 @@ private CObject convertSlot(ARCHETYPESLOT cobject14) {
archetypeSlot.setNodeId(cobject14.getNodeId());
archetypeSlot.setRmTypeName(cobject14.getRmTypeName());

archetypeSlot.setOccurrences(IntervalConverter.convertMultiplicity(cobject14.getOccurrences()));
archetypeSlot.setOccurrences(BaseTypesConverter.convertMultiplicity(cobject14.getOccurrences()));
//TODO: assertions for include/exclude, should be straightforward
return archetypeSlot;
}
Expand All @@ -99,7 +99,7 @@ private CObject convertRoot(CARCHETYPEROOT cRoot14) {
CArchetypeRoot root = new CArchetypeRoot();
root.setArchetypeRef(overlay.getArchetypeId().getFullId());
root.setNodeId(cRoot14.getNodeId());
root.setOccurrences(IntervalConverter.convertMultiplicity(cRoot14.getOccurrences()));
root.setOccurrences(BaseTypesConverter.convertMultiplicity(cRoot14.getOccurrences()));
root.setRmTypeName(cRoot14.getRmTypeName());
return root;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,18 @@ public static void convert(Template template, OPERATIONALTEMPLATE opt14) {
author.put(item.getId(), item.getValue());
}
}
if(description14.getOtherDetails() != null) {
for(StringDictionaryItem item:description14.getOtherDetails()) {
description.getOtherDetails().put(item.getId(), item.getValue());
}
}

description.setOtherContributors(description14.getOtherContributors());

description.setOriginalAuthor(author);
template.setDescription(description);

template.setOriginalLanguage(
TerminologyCode.createFromString(
opt14.getLanguage().getTerminologyId().getValue(),
null,
opt14.getLanguage().getCodeString()));
template.setOriginalLanguage(BaseTypesConverter.convert(opt14.getLanguage()));
//TODO: implement me further
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,82 @@
package com.nedap.archie.opt14;

import com.nedap.archie.adl14.aom14.CDVOrdinal;
import com.nedap.archie.adl14.aom14.CDVOrdinalItem;
import com.nedap.archie.adl14.aom14.CDVQuantity;

import com.nedap.archie.adl14.aom14.CDVQuantityAssumedValue;
import com.nedap.archie.adl14.aom14.CDVQuantityItem;
import com.nedap.archie.adl14.treewalkers.Adl14CComplexObjectParser;
import com.nedap.archie.aom.CObject;
import com.nedap.archie.base.terminology.TerminologyCode;

import java.util.LinkedHashMap;
import java.util.Map;

import static com.nedap.archie.opt14.BaseTypesConverter.convert;

public class DomainTypeConverter {
public static CObject convertDomainType(CDOMAINTYPE cobject14) {
if(cobject14 instanceof CDVORDINAL) {
return convertCDVOrdinal((CDVORDINAL) cobject14);
} else if (cobject14 instanceof CDVQUANTITY) {
return convertCDVQuantity((CDVQUANTITY) cobject14);
} else if (cobject14 instanceof CDVSTATE) {

} else if (cobject14 instanceof CCODEPHRASE) {

}
return null;
}

private static CObject convertCDVOrdinal(CDVORDINAL ordinal14) {
CDVOrdinal ordinal = new CDVOrdinal();
Map<String, CDVOrdinalItem> items = new LinkedHashMap<>();
if(ordinal14.getList() != null) {
Integer i = 0;
for(DVORDINAL dvordinal14:ordinal14.getList()) {
CDVOrdinalItem item = new CDVOrdinalItem();
item.setValue(dvordinal14.getValue());
if(dvordinal14.getSymbol() != null) {
item.setSymbol(convert(dvordinal14.getSymbol().getDefiningCode()));
}
items.put(i.toString(), item);
i++;
}
}
//TODO: no assumed value in our own model, but there is in the OPT form.

return Adl14CComplexObjectParser.convertCDVOrdinal(ordinal);
}

private static CObject convertCDVQuantity(CDVQUANTITY cobject14) {
CDVQUANTITY quantity14 = cobject14;
CDVQuantity quantity = new CDVQuantity();
Map<String, CDVQuantityItem> items = new LinkedHashMap<>();

if(quantity14.getList() != null) {
Integer i = 0;
for(CQUANTITYITEM item14:quantity14.getList()) {
CDVQuantityItem item = new CDVQuantityItem();
item.setMagnitude(BaseTypesConverter.convertInterval(item14.getMagnitude()));
item.setPrecision(BaseTypesConverter.convertInterval(item14.getPrecision()));
item.setUnits(item14.getUnits());
items.put(i.toString(), item);
i++;
}
}
quantity.setList(items);

quantity.setProperty(convert(quantity14.getProperty()));

DVQUANTITY assumedValue14 = quantity14.getAssumedValue();
if(assumedValue14 != null) {
CDVQuantityAssumedValue assumedValue = new CDVQuantityAssumedValue();
assumedValue.setMagnitude(assumedValue14.getMagnitude());
assumedValue.setPrecision(assumedValue14.getPrecision() == null ? null : assumedValue14.getPrecision().longValue());
assumedValue.setUnits(assumedValue14.getUnits());
quantity.setAssumedValue(assumedValue);
}
return Adl14CComplexObjectParser.convertCDvQuantity(quantity);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ public Template convert(OPERATIONALTEMPLATE opt14) {
Template template = new Template();
template.setArchetypeId(new ArchetypeHRID("openEHR-EHR-" + opt14.getDefinition().getRmTypeName() + "." + opt14.getTemplateId().getValue() + "v1.0.0"));
template.setParentArchetypeId(opt14.getDefinition().getArchetypeId().getValue());
if(opt14.getUid() != null) {
template.setUid(opt14.getUid().getValue());
}
DescriptionConverter.convert(template, opt14);

new DefinitionConverter().convert(template, opt14);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import com.nedap.archie.aom.primitives.CReal;
import com.nedap.archie.aom.primitives.CString;

import static com.nedap.archie.opt14.IntervalConverter.convertInterval;
import static com.nedap.archie.opt14.BaseTypesConverter.convertInterval;

public class PrimitiveConverter {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public static ArchetypeTerminology createTerminology(OPERATIONALTEMPLATE opt14,
ArchetypeTerm term = new ArchetypeTerm();
term.setCode(term14.getCode());
for(StringDictionaryItem item:term14.getItems()) {
term.put(item.getId(), item.getId());
term.put(item.getId(), item.getValue());
}
terms.put(term14.getCode(), term);
}
Expand Down
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public class ADL14TerminologySupportTest {

@Test
public void terminologyBindingsConverted() throws IOException {
ADL14ConversionConfiguration conversionConfiguration = ConversionConfigForTest.getConfig();
ADL14ConversionConfiguration conversionConfiguration = OpenEHRADL14ConversionConfiguration.getConfig();
ADL14Converter converter = new ADL14Converter(BuiltinReferenceModels.getMetaModels(), conversionConfiguration);
String createdAtCode = null;
//apply the first conversion and store the log. It has created an at code to bind to [openehr::124], used in a DV_QUANTITY.property
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public class ArchetypeSlotConversionTest {

@Test
public void testSlotConversion() throws Exception {
ADL14ConversionConfiguration conversionConfiguration = ConversionConfigForTest.getConfig();
ADL14ConversionConfiguration conversionConfiguration = OpenEHRADL14ConversionConfiguration.getConfig();
ADL14Converter converter = new ADL14Converter(BuiltinReferenceModels.getMetaModels(), conversionConfiguration);
ADL2ConversionRunLog log = null;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public class LargeSetOfADL14sTest {

@Before
public void setup() throws Exception {
conversionConfiguration = ConversionConfigForTest.getConfig();
conversionConfiguration = OpenEHRADL14ConversionConfiguration.getConfig();
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public class PreviousLogConversionTest {
@Test
public void applyConsistentConversion() throws Exception {

ADL14ConversionConfiguration conversionConfiguration = ConversionConfigForTest.getConfig();
ADL14ConversionConfiguration conversionConfiguration = OpenEHRADL14ConversionConfiguration.getConfig();
ADL14Converter converter = new ADL14Converter(BuiltinReferenceModels.getMetaModels(), conversionConfiguration);
ADL2ConversionRunLog log = null;

Expand Down Expand Up @@ -51,7 +51,7 @@ public void applyConsistentConversion() throws Exception {

@Test
public void testValueSet() throws Exception {
ADL14ConversionConfiguration conversionConfiguration = ConversionConfigForTest.getConfig();
ADL14ConversionConfiguration conversionConfiguration = OpenEHRADL14ConversionConfiguration.getConfig();
ADL14Converter converter = new ADL14Converter(BuiltinReferenceModels.getMetaModels(), conversionConfiguration);
ADL2ConversionRunLog log = null;

Expand Down Expand Up @@ -88,7 +88,7 @@ public void testValueSet() throws Exception {

@Test
public void unusedValuesAreRemoved() throws Exception {
ADL14ConversionConfiguration conversionConfiguration = ConversionConfigForTest.getConfig();
ADL14ConversionConfiguration conversionConfiguration = OpenEHRADL14ConversionConfiguration.getConfig();
ADL14Converter converter = new ADL14Converter(BuiltinReferenceModels.getMetaModels(), conversionConfiguration);
ADL2ConversionRunLog log = null;
String createdAtCode = null;
Expand Down

0 comments on commit be673b1

Please sign in to comment.