Skip to content

Commit

Permalink
Fixes exception while unmarshalling node with children DV_CODED_TEXT …
Browse files Browse the repository at this point in the history
…and DV_TEXT
  • Loading branch information
subigre committed Jan 18, 2022
1 parent 4e97efa commit 174aa1a
Show file tree
Hide file tree
Showing 13 changed files with 44,124 additions and 136 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,13 @@

package org.ehrbase.serialisation.flatencoding.std.marshal;

import static org.ehrbase.serialisation.flatencoding.std.umarshal.StdToCompositionWalker.handleDVTextInternal;

import com.nedap.archie.rm.RMObject;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.ehrbase.serialisation.flatencoding.std.marshal.config.DefaultStdConfig;
import org.ehrbase.serialisation.flatencoding.std.marshal.config.StdConfig;
import org.ehrbase.serialisation.flatencoding.std.marshal.postprocessor.MarshalPostprocessor;
Expand All @@ -28,14 +34,7 @@
import org.ehrbase.serialisation.walker.FromCompositionWalker;
import org.ehrbase.util.reflection.ReflectionHelper;
import org.ehrbase.webtemplate.model.WebTemplateNode;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static org.ehrbase.serialisation.flatencoding.std.umarshal.StdToCompositionWalker.handleDVTextInternal;
import org.ehrbase.webtemplate.util.WebTemplateUtils;

public class StdFromCompositionWalker extends FromCompositionWalker<Map<String, Object>> {

Expand Down Expand Up @@ -112,24 +111,9 @@ public static <T extends RMObject> List<MarshalPostprocessor<T>> findPostprocess

@Override
protected void handleDVText(WebTemplateNode currentNode) {
if (currentNode.getRmType().equals("ELEMENT")) {
List<WebTemplateNode> trueChildren =
currentNode.getChildren().stream()
.filter(
n ->
!List.of("null_flavour", "feeder_audit").contains(n.getName())
|| !n.isNullable())
.collect(Collectors.toList());
if (trueChildren.stream()
.map(WebTemplateNode::getId)
.collect(Collectors.toList())
.containsAll(List.of("coded_text_value", "text_value"))
&& currentNode.getChoicesInChildren().size() > 0
&& trueChildren.size() == 2) {
handleDVTextInternal(currentNode);
} else {
super.handleDVText(currentNode);
}
if (currentNode.getRmType().equals("ELEMENT")
&& WebTemplateUtils.hasDvCodedTextAndDvText(currentNode)) {
handleDVTextInternal(currentNode);
} else {
super.handleDVText(currentNode);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@

package org.ehrbase.serialisation.flatencoding.std.umarshal;

import static org.ehrbase.util.rmconstants.RmConstants.DV_CODED_TEXT;
import static org.ehrbase.util.rmconstants.RmConstants.DV_TEXT;
import static org.ehrbase.util.rmconstants.RmConstants.ELEMENT;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.nedap.archie.rm.RMObject;
Expand All @@ -30,6 +34,15 @@
import com.nedap.archie.rm.datavalues.DvText;
import com.nedap.archie.rm.generic.PartyRelated;
import com.nedap.archie.rm.support.identification.TerminologyId;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
Expand All @@ -50,11 +63,7 @@
import org.ehrbase.webtemplate.model.WebTemplateInput;
import org.ehrbase.webtemplate.model.WebTemplateNode;
import org.ehrbase.webtemplate.path.flat.FlatPathDto;

import java.util.*;
import java.util.stream.Collectors;

import static org.ehrbase.util.rmconstants.RmConstants.*;
import org.ehrbase.webtemplate.util.WebTemplateUtils;

public class StdToCompositionWalker extends ToCompositionWalker<Map<FlatPathDto, String>> {

Expand Down Expand Up @@ -144,12 +153,12 @@ protected ImmutablePair<Map<FlatPathDto, String>, RMObject> extractPair(
Integer i) {

if (
// Nodes with children need to be put on the stack even if there are skip since the might have
// children. If there are empty there will be removed in ToCompositionWalker::normalise
(CollectionUtils.isEmpty(childNode.getChildren())
// Nodes with children need to be put on the stack even if there are skip since the might have
// children. If there are empty there will be removed in ToCompositionWalker::normalise
(CollectionUtils.isEmpty(childNode.getChildren())
&& context.getFlatHelper().skip(childNode, currentNode))
// NonMandatoryRmAttribute are handled in the UnmarshalPostprocessor
|| (currentNode != null
// NonMandatoryRmAttribute are handled in the UnmarshalPostprocessor
|| (currentNode != null
&& context.getFlatHelper().isNonMandatoryRmAttribute(childNode, currentNode))) {
return new ImmutablePair<>(null, null);
}
Expand Down Expand Up @@ -208,7 +217,7 @@ protected void preHandle(Context<Map<FlatPathDto, String>> context) {

if (context.getRmObjectDeque().peek().getClass().isAssignableFrom(DvCodedText.class)
&& context.getObjectDeque().peek().keySet().stream()
.anyMatch(k -> "other".equals(k.getLast().getAttributeName()))) {
.anyMatch(k -> "other".equals(k.getLast().getAttributeName()))) {
replaceRmObject(context, new DvText());
}

Expand Down Expand Up @@ -285,8 +294,8 @@ private boolean isRaw(Context<Map<FlatPathDto, String>> context) {
return Objects.equals(current.getKey().getLast().getAttributeName(), "raw")
// last flat path segment matches node_id ( starting '_' marks optional flat path )
&& Objects.equals(
StringUtils.removeStart(context.getNodeDeque().peek().getId(false), "_"),
StringUtils.removeStart(current.getKey().getLast().getName(), "_"));
StringUtils.removeStart(context.getNodeDeque().peek().getId(false), "_"),
StringUtils.removeStart(current.getKey().getLast().getName(), "_"));
}

@Override
Expand All @@ -310,7 +319,8 @@ protected void postHandle(Context<Map<FlatPathDto, String>> context) {
if (context.getFlatHelper().skip(childNode, currentNode)) {

context.getNodeDeque().push(childNode);
context.getRmObjectDeque().push(new RMObject() {});
context.getRmObjectDeque().push(new RMObject() {
});

String path = context.getFlatHelper().buildNamePath(context, true);
Map<FlatPathDto, String> subValues =
Expand Down Expand Up @@ -385,54 +395,20 @@ public static <T extends RMObject> List<UnmarshalPostprocessor<T>> findUnmarshal

@Override
protected void handleDVText(WebTemplateNode currentNode) {
if (currentNode.getRmType().equals(ELEMENT)) {
List<WebTemplateNode> trueChildren =
currentNode.getChildren().stream()
.filter(n -> !"name".equals(n.getId()))
.filter(
n ->
!List.of("null_flavour", "feeder_audit").contains(n.getId())
|| !n.isNullable())
.collect(Collectors.toList());
if (trueChildren.stream()
.map(WebTemplateNode::getRmType)
.collect(Collectors.toList())
.containsAll(List.of(DV_TEXT, DV_CODED_TEXT))
&& currentNode.getChoicesInChildren().size() > 0
&& trueChildren.size() == 2) {
handleDVTextInternal(currentNode);
} else {
super.handleDVText(currentNode);
}
if (currentNode.getRmType().equals("ELEMENT")
&& WebTemplateUtils.hasDvCodedTextAndDvText(currentNode)) {
handleDVTextInternal(currentNode);
} else {
super.handleDVText(currentNode);
}
}

public static void handleDVTextInternal(WebTemplateNode node) {

if (node.getRmType().equals(ELEMENT)) {
List<WebTemplateNode> trueChildren =
node.getChildren().stream()
.filter(n -> !"name".equals(n.getId()))
.filter(
n ->
!List.of("null_flavour", "feeder_audit").contains(n.getId())
|| !n.isNullable())
.collect(Collectors.toList());
if (trueChildren.stream()
.map(WebTemplateNode::getId)
.collect(Collectors.toList())
.containsAll(List.of("coded_text_value", "text_value"))
&& node.getChoicesInChildren().size() > 0
&& trueChildren.size() == 2) {
WebTemplateNode merged = Filter.mergeDVText(node);

node.getChildren()
.removeIf(n -> List.of("coded_text_value", "text_value").contains(n.getId()));
node.getChildren().add(merged);
}
}
WebTemplateNode merged = Filter.mergeDVText(node);
node.getChildren()
.removeIf(
childNode -> List.of("coded_text_value", "text_value").contains(childNode.getId()));
node.getChildren().add(merged);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,63 @@ public void toFlatJsonAllTypes() throws IOException, XmlException {
});
}

@Test
public void toFlatJsonIps() throws Exception {
OPERATIONALTEMPLATE template =
TemplateDocument.Factory.parse(OperationalTemplateTestData.IPS.getStream())
.getTemplate();

Composition composition =
new CanonicalJson()
.unmarshal(
IOUtils.toString(
CompositionTestDataCanonicalJson.IPS.getStream(), StandardCharsets.UTF_8),
Composition.class);

FlatJsonMarshaller marshaller = new FlatJsonMarshaller();

String actual = marshaller.toFlatJson(composition, new OPTParser(template).parse());
assertThat(actual).isNotNull();

String expected =
IOUtils.toString(
CompositionTestDataSimSDTJson.IPS.getStream(), StandardCharsets.UTF_8);

List<String> errors = compere(actual, expected);


checkErrors(errors,
new String[] {
"Missing path: international_patient_summary/medication_summary/medication_statement/order_id:0|id, value: 9a0e5173-07c8-443d-b414-24432b9d95ca",
"Missing path: international_patient_summary/medical_devices/device_use_statement/device_details:0/medical_device/unique_device_identifier_udi|id, value: 73b166ae-1c28-4ce0-8c08-a9587d8fd95a",
"Missing path: international_patient_summary/medical_devices/device_use_statement/device_details:0/medical_device/other_identifier:0|id, value: 60287ff3-ec0f-4cd5-9000-2c05af2e6a84",
"Missing path: international_patient_summary/diagnostic_results/imaging_examination_result/examination_request_details:0/requester_order_identifier|id, value: 38a6687c-5136-4e75-9f1c-126e8f0e112b",
"Missing path: international_patient_summary/diagnostic_results/imaging_examination_result/examination_request_details:0/receiver_order_identifier|id, value: 9fc6db02-81de-4ec9-afe4-f365c42019e1",
"Missing path: international_patient_summary/diagnostic_results/imaging_examination_result/examination_request_details:0/report_identifier|id, value: a147525c-4763-4070-ba22-26e6b33348f4",
"Missing path: international_patient_summary/diagnostic_results/imaging_examination_result/examination_request_details:0/reported_image:0/image_identifier|id, value: 5462ef5c-2275-47c2-8fb5-f9f1d7a19613",
"Missing path: international_patient_summary/diagnostic_results/imaging_examination_result/examination_request_details:0/reported_image:0/dicom_series_identifier|id, value: 55dd86d7-52ff-4064-8dc7-f8d9b2bc22e7",
"Missing path: international_patient_summary/diagnostic_results/imaging_examination_result/examination_request_details:0/comparison_image:0/image_identifier|id, value: a6c20273-7b53-4c04-9b2c-2d4c218893b2",
"Missing path: international_patient_summary/diagnostic_results/imaging_examination_result/examination_request_details:0/comparison_image:0/dicom_series_identifier|id, value: 1ba8eff7-8f3f-4625-9432-05aa01726073",
"Missing path: international_patient_summary/vital_signs/pulse_oximetry/any_event:0/spo, value: 0.8920999999999999",
"Missing path: international_patient_summary/plan_of_care/care_plan/care_plan_id|id, value: 0942fb74-27f8-48c6-869e-10192740c371",
"Missing path: international_patient_summary/plan_of_care/service_request/current_activity:0/action_archetype_id, value: /.*/"
},
new String[] {
"Extra path: international_patient_summary/medication_summary/medication_statement/order_id:0, value: 9a0e5173-07c8-443d-b414-24432b9d95ca",
"Extra path: international_patient_summary/medical_devices/device_use_statement/device_details:0/medical_device/unique_device_identifier_udi, value: 73b166ae-1c28-4ce0-8c08-a9587d8fd95a",
"Extra path: international_patient_summary/medical_devices/device_use_statement/device_details:0/medical_device/other_identifier:0, value: 60287ff3-ec0f-4cd5-9000-2c05af2e6a84",
"Extra path: international_patient_summary/diagnostic_results/imaging_examination_result/examination_request_details:0/requester_order_identifier, value: 38a6687c-5136-4e75-9f1c-126e8f0e112b",
"Extra path: international_patient_summary/diagnostic_results/imaging_examination_result/examination_request_details:0/receiver_order_identifier, value: 9fc6db02-81de-4ec9-afe4-f365c42019e1",
"Extra path: international_patient_summary/diagnostic_results/imaging_examination_result/examination_request_details:0/report_identifier, value: a147525c-4763-4070-ba22-26e6b33348f4",
"Extra path: international_patient_summary/diagnostic_results/imaging_examination_result/examination_request_details:0/reported_image:0/image_identifier, value: 5462ef5c-2275-47c2-8fb5-f9f1d7a19613",
"Extra path: international_patient_summary/diagnostic_results/imaging_examination_result/examination_request_details:0/reported_image:0/dicom_series_identifier, value: 55dd86d7-52ff-4064-8dc7-f8d9b2bc22e7",
"Extra path: international_patient_summary/diagnostic_results/imaging_examination_result/examination_request_details:0/comparison_image:0/image_identifier, value: a6c20273-7b53-4c04-9b2c-2d4c218893b2",
"Extra path: international_patient_summary/diagnostic_results/imaging_examination_result/examination_request_details:0/comparison_image:0/dicom_series_identifier, value: 1ba8eff7-8f3f-4625-9432-05aa01726073",
"Extra path: international_patient_summary/vital_signs/pulse_oximetry/any_event:0/spo, value: 0.8921",
"Extra path: international_patient_summary/plan_of_care/care_plan/care_plan_id, value: 0942fb74-27f8-48c6-869e-10192740c371"
});
}

public void checkErrors(List<String> errors, String[] missing, String[] extra) {

SoftAssertions softAssertions = new SoftAssertions();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,4 +192,21 @@ public void unmarshallNestedComposition() throws Exception {

assertDoesNotThrow(() -> new Validator(optTemplate).check(composition));
}


@Test
public void unmarshallIpsComposition() throws Exception {
var optTemplate = TemplateDocument.Factory.parse(OperationalTemplateTestData.IPS.getStream())
.getTemplate();
var webTemplate = new OPTParser(optTemplate).parse();

var json = IOUtils.toString(CompositionTestDataSimSDTJson.IPS.getStream(),
StandardCharsets.UTF_8);

var composition = new FlatJsonUnmarshaller().unmarshal(json, webTemplate);

assertThat(composition).isNotNull();

assertDoesNotThrow(() -> new Validator(optTemplate).check(composition));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ public enum CompositionTestDataCanonicalJson {
MINIMAL_WITHOUT_OPTIONAL_ATTRIBUTE("dv multimedia without alternate_text", "minimal_without_optional_attribute.json"),
GECCO_PERSONENDATEN("GECCO_Personendaten", "gecco_personendaten.json"),
GECCO_LABORBEFUND("GECCO_Laborbefund", "gecco_laborbefund.json"),
PARTICIPATION_NO_CONTENT("to test various participation CR #710", "participation_no_content.json");
PARTICIPATION_NO_CONTENT("to test various participation CR #710", "participation_no_content.json"),
IPS("Internation Patient Summary", "ips_canonical.json");


private final String filename;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ public enum CompositionTestDataSimSDTJson {
MULTI_LIST("MULTI_LIST", "multi_list.json"),
NCD("NCD", "NCD.json"),
EREACT_COVID_MANAGEMENT("flat with action", "EREACT - Covid status monitoring - FLAT.json"),
NESTED("nested.en.v1", "nested.en.v1.json");
NESTED("nested.en.v1", "nested.en.v1.json"),
IPS("International Patient Summary", "ips_flat.json");

private final String filename;
private final String description;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,8 @@ public enum OperationalTemplateTestData {
MINIMAL_ACTION("Minimal Action 3", "minimal_action3.opt", "minimal_action_3.en.v1"),
NCD("ncd", "NCD.opt", "NCD"),
MULTIMEDIA_TEST("MultimediaTest", "multimedia_test.en.v1.opt", "multimedia_test.en.v1"),
NESTED("nested.en.v1", "nested.en.v1.opt", "nested.en.v1");
NESTED("nested.en.v1", "nested.en.v1.opt", "nested.en.v1"),
IPS("International Patient Summary", "ips.v0.opt", "International Patient Summary");

private final String filename;
private final String templateId;
Expand Down
Loading

0 comments on commit 174aa1a

Please sign in to comment.