From 4eabb595b1df99df7b59b8ac7e5198dc9af222ea Mon Sep 17 00:00:00 2001 From: "stefan.spiska" Date: Thu, 15 Aug 2024 16:57:43 +0200 Subject: [PATCH 01/26] positive test --- .../validation/CompositionValidatorTest.java | 16 + .../test/resources/composition/name-test.json | 297 ++++++ .../name-test.ehrbase.org.v0.opt | 890 ++++++++++++++++++ 3 files changed, 1203 insertions(+) create mode 100644 validation/src/test/resources/composition/name-test.json create mode 100644 validation/src/test/resources/operational_templates/name-test.ehrbase.org.v0.opt diff --git a/validation/src/test/java/org/ehrbase/openehr/sdk/validation/CompositionValidatorTest.java b/validation/src/test/java/org/ehrbase/openehr/sdk/validation/CompositionValidatorTest.java index d6c784f21..c7182f6aa 100644 --- a/validation/src/test/java/org/ehrbase/openehr/sdk/validation/CompositionValidatorTest.java +++ b/validation/src/test/java/org/ehrbase/openehr/sdk/validation/CompositionValidatorTest.java @@ -214,6 +214,16 @@ void validateAdverseReaction_BadCodedValue() throws Exception { result.forEach(System.out::println); } + @Test + void validateName() throws Exception { + var composition = getCompositionJson("name-test.json"); + var template = getOperationalTemplate("name-test.ehrbase.org.v0.opt"); + + var result = validator.validate(composition, template); + assertEquals(0, result.size()); + result.forEach(System.out::println); + } + @Test void compositionValidationCRSDK120() throws Exception { var template = getOperationalTemplate(OperationalTemplateTestData.BEFUND_DER_BLUTGASANALYSE); @@ -248,6 +258,12 @@ private Composition getComposition(String name) throws IOException, JAXBExceptio return (Composition) unmarshaller.unmarshal(new FileInputStream("./src/test/resources/composition/" + name)); } + private Composition getCompositionJson(String name) throws IOException { + var unmarshaller = new CanonicalJson(); + return (Composition) unmarshaller.unmarshal(IOUtils.toString( + new FileInputStream("./src/test/resources/composition/" + name), StandardCharsets.UTF_8)); + } + private OPERATIONALTEMPLATE getOperationalTemplate(OperationalTemplateTestData template) throws IOException, XmlException { return TemplateDocument.Factory.parse(template.getStream()).getTemplate(); diff --git a/validation/src/test/resources/composition/name-test.json b/validation/src/test/resources/composition/name-test.json new file mode 100644 index 000000000..d8de84a9a --- /dev/null +++ b/validation/src/test/resources/composition/name-test.json @@ -0,0 +1,297 @@ +{ + "_type": "COMPOSITION", + "name": { + "_type": "DV_TEXT", + "value": "name-test.ehrbase.org.v0" + }, + "archetype_details": { + "archetype_id": { + "value": "openEHR-EHR-COMPOSITION.report.v1" + }, + "template_id": { + "value": "name-test.ehrbase.org.v0" + }, + "rm_version": "1.0.4" + }, + "language": { + "_type": "CODE_PHRASE", + "terminology_id": { + "_type": "TERMINOLOGY_ID", + "value": "ISO_639-1" + }, + "code_string": "en" + }, + "territory": { + "_type": "CODE_PHRASE", + "terminology_id": { + "_type": "TERMINOLOGY_ID", + "value": "ISO_3166-1" + }, + "code_string": "DE" + }, + "category": { + "_type": "DV_CODED_TEXT", + "value": "event", + "defining_code": { + "_type": "CODE_PHRASE", + "terminology_id": { + "_type": "TERMINOLOGY_ID", + "value": "openehr" + }, + "code_string": "433" + } + }, + "composer": { + "_type": "PARTY_IDENTIFIED", + "name": "Max Mustermann" + }, + "context": { + "_type": "EVENT_CONTEXT", + "start_time": { + "_type": "DV_DATE_TIME", + "value": "2022-02-03T04:05:06" + }, + "end_time": { + "_type": "DV_DATE_TIME", + "value": "2022-02-03T04:05:06" + }, + "setting": { + "_type": "DV_CODED_TEXT", + "value": "home", + "defining_code": { + "_type": "CODE_PHRASE", + "terminology_id": { + "_type": "TERMINOLOGY_ID", + "value": "openehr" + }, + "code_string": "225" + } + }, + "health_care_facility": { + "_type": "PARTY_IDENTIFIED", + "name": "DOE, John" + } + }, + "content": [ + { + "_type": "OBSERVATION", + "name": { + "_type": "DV_TEXT", + "value": "name test" + }, + "archetype_details": { + "archetype_id": { + "value": "openEHR-EHR-OBSERVATION.name_test.v0" + }, + "rm_version": "1.0.4" + }, + "language": { + "_type": "CODE_PHRASE", + "terminology_id": { + "_type": "TERMINOLOGY_ID", + "value": "ISO_639-1" + }, + "code_string": "en" + }, + "encoding": { + "_type": "CODE_PHRASE", + "terminology_id": { + "_type": "TERMINOLOGY_ID", + "value": "IANA_character-sets" + }, + "code_string": "ISO-10646-UTF-1" + }, + "workflow_id": { + "_type": "OBJECT_REF", + "namespace": "unknown", + "type": "ANY", + "id": { + "_type": "GENERIC_ID", + "value": "32951dd7-c841-3872-97e1-d8daa46d7686", + "scheme": "scheme" + } + }, + "subject": { + "_type": "PARTY_SELF" + }, + "provider": { + "_type": "PARTY_SELF" + }, + "guideline_id": { + "_type": "OBJECT_REF", + "namespace": "unknown", + "type": "ANY", + "id": { + "_type": "GENERIC_ID", + "value": "0d0fd2cc-0cd3-3a65-94df-d8aeabf9a85a", + "scheme": "scheme" + } + }, + "data": { + "name": { + "_type": "DV_TEXT", + "value": "History" + }, + "origin": { + "_type": "DV_DATE_TIME", + "value": "2022-02-03T04:05:06" + }, + "period": { + "_type": "DV_DURATION", + "value": "PT0S" + }, + "duration": { + "_type": "DV_DURATION", + "value": "PT0S" + }, + "events": [ + { + "_type": "POINT_EVENT", + "name": { + "_type": "DV_TEXT", + "value": "Any event" + }, + "time": { + "_type": "DV_DATE_TIME", + "value": "2022-02-03T04:05:06" + }, + "data": { + "_type": "ITEM_TREE", + "name": { + "_type": "DV_TEXT", + "value": "Tree" + }, + "items": [ + { + "_type": "CLUSTER", + "name": { + "_type": "DV_TEXT", + "value": "costume name" + }, + "archetype_details": { + "archetype_id": { + "value": "openEHR-EHR-CLUSTER.name_restricted.v0" + }, + "rm_version": "1.0.4" + }, + "items": [ + { + "_type": "ELEMENT", + "name": { + "_type": "DV_TEXT", + "value": "test" + }, + "value": { + "_type": "DV_TEXT", + "value": "value1" + }, + "archetype_node_id": "at0001" + } + ], + "archetype_node_id": "openEHR-EHR-CLUSTER.name.v0" + }, + { + "_type": "CLUSTER", + "name": { + "_type": "DV_TEXT", + "value": "Fv1" + }, + "archetype_details": { + "archetype_id": { + "value": "openEHR-EHR-CLUSTER.name_restricted.v0" + }, + "rm_version": "1.0.4" + }, + "items": [ + { + "_type": "ELEMENT", + "name": { + "_type": "DV_TEXT", + "value": "test" + }, + "value": { + "_type": "DV_TEXT", + "value": "value1" + }, + "archetype_node_id": "at0001" + } + ], + "archetype_node_id": "openEHR-EHR-CLUSTER.name_restricted.v0" + }, + { + "_type": "CLUSTER", + "name": { + "_type": "DV_TEXT", + "value": "Fv2" + }, + "archetype_details": { + "archetype_id": { + "value": "openEHR-EHR-CLUSTER.name_restricted.v0" + }, + "rm_version": "1.0.4" + }, + "items": [ + { + "_type": "ELEMENT", + "name": { + "_type": "DV_TEXT", + "value": "test" + }, + "value": { + "_type": "DV_TEXT", + "value": "value2" + }, + "archetype_node_id": "at0001" + } + ], + "archetype_node_id": "openEHR-EHR-CLUSTER.name_restricted.v0" + }, + { + "_type": "CLUSTER", + "name": { + "_type": "DV_CODED_TEXT", + "value": "NameOne", + "defining_code": { + "_type": "CODE_PHRASE", + "terminology_id": { + "_type": "TERMINOLOGY_ID", + "value": "local" + }, + "code_string": "at0001" + } + }, + "archetype_details": { + "archetype_id": { + "value": "openEHR-EHR-CLUSTER.name_restricted.v0" + }, + "rm_version": "1.0.4" + }, + "items": [ + { + "_type": "ELEMENT", + "name": { + "_type": "DV_TEXT", + "value": "test" + }, + "value": { + "_type": "DV_TEXT", + "value": "value2" + }, + "archetype_node_id": "at0001" + } + ], + "archetype_node_id": "openEHR-EHR-CLUSTER.name_code.v0" + } + ], + "archetype_node_id": "at0003" + }, + "archetype_node_id": "at0002" + } + ], + "archetype_node_id": "at0001" + }, + "archetype_node_id": "openEHR-EHR-OBSERVATION.name_test.v0" + } + ], + "archetype_node_id": "openEHR-EHR-COMPOSITION.report.v1" +} \ No newline at end of file diff --git a/validation/src/test/resources/operational_templates/name-test.ehrbase.org.v0.opt b/validation/src/test/resources/operational_templates/name-test.ehrbase.org.v0.opt new file mode 100644 index 000000000..134eb0492 --- /dev/null +++ b/validation/src/test/resources/operational_templates/name-test.ehrbase.org.v0.opt @@ -0,0 +1,890 @@ + + From 95aa6e96cb46e2d25bfaafc2d29105091f2ffdaf Mon Sep 17 00:00:00 2001 From: "stefan.spiska" Date: Fri, 16 Aug 2024 11:07:55 +0200 Subject: [PATCH 02/26] fix message if name attribute as wrong type --- .../webtemplate/DvTextValidator.java | 6 ++++ .../validation/CompositionValidatorTest.java | 34 +++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/DvTextValidator.java b/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/DvTextValidator.java index 8537eb32d..a9f723060 100644 --- a/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/DvTextValidator.java +++ b/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/DvTextValidator.java @@ -17,6 +17,7 @@ */ package org.ehrbase.openehr.sdk.validation.webtemplate; +import com.nedap.archie.rm.datavalues.DvCodedText; import com.nedap.archie.rm.datavalues.DvText; import java.util.Collections; import java.util.List; @@ -45,10 +46,15 @@ public Class getAssociatedClass() { */ @Override public List validate(DvText dvText, WebTemplateNode node) { + if (!WebTemplateValidationUtils.hasInputs(node)) { return Collections.emptyList(); } + if (node.getRmType().equals("DV_CODED_TEXT") && !(dvText instanceof DvCodedText)) { + return List.of(new ConstraintViolation(node.getAqlPath(), "Expected a DV_CODED_TEXT but got DV_TEXT")); + } + var input = WebTemplateValidationUtils.getInputWithType(node, "TEXT"); return new PrimitiveConstraintValidator().validate(node.getAqlPath(), dvText.getValue(), input); } diff --git a/validation/src/test/java/org/ehrbase/openehr/sdk/validation/CompositionValidatorTest.java b/validation/src/test/java/org/ehrbase/openehr/sdk/validation/CompositionValidatorTest.java index c7182f6aa..6fe6b2599 100644 --- a/validation/src/test/java/org/ehrbase/openehr/sdk/validation/CompositionValidatorTest.java +++ b/validation/src/test/java/org/ehrbase/openehr/sdk/validation/CompositionValidatorTest.java @@ -17,18 +17,23 @@ */ package org.ehrbase.openehr.sdk.validation; +import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.assertFalse; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import com.nedap.archie.rm.composition.Composition; +import com.nedap.archie.rm.datastructures.Cluster; +import com.nedap.archie.rm.datavalues.DvText; import com.nedap.archie.xml.JAXBUtil; import java.io.FileInputStream; import java.io.IOException; import java.nio.charset.StandardCharsets; +import java.util.List; import javax.xml.bind.JAXBException; import org.apache.commons.io.IOUtils; import org.apache.xmlbeans.XmlException; +import org.assertj.core.groups.Tuple; import org.ehrbase.openehr.sdk.serialisation.flatencoding.FlatFormat; import org.ehrbase.openehr.sdk.serialisation.flatencoding.FlatJasonProvider; import org.ehrbase.openehr.sdk.serialisation.jsonencoding.CanonicalJson; @@ -224,6 +229,35 @@ void validateName() throws Exception { result.forEach(System.out::println); } + @Test + void validateNameWrongType() throws Exception { + var composition = getCompositionJson("name-test.json"); + var template = getOperationalTemplate("name-test.ehrbase.org.v0.opt"); + + List objects = composition + .itemsAtPath( + "/content[openEHR-EHR-OBSERVATION.name_test.v0]/data[at0001]/events[at0002]/data[at0003]/items") + .stream() + .map(Cluster.class::cast) + .toList(); + + repaceName(objects, "NameOne", new DvText("NameOne")); + + var result = validator.validate(composition, template); + assertEquals(1, result.size()); + + assertThat(result) + .extracting(ConstraintViolation::getAqlPath, ConstraintViolation::getMessage) + .containsExactly(new Tuple( + "/content[openEHR-EHR-OBSERVATION.name_test.v0]/data[at0001]/events[at0002]/data[at0003]/items[openEHR-EHR-CLUSTER.name_code.v0 and name/value='NameOne']/name", + "Expected a DV_CODED_TEXT but got DV_TEXT")); + } + + private void repaceName(List cluster, String nameOne, DvText dvText) { + + cluster.stream().filter(c -> c.getName().getValue().equals(nameOne)).forEach(c -> c.setName(dvText)); + } + @Test void compositionValidationCRSDK120() throws Exception { var template = getOperationalTemplate(OperationalTemplateTestData.BEFUND_DER_BLUTGASANALYSE); From 5e355510a843b7d200833bbd11ea4d8941956936 Mon Sep 17 00:00:00 2001 From: "stefan.spiska" Date: Fri, 16 Aug 2024 17:10:27 +0200 Subject: [PATCH 03/26] validate that their no unknown nodes --- .../sdk/serialisation/walker/Walker.java | 36 +++++++++++++++++++ .../webtemplate/ValidationWalker.java | 17 +++++++++ .../validation/CompositionValidatorTest.java | 29 +++++++++++++-- 3 files changed, 80 insertions(+), 2 deletions(-) diff --git a/serialisation/src/main/java/org/ehrbase/openehr/sdk/serialisation/walker/Walker.java b/serialisation/src/main/java/org/ehrbase/openehr/sdk/serialisation/walker/Walker.java index b8901f1de..31a61c272 100644 --- a/serialisation/src/main/java/org/ehrbase/openehr/sdk/serialisation/walker/Walker.java +++ b/serialisation/src/main/java/org/ehrbase/openehr/sdk/serialisation/walker/Walker.java @@ -25,10 +25,12 @@ import com.nedap.archie.rm.composition.Composition; import com.nedap.archie.rm.composition.EventContext; import com.nedap.archie.rm.composition.IsmTransition; +import com.nedap.archie.rm.datastructures.ItemTree; import com.nedap.archie.rm.datavalues.quantity.DvInterval; import com.nedap.archie.rminfo.ArchieRMInfoLookup; import com.nedap.archie.rminfo.RMTypeInfo; import java.util.ArrayList; +import java.util.Collections; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; @@ -143,7 +145,39 @@ private void handle(Context context) { handle(context); }); } + + RMObject curentRmObject = context.getRmObjectDeque().peek(); + + List templateChildren; + + if (curentRmObject instanceof ItemTree itemTree) { + templateChildren = itemTree.getItems(); + } else { + templateChildren = Collections.emptyList(); + } + + List missingChildren = templateChildren.stream() + .filter(c -> currentNode.getChildren().stream().noneMatch(n -> { + AqlPath.AqlNode lastNode = n.getAqlPathDto().getLastNode(); + + if (!Objects.equals(n.getNodeId(), c.getArchetypeNodeId())) { + return false; + } + + String otherPredicate = lastNode.findOtherPredicate("name/value"); + + if (otherPredicate != null + && !Objects.equals(otherPredicate, c.getName().getValue())) { + return false; + } + + return true; + })) + .toList(); + + missingChildren.forEach(c -> handleMissingChildren(context, c)); } + postHandle(context); insertDefaults(context); context.getRmObjectDeque().remove(); @@ -151,6 +185,8 @@ private void handle(Context context) { context.getObjectDeque().remove(); } + protected void handleMissingChildren(Context context, RMObject c) {} + private Stream streamChildConstellations( Context context, WebTemplateNode currentNode, diff --git a/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/ValidationWalker.java b/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/ValidationWalker.java index 6b8ed4d10..10942ebbd 100644 --- a/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/ValidationWalker.java +++ b/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/ValidationWalker.java @@ -18,6 +18,7 @@ package org.ehrbase.openehr.sdk.validation.webtemplate; import com.nedap.archie.rm.RMObject; +import com.nedap.archie.rm.archetyped.Locatable; import com.nedap.archie.rm.datavalues.DvCodedText; import java.util.List; import java.util.Map; @@ -72,6 +73,22 @@ protected void postHandle(Context> context) { // No-op } + @Override + protected void handleMissingChildren(Context> context, RMObject c) { + + if (c instanceof Locatable locatable) { + context.getObjectDeque() + .peek() + .add(new ConstraintViolation( + context.getNodeDeque().peek().getAqlPath(), + "RmObject with type:Cluster, nodeId:openEHR-EHR-CLUSTER.name_code.v0,name:not in template not in template" + .formatted( + locatable.getClass().getSimpleName(), + locatable.getArchetypeNodeId(), + locatable.getName().getValue()))); + } + } + @SuppressWarnings("unchecked") private ConstraintValidator getValidator(RMObject object) { return VALIDATORS.getOrDefault(object.getClass(), defaultValidator); diff --git a/validation/src/test/java/org/ehrbase/openehr/sdk/validation/CompositionValidatorTest.java b/validation/src/test/java/org/ehrbase/openehr/sdk/validation/CompositionValidatorTest.java index 6fe6b2599..31b74252e 100644 --- a/validation/src/test/java/org/ehrbase/openehr/sdk/validation/CompositionValidatorTest.java +++ b/validation/src/test/java/org/ehrbase/openehr/sdk/validation/CompositionValidatorTest.java @@ -241,7 +241,7 @@ void validateNameWrongType() throws Exception { .map(Cluster.class::cast) .toList(); - repaceName(objects, "NameOne", new DvText("NameOne")); + replaceName(objects, "NameOne", new DvText("NameOne")); var result = validator.validate(composition, template); assertEquals(1, result.size()); @@ -253,7 +253,32 @@ void validateNameWrongType() throws Exception { "Expected a DV_CODED_TEXT but got DV_TEXT")); } - private void repaceName(List cluster, String nameOne, DvText dvText) { + @Test + void validateNameNotInTemplate() throws Exception { + var composition = getCompositionJson("name-test.json"); + var template = getOperationalTemplate("name-test.ehrbase.org.v0.opt"); + + List objects = composition + .itemsAtPath( + "/content[openEHR-EHR-OBSERVATION.name_test.v0]/data[at0001]/events[at0002]/data[at0003]/items") + .stream() + .map(Cluster.class::cast) + .toList(); + + replaceName(objects, "NameOne", new DvText("not in template")); + + var result = validator.validate(composition, template); + assertEquals(1, result.size()); + + assertThat(result) + .extracting(ConstraintViolation::getAqlPath, ConstraintViolation::getMessage) + .containsExactly( + new Tuple( + "/content[openEHR-EHR-OBSERVATION.name_test.v0]/data[at0001]/events[at0002]/data[at0003]", + "RmObject with type:Cluster, nodeId:openEHR-EHR-CLUSTER.name_code.v0,name:not in template not in template")); + } + + private void replaceName(List cluster, String nameOne, DvText dvText) { cluster.stream().filter(c -> c.getName().getValue().equals(nameOne)).forEach(c -> c.setName(dvText)); } From 5ebb1766a32e6a705755cb4e408a329ef78851f3 Mon Sep 17 00:00:00 2001 From: "stefan.spiska" Date: Tue, 20 Aug 2024 15:14:50 +0200 Subject: [PATCH 04/26] add test --- .../validation/CompositionValidatorTest.java | 10 + .../cluster-slot.ehrbase.or.v0.json | 185 +++++++ .../cluster-slot.ehrbase.org.v0.opt | 497 ++++++++++++++++++ 3 files changed, 692 insertions(+) create mode 100644 validation/src/test/resources/composition/cluster-slot.ehrbase.or.v0.json create mode 100644 validation/src/test/resources/operational_templates/cluster-slot.ehrbase.org.v0.opt diff --git a/validation/src/test/java/org/ehrbase/openehr/sdk/validation/CompositionValidatorTest.java b/validation/src/test/java/org/ehrbase/openehr/sdk/validation/CompositionValidatorTest.java index 31b74252e..09bff0447 100644 --- a/validation/src/test/java/org/ehrbase/openehr/sdk/validation/CompositionValidatorTest.java +++ b/validation/src/test/java/org/ehrbase/openehr/sdk/validation/CompositionValidatorTest.java @@ -219,6 +219,16 @@ void validateAdverseReaction_BadCodedValue() throws Exception { result.forEach(System.out::println); } + @Test + void validateClusterSlot() throws Exception { + var composition = getCompositionJson("cluster-slot.ehrbase.or.v0.json"); + var template = getOperationalTemplate("cluster-slot.ehrbase.org.v0.opt"); + + var result = validator.validate(composition, template); + assertEquals(0, result.size()); + result.forEach(System.out::println); + } + @Test void validateName() throws Exception { var composition = getCompositionJson("name-test.json"); diff --git a/validation/src/test/resources/composition/cluster-slot.ehrbase.or.v0.json b/validation/src/test/resources/composition/cluster-slot.ehrbase.or.v0.json new file mode 100644 index 000000000..9118ff32c --- /dev/null +++ b/validation/src/test/resources/composition/cluster-slot.ehrbase.or.v0.json @@ -0,0 +1,185 @@ +{ + "_type": "COMPOSITION", + "name": { + "_type": "DV_TEXT", + "value": "cluster-slot.ehrbase.org.v0" + }, + "archetype_details": { + "archetype_id": { + "value": "openEHR-EHR-COMPOSITION.report.v1" + }, + "template_id": { + "value": "cluster-slot.ehrbase.org.v0" + }, + "rm_version": "1.0.4" + }, + "language": { + "_type": "CODE_PHRASE", + "terminology_id": { + "_type": "TERMINOLOGY_ID", + "value": "ISO_639-1" + }, + "code_string": "en" + }, + "territory": { + "_type": "CODE_PHRASE", + "terminology_id": { + "_type": "TERMINOLOGY_ID", + "value": "ISO_3166-1" + }, + "code_string": "DE" + }, + "category": { + "_type": "DV_CODED_TEXT", + "value": "event", + "defining_code": { + "_type": "CODE_PHRASE", + "terminology_id": { + "_type": "TERMINOLOGY_ID", + "value": "openehr" + }, + "code_string": "433" + } + }, + "composer": { + "_type": "PARTY_IDENTIFIED", + "name": "Max Mustermann" + }, + "context": { + "_type": "EVENT_CONTEXT", + "start_time": { + "_type": "DV_DATE_TIME", + "value": "2022-02-03T04:05:06" + }, + "end_time": { + "_type": "DV_DATE_TIME", + "value": "2022-02-03T04:05:06" + }, + "setting": { + "_type": "DV_CODED_TEXT", + "value": "home", + "defining_code": { + "_type": "CODE_PHRASE", + "terminology_id": { + "_type": "TERMINOLOGY_ID", + "value": "openehr" + }, + "code_string": "225" + } + }, + "health_care_facility": { + "_type": "PARTY_IDENTIFIED", + "name": "DOE, John" + } + }, + "content": [ + { + "_type": "OBSERVATION", + "name": { + "_type": "DV_TEXT", + "value": "cluster slot" + }, + "archetype_details": { + "archetype_id": { + "value": "openEHR-EHR-OBSERVATION.cluster_slot.v0" + }, + "rm_version": "1.0.4" + }, + "language": { + "_type": "CODE_PHRASE", + "terminology_id": { + "_type": "TERMINOLOGY_ID", + "value": "ISO_639-1" + }, + "code_string": "en" + }, + "encoding": { + "_type": "CODE_PHRASE", + "terminology_id": { + "_type": "TERMINOLOGY_ID", + "value": "IANA_character-sets" + }, + "code_string": "ISO-10646-UTF-1" + }, + "subject": { + "_type": "PARTY_SELF" + }, + "provider": { + "_type": "PARTY_SELF" + }, + "data": { + "name": { + "_type": "DV_TEXT", + "value": "History" + }, + "origin": { + "_type": "DV_DATE_TIME", + "value": "2022-02-03T04:05:06" + }, + "period": { + "_type": "DV_DURATION", + "value": "PT0S" + }, + "duration": { + "_type": "DV_DURATION", + "value": "PT0S" + }, + "events": [ + { + "_type": "POINT_EVENT", + "name": { + "_type": "DV_TEXT", + "value": "Any event" + }, + "time": { + "_type": "DV_DATE_TIME", + "value": "2022-02-03T04:05:06" + }, + "data": { + "_type": "ITEM_TREE", + "name": { + "_type": "DV_TEXT", + "value": "Tree" + }, + "items": [ + { + "_type": "CLUSTER", + "name": { + "_type": "DV_TEXT", + "value": "costume name" + }, + "archetype_details": { + "archetype_id": { + "value": "openEHR-EHR-CLUSTER.name_restricted.v0" + }, + "rm_version": "1.0.4" + }, + "items": [ + { + "_type": "ELEMENT", + "name": { + "_type": "DV_TEXT", + "value": "test" + }, + "value": { + "_type": "DV_TEXT", + "value": "value1" + }, + "archetype_node_id": "at0001" + } + ], + "archetype_node_id": "at0004" + } + ], + "archetype_node_id": "at0003" + }, + "archetype_node_id": "at0002" + } + ], + "archetype_node_id": "at0001" + }, + "archetype_node_id": "openEHR-EHR-OBSERVATION.cluster_slot.v0" + } + ], + "archetype_node_id": "openEHR-EHR-COMPOSITION.report.v1" +} \ No newline at end of file diff --git a/validation/src/test/resources/operational_templates/cluster-slot.ehrbase.org.v0.opt b/validation/src/test/resources/operational_templates/cluster-slot.ehrbase.org.v0.opt new file mode 100644 index 000000000..9466542e4 --- /dev/null +++ b/validation/src/test/resources/operational_templates/cluster-slot.ehrbase.org.v0.opt @@ -0,0 +1,497 @@ + + From 6e33d6c7ac321ad1c1078402e496673190c1d4e2 Mon Sep 17 00:00:00 2001 From: "stefan.spiska" Date: Tue, 20 Aug 2024 16:31:42 +0200 Subject: [PATCH 05/26] add test --- .../webtemplate/DvTextValidator.java | 3 +- .../webtemplate/ValidationWalker.java | 2 +- .../validation/CompositionValidatorTest.java | 56 +++++++++++++++---- .../test/resources/composition/name-test.json | 2 +- 4 files changed, 50 insertions(+), 13 deletions(-) diff --git a/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/DvTextValidator.java b/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/DvTextValidator.java index a9f723060..6fcc35f07 100644 --- a/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/DvTextValidator.java +++ b/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/DvTextValidator.java @@ -21,6 +21,7 @@ import com.nedap.archie.rm.datavalues.DvText; import java.util.Collections; import java.util.List; +import java.util.Objects; import org.ehrbase.openehr.sdk.validation.ConstraintViolation; import org.ehrbase.openehr.sdk.webtemplate.model.WebTemplateNode; @@ -51,7 +52,7 @@ public List validate(DvText dvText, WebTemplateNode node) { return Collections.emptyList(); } - if (node.getRmType().equals("DV_CODED_TEXT") && !(dvText instanceof DvCodedText)) { + if (Objects.equals(node.getRmType(), "DV_CODED_TEXT") && !(dvText instanceof DvCodedText)) { return List.of(new ConstraintViolation(node.getAqlPath(), "Expected a DV_CODED_TEXT but got DV_TEXT")); } diff --git a/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/ValidationWalker.java b/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/ValidationWalker.java index 10942ebbd..3572e0e6a 100644 --- a/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/ValidationWalker.java +++ b/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/ValidationWalker.java @@ -81,7 +81,7 @@ protected void handleMissingChildren(Context> context, .peek() .add(new ConstraintViolation( context.getNodeDeque().peek().getAqlPath(), - "RmObject with type:Cluster, nodeId:openEHR-EHR-CLUSTER.name_code.v0,name:not in template not in template" + "RmObject with type:%s, nodeId:%s,name:%s; not in template" .formatted( locatable.getClass().getSimpleName(), locatable.getArchetypeNodeId(), diff --git a/validation/src/test/java/org/ehrbase/openehr/sdk/validation/CompositionValidatorTest.java b/validation/src/test/java/org/ehrbase/openehr/sdk/validation/CompositionValidatorTest.java index 09bff0447..06be3af13 100644 --- a/validation/src/test/java/org/ehrbase/openehr/sdk/validation/CompositionValidatorTest.java +++ b/validation/src/test/java/org/ehrbase/openehr/sdk/validation/CompositionValidatorTest.java @@ -169,7 +169,13 @@ void rippleConformance() throws Exception { var composition = getComposition("RIPPLE-ConformanceTest.xml"); var result = validator.validate(composition, template); - assertTrue(result.isEmpty()); + assertEquals(1, result.size()); + + assertThat(result) + .extracting(ConstraintViolation::getAqlPath, ConstraintViolation::getMessage) + .containsExactly(new Tuple( + "/content[openEHR-EHR-SECTION.adhoc.v1]/items[openEHR-EHR-ACTION.procedure.v1]/description[at0001]", + "RmObject with type:Element, nodeId:at0065,name:Run-time coded name; not in template")); } @Test @@ -240,16 +246,51 @@ void validateName() throws Exception { } @Test - void validateNameWrongType() throws Exception { + void validateNameRuntimeName() throws Exception { + var composition = getCompositionJson("name-test.json"); + var template = getOperationalTemplate("name-test.ehrbase.org.v0.opt"); + List objects = getClusterList(composition); + + replaceName(objects, "costume name", new DvText("costume name2")); + + var result = validator.validate(composition, template); + assertEquals(0, result.size()); + result.forEach(System.out::println); + } + + @Test + void validateNameRuntimeNameForbidden() throws Exception { var composition = getCompositionJson("name-test.json"); var template = getOperationalTemplate("name-test.ehrbase.org.v0.opt"); + List objects = getClusterList(composition); + + replaceName(objects, "Fv1", new DvText("costume name2")); - List objects = composition + var result = validator.validate(composition, template); + assertEquals(1, result.size()); + assertThat(result) + .extracting(ConstraintViolation::getAqlPath, ConstraintViolation::getMessage) + .containsExactly( + new Tuple( + "/content[openEHR-EHR-OBSERVATION.name_test.v0]/data[at0001]/events[at0002]/data[at0003]", + "RmObject with type:Cluster, nodeId:openEHR-EHR-CLUSTER.name_restricted.v0,name:costume name2; not in template")); + } + + private static List getClusterList(Composition composition) { + return composition .itemsAtPath( "/content[openEHR-EHR-OBSERVATION.name_test.v0]/data[at0001]/events[at0002]/data[at0003]/items") .stream() .map(Cluster.class::cast) .toList(); + } + + @Test + void validateNameWrongType() throws Exception { + var composition = getCompositionJson("name-test.json"); + var template = getOperationalTemplate("name-test.ehrbase.org.v0.opt"); + + List objects = getClusterList(composition); replaceName(objects, "NameOne", new DvText("NameOne")); @@ -268,12 +309,7 @@ void validateNameNotInTemplate() throws Exception { var composition = getCompositionJson("name-test.json"); var template = getOperationalTemplate("name-test.ehrbase.org.v0.opt"); - List objects = composition - .itemsAtPath( - "/content[openEHR-EHR-OBSERVATION.name_test.v0]/data[at0001]/events[at0002]/data[at0003]/items") - .stream() - .map(Cluster.class::cast) - .toList(); + List objects = getClusterList(composition); replaceName(objects, "NameOne", new DvText("not in template")); @@ -285,7 +321,7 @@ void validateNameNotInTemplate() throws Exception { .containsExactly( new Tuple( "/content[openEHR-EHR-OBSERVATION.name_test.v0]/data[at0001]/events[at0002]/data[at0003]", - "RmObject with type:Cluster, nodeId:openEHR-EHR-CLUSTER.name_code.v0,name:not in template not in template")); + "RmObject with type:Cluster, nodeId:openEHR-EHR-CLUSTER.name_code.v0,name:not in template; not in template")); } private void replaceName(List cluster, String nameOne, DvText dvText) { diff --git a/validation/src/test/resources/composition/name-test.json b/validation/src/test/resources/composition/name-test.json index d8de84a9a..f0c8ba0c4 100644 --- a/validation/src/test/resources/composition/name-test.json +++ b/validation/src/test/resources/composition/name-test.json @@ -170,7 +170,7 @@ }, "archetype_details": { "archetype_id": { - "value": "openEHR-EHR-CLUSTER.name_restricted.v0" + "value": "openEHR-EHR-CLUSTER.name.v0" }, "rm_version": "1.0.4" }, From 5ade56053812f237cf2951c7397151d2a2615f24 Mon Sep 17 00:00:00 2001 From: "stefan.spiska" Date: Tue, 20 Aug 2024 20:05:36 +0200 Subject: [PATCH 06/26] fix test --- .../sdk/serialisation/walker/Walker.java | 104 +++++++++++----- .../webtemplate/ValidationWalker.java | 12 +- .../test/resources/composition/name-test.json | 2 +- .../name-test.ehrbase.org.v0.opt | 114 ++++++++++++++---- 4 files changed, 175 insertions(+), 57 deletions(-) diff --git a/serialisation/src/main/java/org/ehrbase/openehr/sdk/serialisation/walker/Walker.java b/serialisation/src/main/java/org/ehrbase/openehr/sdk/serialisation/walker/Walker.java index 31a61c272..e5c08193d 100644 --- a/serialisation/src/main/java/org/ehrbase/openehr/sdk/serialisation/walker/Walker.java +++ b/serialisation/src/main/java/org/ehrbase/openehr/sdk/serialisation/walker/Walker.java @@ -19,13 +19,19 @@ import static org.ehrbase.openehr.sdk.util.rmconstants.RmConstants.*; -import com.nedap.archie.openehrtestrm.Element; import com.nedap.archie.rm.RMObject; import com.nedap.archie.rm.archetyped.Locatable; +import com.nedap.archie.rm.composition.AdminEntry; import com.nedap.archie.rm.composition.Composition; +import com.nedap.archie.rm.composition.Evaluation; import com.nedap.archie.rm.composition.EventContext; import com.nedap.archie.rm.composition.IsmTransition; -import com.nedap.archie.rm.datastructures.ItemTree; +import com.nedap.archie.rm.composition.Section; +import com.nedap.archie.rm.datastructures.Cluster; +import com.nedap.archie.rm.datastructures.Element; +import com.nedap.archie.rm.datastructures.Event; +import com.nedap.archie.rm.datastructures.History; +import com.nedap.archie.rm.datastructures.ItemStructure; import com.nedap.archie.rm.datavalues.quantity.DvInterval; import com.nedap.archie.rminfo.ArchieRMInfoLookup; import com.nedap.archie.rminfo.RMTypeInfo; @@ -36,6 +42,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Optional; import java.util.stream.Collectors; import java.util.stream.IntStream; import java.util.stream.Stream; @@ -146,46 +153,85 @@ private void handle(Context context) { }); } - RMObject curentRmObject = context.getRmObjectDeque().peek(); + List missingChildren = findMissingChildren(context, currentNode); - List templateChildren; + missingChildren.forEach(c -> handleMissingChildren(context, c)); + } - if (curentRmObject instanceof ItemTree itemTree) { - templateChildren = itemTree.getItems(); - } else { - templateChildren = Collections.emptyList(); - } + postHandle(context); + insertDefaults(context); + context.getRmObjectDeque().remove(); + context.getNodeDeque().remove(); + context.getObjectDeque().remove(); + } + + private static List findMissingChildren(Context context, WebTemplateNode currentNode) { + RMObject curentRmObject = context.getRmObjectDeque().peek(); + + return getLocatable(curentRmObject).stream() + .filter(c -> currentNode.getChildren().stream().noneMatch(n -> { + AqlPath.AqlNode lastNode = n.getAqlPathDto().getLastNode(); + + if (!Objects.equals(n.getNodeId(), c.getArchetypeNodeId())) { + return false; + } + + String otherPredicate = lastNode.findOtherPredicate("name/value"); - List missingChildren = templateChildren.stream() - .filter(c -> currentNode.getChildren().stream().noneMatch(n -> { - AqlPath.AqlNode lastNode = n.getAqlPathDto().getLastNode(); + if (otherPredicate != null + && !Objects.equals(otherPredicate, c.getName().getValue())) { + return false; + } - if (!Objects.equals(n.getNodeId(), c.getArchetypeNodeId())) { - return false; - } + return true; + })) + .toList(); + } - String otherPredicate = lastNode.findOtherPredicate("name/value"); + private static List getLocatable(RMObject curentRmObject) { - if (otherPredicate != null - && !Objects.equals(otherPredicate, c.getName().getValue())) { - return false; - } + List templateChildren; - return true; - })) + if (curentRmObject instanceof ItemStructure itemTree) { + templateChildren = itemTree.getItems(); + } else if (curentRmObject instanceof Cluster cluster) { + + templateChildren = cluster.getItems(); + } else if (curentRmObject instanceof History history) { + + templateChildren = history.getEvents(); + } else if (curentRmObject instanceof Event event) { + + templateChildren = Stream.concat( + Optional.of(event).map(Event::getData).stream(), + Optional.of(event).map(Event::getState).stream()) .toList(); + } else if (curentRmObject instanceof AdminEntry adminEntry) { - missingChildren.forEach(c -> handleMissingChildren(context, c)); + templateChildren = + Optional.of(adminEntry).map(AdminEntry::getData).stream().toList(); + } else if (curentRmObject instanceof Evaluation evaluation) { + + templateChildren = + Optional.of(evaluation).map(Evaluation::getData).stream().toList(); + } else if (curentRmObject instanceof Composition composition) { + + templateChildren = composition.getContent(); + } else if (curentRmObject instanceof Section section) { + + templateChildren = section.getItems(); + } else { + templateChildren = Collections.emptyList(); } - postHandle(context); - insertDefaults(context); - context.getRmObjectDeque().remove(); - context.getNodeDeque().remove(); - context.getObjectDeque().remove(); + if (templateChildren == null) { + templateChildren = Collections.emptyList(); + } + + return templateChildren; } - protected void handleMissingChildren(Context context, RMObject c) {} + protected void handleMissingChildren(Context context, Locatable c) {} private Stream streamChildConstellations( Context context, diff --git a/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/ValidationWalker.java b/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/ValidationWalker.java index 3572e0e6a..435df1848 100644 --- a/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/ValidationWalker.java +++ b/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/ValidationWalker.java @@ -22,6 +22,7 @@ import com.nedap.archie.rm.datavalues.DvCodedText; import java.util.List; import java.util.Map; +import java.util.Objects; import org.ehrbase.openehr.sdk.serialisation.walker.Context; import org.ehrbase.openehr.sdk.serialisation.walker.FromCompositionWalker; import org.ehrbase.openehr.sdk.util.reflection.ReflectionHelper; @@ -74,13 +75,18 @@ protected void postHandle(Context> context) { } @Override - protected void handleMissingChildren(Context> context, RMObject c) { + protected void handleMissingChildren(Context> context, Locatable locatable) { + + WebTemplateNode peek = context.getNodeDeque().peek(); + + boolean clusterSlot = Objects.equals(peek.getRmType(), "CLUSTER") + && peek.getChildren().isEmpty(); + if (!clusterSlot) { - if (c instanceof Locatable locatable) { context.getObjectDeque() .peek() .add(new ConstraintViolation( - context.getNodeDeque().peek().getAqlPath(), + peek.getAqlPath(), "RmObject with type:%s, nodeId:%s,name:%s; not in template" .formatted( locatable.getClass().getSimpleName(), diff --git a/validation/src/test/resources/composition/name-test.json b/validation/src/test/resources/composition/name-test.json index f0c8ba0c4..9eb2f2d47 100644 --- a/validation/src/test/resources/composition/name-test.json +++ b/validation/src/test/resources/composition/name-test.json @@ -277,7 +277,7 @@ "_type": "DV_TEXT", "value": "value2" }, - "archetype_node_id": "at0001" + "archetype_node_id": "at0003" } ], "archetype_node_id": "openEHR-EHR-CLUSTER.name_code.v0" diff --git a/validation/src/test/resources/operational_templates/name-test.ehrbase.org.v0.opt b/validation/src/test/resources/operational_templates/name-test.ehrbase.org.v0.opt index 134eb0492..68d61479b 100644 --- a/validation/src/test/resources/operational_templates/name-test.ehrbase.org.v0.opt +++ b/validation/src/test/resources/operational_templates/name-test.ehrbase.org.v0.opt @@ -14,9 +14,11 @@ - 0.2.0 + 1.0.0 - Archetype Designer v1.24.13, user=stefanspiska@github, repositoryId=template-1rv + b5854414c80c0fcd041282e3a60d1e74 + DE0723367AA22BB716CEC5342B21FF60 + Archetype Designer v1.24.14-A1, user=stefanspiska@github, repositoryId=template-1rv
@@ -441,14 +443,14 @@ openEHR-EHR-CLUSTER.name.v0 - - test - - name name + + test + + CLUSTER @@ -573,14 +575,14 @@ openEHR-EHR-CLUSTER.name_restricted.v0 - - test - - Fv1 name restricted + + test + + CLUSTER @@ -706,23 +708,24 @@ openEHR-EHR-CLUSTER.name_restricted.v0 - - test - - Fv2 name restricted + + test + + CLUSTER true - false + true false - true + false 0 + 1 at0000 @@ -778,6 +781,65 @@ + + items + + true + true + false + false + 1 + 1 + + false + + ELEMENT + + true + true + false + false + 0 + 1 + + at0003 + + value + + true + true + false + false + 0 + 1 + + false + + DV_TEXT + + true + true + false + false + 1 + 1 + + + + + + + false + false + + true + false + false + true + 1 + + + openEHR-EHR-CLUSTER.name_code.v0 @@ -789,6 +851,10 @@ NameTwo + + test + + name code name code @@ -826,6 +892,10 @@ openEHR-EHR-OBSERVATION.name_test.v0 + + name test + name test + History @ internal @ @@ -842,10 +912,6 @@ cluster - - name test - name test - false @@ -865,6 +931,10 @@ name-test.ehrbase.org.v0 + + name-test.ehrbase.org.v0 + Document to communicate information to others, commonly in response to a request from another party. + Tree @ internal @ @@ -882,9 +952,5 @@ Additional information required to capture local context or to align with other reference models/formalisms. For example: local information requirements or additional metadata to align with FHIR or CIMI equivalents. - - name-test.ehrbase.org.v0 - Document to communicate information to others, commonly in response to a request from another party. - From e7fd9b0d185817c51d9245e2d48896eeac66d8be Mon Sep 17 00:00:00 2001 From: "stefan.spiska" Date: Tue, 20 Aug 2024 20:06:59 +0200 Subject: [PATCH 07/26] change readme --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 60c36bd0f..edd600eeb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ Note: version releases in the 0.x.y range may introduce breaking changes. - Deprecated `response-dto` `EHR_(STATUS)` related classes that are only used by EHRbase ([621](https://github.com/ehrbase/openEHR_SDK/pull/621)) ### Added ### Fixed +- fix validation of Name ([631](https://github.com/ehrbase/openEHR_SDK/pull/631)) ## [2.16.0] ### Added From 91c3032b9b94d5b2e287bad288adb1ce8153aeef Mon Sep 17 00:00:00 2001 From: "stefan.spiska" Date: Wed, 21 Aug 2024 08:14:59 +0200 Subject: [PATCH 08/26] fix test --- .../serialisation/walker/ToCompositionWalker.java | 13 +++++++++++++ .../openehr/sdk/serialisation/walker/Walker.java | 3 ++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/serialisation/src/main/java/org/ehrbase/openehr/sdk/serialisation/walker/ToCompositionWalker.java b/serialisation/src/main/java/org/ehrbase/openehr/sdk/serialisation/walker/ToCompositionWalker.java index 3f2d1f9a5..809616fa8 100644 --- a/serialisation/src/main/java/org/ehrbase/openehr/sdk/serialisation/walker/ToCompositionWalker.java +++ b/serialisation/src/main/java/org/ehrbase/openehr/sdk/serialisation/walker/ToCompositionWalker.java @@ -45,6 +45,7 @@ import com.nedap.archie.rm.support.identification.ArchetypeID; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Objects; @@ -318,4 +319,16 @@ protected void insertDefaults(Context context) { context.getDefaultValues(), context.getNodeDeque().peek())); } + + @Override + protected final void handleMissingChildren(Context context, Locatable c) { + // NOP + } + + @Override + protected final List findMissingChildren( + Context context, WebTemplateNode currentNode) { + // NOP + return Collections.emptyList(); + } } diff --git a/serialisation/src/main/java/org/ehrbase/openehr/sdk/serialisation/walker/Walker.java b/serialisation/src/main/java/org/ehrbase/openehr/sdk/serialisation/walker/Walker.java index e5c08193d..efde2832f 100644 --- a/serialisation/src/main/java/org/ehrbase/openehr/sdk/serialisation/walker/Walker.java +++ b/serialisation/src/main/java/org/ehrbase/openehr/sdk/serialisation/walker/Walker.java @@ -165,10 +165,11 @@ private void handle(Context context) { context.getObjectDeque().remove(); } - private static List findMissingChildren(Context context, WebTemplateNode currentNode) { + protected List findMissingChildren(Context context, WebTemplateNode currentNode) { RMObject curentRmObject = context.getRmObjectDeque().peek(); return getLocatable(curentRmObject).stream() + .filter(Objects::nonNull) .filter(c -> currentNode.getChildren().stream().noneMatch(n -> { AqlPath.AqlNode lastNode = n.getAqlPathDto().getLastNode(); From 180c5045a13a2d4627da05a5034e16b2323af031 Mon Sep 17 00:00:00 2001 From: "stefan.spiska" Date: Mon, 9 Sep 2024 12:16:19 +0200 Subject: [PATCH 09/26] fix review --- .../walker/ToCompositionWalker.java | 8 +- .../sdk/serialisation/walker/Walker.java | 87 +++++++------------ .../webtemplate/ValidationWalker.java | 4 +- 3 files changed, 38 insertions(+), 61 deletions(-) diff --git a/serialisation/src/main/java/org/ehrbase/openehr/sdk/serialisation/walker/ToCompositionWalker.java b/serialisation/src/main/java/org/ehrbase/openehr/sdk/serialisation/walker/ToCompositionWalker.java index 809616fa8..c3405677e 100644 --- a/serialisation/src/main/java/org/ehrbase/openehr/sdk/serialisation/walker/ToCompositionWalker.java +++ b/serialisation/src/main/java/org/ehrbase/openehr/sdk/serialisation/walker/ToCompositionWalker.java @@ -45,12 +45,12 @@ import com.nedap.archie.rm.support.identification.ArchetypeID; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.stream.Collectors; +import java.util.stream.Stream; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.tuple.ImmutablePair; import org.ehrbase.openehr.sdk.serialisation.walker.defaultvalues.defaultinserter.DefaultValueInserter; @@ -321,14 +321,14 @@ protected void insertDefaults(Context context) { } @Override - protected final void handleMissingChildren(Context context, Locatable c) { + protected final void handleChildrenNotInTemplate(Context context, Locatable c) { // NOP } @Override - protected final List findMissingChildren( + protected final Stream findChildrenNotInTemplate( Context context, WebTemplateNode currentNode) { // NOP - return Collections.emptyList(); + return Stream.empty(); } } diff --git a/serialisation/src/main/java/org/ehrbase/openehr/sdk/serialisation/walker/Walker.java b/serialisation/src/main/java/org/ehrbase/openehr/sdk/serialisation/walker/Walker.java index efde2832f..0b85dab5a 100644 --- a/serialisation/src/main/java/org/ehrbase/openehr/sdk/serialisation/walker/Walker.java +++ b/serialisation/src/main/java/org/ehrbase/openehr/sdk/serialisation/walker/Walker.java @@ -21,28 +21,21 @@ import com.nedap.archie.rm.RMObject; import com.nedap.archie.rm.archetyped.Locatable; -import com.nedap.archie.rm.composition.AdminEntry; import com.nedap.archie.rm.composition.Composition; -import com.nedap.archie.rm.composition.Evaluation; import com.nedap.archie.rm.composition.EventContext; import com.nedap.archie.rm.composition.IsmTransition; -import com.nedap.archie.rm.composition.Section; -import com.nedap.archie.rm.datastructures.Cluster; import com.nedap.archie.rm.datastructures.Element; -import com.nedap.archie.rm.datastructures.Event; -import com.nedap.archie.rm.datastructures.History; -import com.nedap.archie.rm.datastructures.ItemStructure; import com.nedap.archie.rm.datavalues.quantity.DvInterval; import com.nedap.archie.rminfo.ArchieRMInfoLookup; import com.nedap.archie.rminfo.RMTypeInfo; +import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; -import java.util.Collections; +import java.util.Collection; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.Optional; import java.util.stream.Collectors; import java.util.stream.IntStream; import java.util.stream.Stream; @@ -153,9 +146,9 @@ private void handle(Context context) { }); } - List missingChildren = findMissingChildren(context, currentNode); + Stream childrenNotInTemplate = findChildrenNotInTemplate(context, currentNode); - missingChildren.forEach(c -> handleMissingChildren(context, c)); + childrenNotInTemplate.forEach(c -> handleChildrenNotInTemplate(context, c)); } postHandle(context); @@ -165,12 +158,12 @@ private void handle(Context context) { context.getObjectDeque().remove(); } - protected List findMissingChildren(Context context, WebTemplateNode currentNode) { + protected Stream findChildrenNotInTemplate( + Context context, WebTemplateNode currentNode) { RMObject curentRmObject = context.getRmObjectDeque().peek(); - return getLocatable(curentRmObject).stream() - .filter(Objects::nonNull) - .filter(c -> currentNode.getChildren().stream().noneMatch(n -> { + return getChildLocatable(curentRmObject).filter(Objects::nonNull).filter(c -> currentNode.getChildren().stream() + .noneMatch(n -> { AqlPath.AqlNode lastNode = n.getAqlPathDto().getLastNode(); if (!Objects.equals(n.getNodeId(), c.getArchetypeNodeId())) { @@ -185,54 +178,38 @@ protected List findMissingChildren(Context context, } return true; - })) - .toList(); + })); } - private static List getLocatable(RMObject curentRmObject) { + private static Stream getChildLocatable(RMObject curentRmObject) { - List templateChildren; + return ArchieRMInfoLookup.getInstance().getTypeInfo(curentRmObject.getClass()).getAttributes().values().stream() + .filter(s -> !s.isComputed()) + .filter(s -> Locatable.class.isAssignableFrom(s.getTypeInCollection())) + .flatMap(a -> { + Object invoke = null; + try { - if (curentRmObject instanceof ItemStructure itemTree) { - templateChildren = itemTree.getItems(); - } else if (curentRmObject instanceof Cluster cluster) { - - templateChildren = cluster.getItems(); - } else if (curentRmObject instanceof History history) { - - templateChildren = history.getEvents(); - } else if (curentRmObject instanceof Event event) { - - templateChildren = Stream.concat( - Optional.of(event).map(Event::getData).stream(), - Optional.of(event).map(Event::getState).stream()) - .toList(); - } else if (curentRmObject instanceof AdminEntry adminEntry) { - - templateChildren = - Optional.of(adminEntry).map(AdminEntry::getData).stream().toList(); - } else if (curentRmObject instanceof Evaluation evaluation) { - - templateChildren = - Optional.of(evaluation).map(Evaluation::getData).stream().toList(); - } else if (curentRmObject instanceof Composition composition) { - - templateChildren = composition.getContent(); - } else if (curentRmObject instanceof Section section) { - - templateChildren = section.getItems(); - } else { - templateChildren = Collections.emptyList(); - } + invoke = a.getGetMethod().invoke(curentRmObject); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } catch (InvocationTargetException e) { + throw new RuntimeException(e); + } - if (templateChildren == null) { - templateChildren = Collections.emptyList(); - } + if (invoke == null) { + return Stream.empty(); + } else if (invoke instanceof Collection c) { - return templateChildren; + return c.stream(); + } else { + return Stream.of(invoke); + } + }) + .map(Locatable.class::cast); } - protected void handleMissingChildren(Context context, Locatable c) {} + protected void handleChildrenNotInTemplate(Context context, Locatable c) {} private Stream streamChildConstellations( Context context, diff --git a/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/ValidationWalker.java b/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/ValidationWalker.java index 435df1848..b222d287c 100644 --- a/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/ValidationWalker.java +++ b/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/ValidationWalker.java @@ -75,13 +75,13 @@ protected void postHandle(Context> context) { } @Override - protected void handleMissingChildren(Context> context, Locatable locatable) { + protected void handleChildrenNotInTemplate(Context> context, Locatable locatable) { WebTemplateNode peek = context.getNodeDeque().peek(); boolean clusterSlot = Objects.equals(peek.getRmType(), "CLUSTER") && peek.getChildren().isEmpty(); - if (!clusterSlot) { + if (!clusterSlot && !peek.getAqlPath().equals("/context")) { context.getObjectDeque() .peek() From 09542cf5c280d4431098151fcaac8eed0957842b Mon Sep 17 00:00:00 2001 From: "stefan.spiska" Date: Wed, 18 Sep 2024 08:55:14 +0200 Subject: [PATCH 10/26] fix review --- CHANGELOG.md | 2 +- .../openehr/sdk/validation/webtemplate/DvTextValidator.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index edd600eeb..aa638ea51 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ Note: version releases in the 0.x.y range may introduce breaking changes. - Deprecated `response-dto` `EHR_(STATUS)` related classes that are only used by EHRbase ([621](https://github.com/ehrbase/openEHR_SDK/pull/621)) ### Added ### Fixed -- fix validation of Name ([631](https://github.com/ehrbase/openEHR_SDK/pull/631)) +- validate for unexpected children ([631](https://github.com/ehrbase/openEHR_SDK/pull/631)) ## [2.16.0] ### Added diff --git a/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/DvTextValidator.java b/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/DvTextValidator.java index 6fcc35f07..22c61969a 100644 --- a/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/DvTextValidator.java +++ b/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/DvTextValidator.java @@ -21,7 +21,7 @@ import com.nedap.archie.rm.datavalues.DvText; import java.util.Collections; import java.util.List; -import java.util.Objects; +import org.ehrbase.openehr.sdk.util.rmconstants.RmConstants; import org.ehrbase.openehr.sdk.validation.ConstraintViolation; import org.ehrbase.openehr.sdk.webtemplate.model.WebTemplateNode; @@ -52,7 +52,7 @@ public List validate(DvText dvText, WebTemplateNode node) { return Collections.emptyList(); } - if (Objects.equals(node.getRmType(), "DV_CODED_TEXT") && !(dvText instanceof DvCodedText)) { + if (RmConstants.DV_CODED_TEXT.equals(node.getRmType()) && !(dvText instanceof DvCodedText)) { return List.of(new ConstraintViolation(node.getAqlPath(), "Expected a DV_CODED_TEXT but got DV_TEXT")); } From 382f677440e4b750fb32c2a48765db79f40ce89a Mon Sep 17 00:00:00 2001 From: "stefan.spiska" Date: Wed, 18 Sep 2024 17:39:38 +0200 Subject: [PATCH 11/26] fix review --- .../openehr/sdk/validation/webtemplate/DvTextValidator.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/DvTextValidator.java b/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/DvTextValidator.java index 22c61969a..8e587f4bf 100644 --- a/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/DvTextValidator.java +++ b/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/DvTextValidator.java @@ -17,7 +17,6 @@ */ package org.ehrbase.openehr.sdk.validation.webtemplate; -import com.nedap.archie.rm.datavalues.DvCodedText; import com.nedap.archie.rm.datavalues.DvText; import java.util.Collections; import java.util.List; @@ -52,7 +51,7 @@ public List validate(DvText dvText, WebTemplateNode node) { return Collections.emptyList(); } - if (RmConstants.DV_CODED_TEXT.equals(node.getRmType()) && !(dvText instanceof DvCodedText)) { + if (RmConstants.DV_CODED_TEXT.equals(node.getRmType())) { return List.of(new ConstraintViolation(node.getAqlPath(), "Expected a DV_CODED_TEXT but got DV_TEXT")); } From 8779d2e92766d404f88e1e550c13aa07781e5885 Mon Sep 17 00:00:00 2001 From: "stefan.spiska" Date: Thu, 19 Sep 2024 15:43:56 +0200 Subject: [PATCH 12/26] fix archetype slot handling --- .../walker/ToCompositionWalker.java | 5 +- .../sdk/serialisation/walker/Walker.java | 49 +++++++++++-------- .../webtemplate/ValidationWalker.java | 10 ++-- .../cluster-slot.ehrbase.or.v0.json | 2 +- .../webtemplate/model/WebTemplateNode.java | 13 +++-- .../sdk/webtemplate/parser/OPTParser.java | 10 ++-- 6 files changed, 54 insertions(+), 35 deletions(-) diff --git a/serialisation/src/main/java/org/ehrbase/openehr/sdk/serialisation/walker/ToCompositionWalker.java b/serialisation/src/main/java/org/ehrbase/openehr/sdk/serialisation/walker/ToCompositionWalker.java index c3405677e..90b260155 100644 --- a/serialisation/src/main/java/org/ehrbase/openehr/sdk/serialisation/walker/ToCompositionWalker.java +++ b/serialisation/src/main/java/org/ehrbase/openehr/sdk/serialisation/walker/ToCompositionWalker.java @@ -53,6 +53,7 @@ import java.util.stream.Stream; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; import org.ehrbase.openehr.sdk.serialisation.walker.defaultvalues.defaultinserter.DefaultValueInserter; import org.ehrbase.openehr.sdk.util.reflection.ReflectionHelper; import org.ehrbase.openehr.sdk.util.rmconstants.RmConstants; @@ -321,12 +322,12 @@ protected void insertDefaults(Context context) { } @Override - protected final void handleChildrenNotInTemplate(Context context, Locatable c) { + protected final void handleChildrenNotInTemplate(Context context, String name, Locatable c) { // NOP } @Override - protected final Stream findChildrenNotInTemplate( + protected final Stream> findChildrenNotInTemplate( Context context, WebTemplateNode currentNode) { // NOP return Stream.empty(); diff --git a/serialisation/src/main/java/org/ehrbase/openehr/sdk/serialisation/walker/Walker.java b/serialisation/src/main/java/org/ehrbase/openehr/sdk/serialisation/walker/Walker.java index 0b85dab5a..586c4c803 100644 --- a/serialisation/src/main/java/org/ehrbase/openehr/sdk/serialisation/walker/Walker.java +++ b/serialisation/src/main/java/org/ehrbase/openehr/sdk/serialisation/walker/Walker.java @@ -41,6 +41,7 @@ import java.util.stream.Stream; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; import org.ehrbase.openehr.sdk.aql.webtemplatepath.AqlPath; import org.ehrbase.openehr.sdk.serialisation.jsonencoding.CanonicalJson; import org.ehrbase.openehr.sdk.serialisation.walker.defaultvalues.DefaultValues; @@ -146,9 +147,10 @@ private void handle(Context context) { }); } - Stream childrenNotInTemplate = findChildrenNotInTemplate(context, currentNode); + Stream> childrenNotInTemplate = + findChildrenNotInTemplate(context, currentNode); - childrenNotInTemplate.forEach(c -> handleChildrenNotInTemplate(context, c)); + childrenNotInTemplate.forEach(c -> handleChildrenNotInTemplate(context, c.getLeft(), c.getRight())); } postHandle(context); @@ -158,30 +160,36 @@ private void handle(Context context) { context.getObjectDeque().remove(); } - protected Stream findChildrenNotInTemplate( + protected Stream> findChildrenNotInTemplate( Context context, WebTemplateNode currentNode) { RMObject curentRmObject = context.getRmObjectDeque().peek(); return getChildLocatable(curentRmObject).filter(Objects::nonNull).filter(c -> currentNode.getChildren().stream() - .noneMatch(n -> { - AqlPath.AqlNode lastNode = n.getAqlPathDto().getLastNode(); + .noneMatch(n -> matches(c.getLeft(), c.getRight(), n))); + } - if (!Objects.equals(n.getNodeId(), c.getArchetypeNodeId())) { - return false; - } + private static boolean matches(String attributeName, Locatable locatable, WebTemplateNode n) { + AqlPath.AqlNode lastNode = n.getAqlPathDto().getLastNode(); - String otherPredicate = lastNode.findOtherPredicate("name/value"); + if (!attributeName.matches(lastNode.getName())) { + return false; + } - if (otherPredicate != null - && !Objects.equals(otherPredicate, c.getName().getValue())) { - return false; - } + if (!Objects.equals(n.getNodeId(), locatable.getArchetypeNodeId())) { + return false; + } - return true; - })); + String otherPredicate = lastNode.findOtherPredicate("name/value"); + + if (otherPredicate != null + && !Objects.equals(otherPredicate, locatable.getName().getValue())) { + return false; + } + + return true; } - private static Stream getChildLocatable(RMObject curentRmObject) { + private static Stream> getChildLocatable(RMObject curentRmObject) { return ArchieRMInfoLookup.getInstance().getTypeInfo(curentRmObject.getClass()).getAttributes().values().stream() .filter(s -> !s.isComputed()) @@ -201,15 +209,14 @@ private static Stream getChildLocatable(RMObject curentRmOb return Stream.empty(); } else if (invoke instanceof Collection c) { - return c.stream(); + return c.stream().map(Locatable.class::cast).map(l -> Pair.of(a.getRmName(), l)); } else { - return Stream.of(invoke); + return Stream.of(invoke).map(Locatable.class::cast).map(l -> Pair.of(a.getRmName(), l)); } - }) - .map(Locatable.class::cast); + }); } - protected void handleChildrenNotInTemplate(Context context, Locatable c) {} + protected void handleChildrenNotInTemplate(Context context, String name, Locatable c) {} private Stream streamChildConstellations( Context context, diff --git a/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/ValidationWalker.java b/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/ValidationWalker.java index b222d287c..f0a224d64 100644 --- a/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/ValidationWalker.java +++ b/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/ValidationWalker.java @@ -75,12 +75,16 @@ protected void postHandle(Context> context) { } @Override - protected void handleChildrenNotInTemplate(Context> context, Locatable locatable) { + protected void handleChildrenNotInTemplate( + Context> context, String attributeName, Locatable locatable) { WebTemplateNode peek = context.getNodeDeque().peek(); - boolean clusterSlot = Objects.equals(peek.getRmType(), "CLUSTER") - && peek.getChildren().isEmpty(); + boolean clusterSlot = peek.getChildren().stream() + .filter(WebTemplateNode::isArchetypeSlot) + .filter(n -> Objects.equals(n.getAqlPathDto().getLastNode().getName(), attributeName)) + .anyMatch(c -> locatable.getArchetypeNodeId().startsWith("openEHR-EHR-" + c.getRmType())); + if (!clusterSlot && !peek.getAqlPath().equals("/context")) { context.getObjectDeque() diff --git a/validation/src/test/resources/composition/cluster-slot.ehrbase.or.v0.json b/validation/src/test/resources/composition/cluster-slot.ehrbase.or.v0.json index 9118ff32c..72450caec 100644 --- a/validation/src/test/resources/composition/cluster-slot.ehrbase.or.v0.json +++ b/validation/src/test/resources/composition/cluster-slot.ehrbase.or.v0.json @@ -168,7 +168,7 @@ "archetype_node_id": "at0001" } ], - "archetype_node_id": "at0004" + "archetype_node_id": "openEHR-EHR-CLUSTER.name_restricted.v0" } ], "archetype_node_id": "at0003" diff --git a/web-template/src/main/java/org/ehrbase/openehr/sdk/webtemplate/model/WebTemplateNode.java b/web-template/src/main/java/org/ehrbase/openehr/sdk/webtemplate/model/WebTemplateNode.java index 3fd8d2cd7..f74e5cd2c 100644 --- a/web-template/src/main/java/org/ehrbase/openehr/sdk/webtemplate/model/WebTemplateNode.java +++ b/web-template/src/main/java/org/ehrbase/openehr/sdk/webtemplate/model/WebTemplateNode.java @@ -45,6 +45,8 @@ public class WebTemplateNode implements Serializable { @JsonIgnore private Integer optionalIdNumber; + private boolean archetypeSlot = false; + private String name; private String localizedName; private String rmType; @@ -90,6 +92,7 @@ public WebTemplateNode(WebTemplateNode other) { this.max = other.max; this.aqlPath = other.aqlPath; this.inContext = other.inContext; + this.archetypeSlot = other.archetypeSlot; this.dependsOn = new ArrayList<>(other.dependsOn); if (other.annotations != null) { this.annotations = new WebTemplateAnnotation(other.annotations); @@ -341,11 +344,7 @@ public boolean isArchetype() { @JsonIgnore public boolean isArchetypeSlot() { - return RM_INFO_LOOKUP.getTypeInfo(this.getRmType()) != null - && Locatable.class.isAssignableFrom( - RM_INFO_LOOKUP.getTypeInfo(this.getRmType()).getJavaClass()) - && StringUtils.startsWith(this.getNodeId(), "at") - && this.getChildren().isEmpty(); + return archetypeSlot; } @JsonIgnore @@ -416,4 +415,8 @@ public String toString() { + rmType + '\'' + ", aqlPath='" + aqlPath + '\'' + '}'; } + + public void setArchetypeSlot(boolean archetypeSlot) { + this.archetypeSlot = archetypeSlot; + } } diff --git a/web-template/src/main/java/org/ehrbase/openehr/sdk/webtemplate/parser/OPTParser.java b/web-template/src/main/java/org/ehrbase/openehr/sdk/webtemplate/parser/OPTParser.java index 231ac5caa..06ecd8a21 100644 --- a/web-template/src/main/java/org/ehrbase/openehr/sdk/webtemplate/parser/OPTParser.java +++ b/web-template/src/main/java/org/ehrbase/openehr/sdk/webtemplate/parser/OPTParser.java @@ -438,12 +438,16 @@ private void parseComplexObjectSingle( List newChildren = new ArrayList<>(); for (COBJECT cobject : cattribute.getChildrenArray()) { - if (cobject instanceof CPRIMITIVEOBJECT) { - inputMap.put( - cattribute.getRmAttributeName(), inputHandler.extractInput((CPRIMITIVEOBJECT) cobject)); + if (cobject instanceof CPRIMITIVEOBJECT cprimitiveobject) { + inputMap.put(cattribute.getRmAttributeName(), inputHandler.extractInput(cprimitiveobject)); } else { List childNode = parseCOBJECT(cobject, pathLoop, termDefinitionMap, cattribute.getRmAttributeName()); + + if (cobject instanceof ARCHETYPESLOT && childNode != null) { + + childNode.forEach(c -> c.setArchetypeSlot(true)); + } if (childNode != null) { newChildren.addAll(childNode); } From f3356a7500ae390f538e2c10ce50d775210e84f9 Mon Sep 17 00:00:00 2001 From: bot Date: Mon, 30 Sep 2024 11:11:58 +0000 Subject: [PATCH 13/26] updated version to 2.19.0-SNAPSHOT --- CHANGELOG.md | 5 +++++ aql/pom.xml | 2 +- bom/pom.xml | 2 +- client/pom.xml | 2 +- example-generator/pom.xml | 2 +- generator-commons/pom.xml | 2 +- generator-maven-plugin/pom.xml | 2 +- generator/pom.xml | 2 +- opt-1.4/pom.xml | 2 +- pom.xml | 4 ++-- response-dto/pom.xml | 2 +- serialisation/pom.xml | 2 +- serialisation_conformance_test/pom.xml | 2 +- terminology/pom.xml | 2 +- test-coverage/pom.xml | 2 +- test-data/pom.xml | 2 +- util/pom.xml | 2 +- validation/pom.xml | 2 +- web-template/pom.xml | 2 +- 19 files changed, 24 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d3fd0159d..66f1bd190 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ Note: version releases in the 0.x.y range may introduce breaking changes. +## [unreleased] + ### Added + ### Fixed + ## [2.18.0] ### Changed - Updated archie to 3.11.0 and antlr to 4.13.1 ([#640](https://github.com/ehrbase/openEHR_SDK/pull/640)) @@ -448,3 +452,4 @@ Note: version releases in the 0.x.y range may introduce breaking changes. [2.16.0]: https://github.com/ehrbase/openEHR_SDK/compare/v2.15.0...v2.16.0 [2.17.0]: https://github.com/ehrbase/openEHR_SDK/compare/v2.16.0...v2.17.0 [2.18.0]: https://github.com/ehrbase/openEHR_SDK/compare/v2.17.0...v2.18.0 +[unreleased]: https://github.com/ehrbase/openEHR_SDK/compare/v2.18.0...HEAD diff --git a/aql/pom.xml b/aql/pom.xml index b88c9c14d..072e20af3 100644 --- a/aql/pom.xml +++ b/aql/pom.xml @@ -25,7 +25,7 @@ org.ehrbase.openehr.sdk sdk-parent - 2.18.0 + 2.19.0-SNAPSHOT aql diff --git a/bom/pom.xml b/bom/pom.xml index 6f41a55bb..7e0c85a2b 100644 --- a/bom/pom.xml +++ b/bom/pom.xml @@ -8,7 +8,7 @@ bom org.ehrbase.openehr.sdk - 2.18.0 + 2.19.0-SNAPSHOT pom openEHR SDK diff --git a/client/pom.xml b/client/pom.xml index 7e3cdfe7a..8b33846e6 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -26,7 +26,7 @@ org.ehrbase.openehr.sdk sdk-parent - 2.18.0 + 2.19.0-SNAPSHOT client diff --git a/example-generator/pom.xml b/example-generator/pom.xml index 6a813a75f..57f949e52 100644 --- a/example-generator/pom.xml +++ b/example-generator/pom.xml @@ -5,7 +5,7 @@ sdk-parent org.ehrbase.openehr.sdk - 2.18.0 + 2.19.0-SNAPSHOT 4.0.0 diff --git a/generator-commons/pom.xml b/generator-commons/pom.xml index a8ef93c98..ffc83a5ae 100644 --- a/generator-commons/pom.xml +++ b/generator-commons/pom.xml @@ -6,7 +6,7 @@ org.ehrbase.openehr.sdk sdk-parent - 2.18.0 + 2.19.0-SNAPSHOT generator-commons diff --git a/generator-maven-plugin/pom.xml b/generator-maven-plugin/pom.xml index 371b6d7c8..85131d911 100644 --- a/generator-maven-plugin/pom.xml +++ b/generator-maven-plugin/pom.xml @@ -5,7 +5,7 @@ sdk-parent org.ehrbase.openehr.sdk - 2.18.0 + 2.19.0-SNAPSHOT 4.0.0 diff --git a/generator/pom.xml b/generator/pom.xml index 560035eb6..827a323d9 100644 --- a/generator/pom.xml +++ b/generator/pom.xml @@ -25,7 +25,7 @@ org.ehrbase.openehr.sdk sdk-parent - 2.18.0 + 2.19.0-SNAPSHOT generator diff --git a/opt-1.4/pom.xml b/opt-1.4/pom.xml index 5192dbb43..8761fba4a 100644 --- a/opt-1.4/pom.xml +++ b/opt-1.4/pom.xml @@ -26,7 +26,7 @@ org.ehrbase.openehr.sdk sdk-parent - 2.18.0 + 2.19.0-SNAPSHOT opt-1.4 diff --git a/pom.xml b/pom.xml index 5166a9956..51e512205 100644 --- a/pom.xml +++ b/pom.xml @@ -25,13 +25,13 @@ org.ehrbase.openehr.sdk bom - 2.18.0 + 2.19.0-SNAPSHOT ./bom/pom.xml org.ehrbase.openehr.sdk sdk-parent - 2.18.0 + 2.19.0-SNAPSHOT pom openEHR SDK diff --git a/response-dto/pom.xml b/response-dto/pom.xml index efbbc3aa1..d92df2ca2 100644 --- a/response-dto/pom.xml +++ b/response-dto/pom.xml @@ -26,7 +26,7 @@ org.ehrbase.openehr.sdk sdk-parent - 2.18.0 + 2.19.0-SNAPSHOT response-dto diff --git a/serialisation/pom.xml b/serialisation/pom.xml index 9f8076bf4..3876ea1c0 100644 --- a/serialisation/pom.xml +++ b/serialisation/pom.xml @@ -26,7 +26,7 @@ org.ehrbase.openehr.sdk sdk-parent - 2.18.0 + 2.19.0-SNAPSHOT serialisation diff --git a/serialisation_conformance_test/pom.xml b/serialisation_conformance_test/pom.xml index 5c3de71d9..b5c7ecf01 100644 --- a/serialisation_conformance_test/pom.xml +++ b/serialisation_conformance_test/pom.xml @@ -26,7 +26,7 @@ org.ehrbase.openehr.sdk sdk-parent - 2.18.0 + 2.19.0-SNAPSHOT serialisation_conformance_test diff --git a/terminology/pom.xml b/terminology/pom.xml index 43c2e1a3c..db7c169f2 100644 --- a/terminology/pom.xml +++ b/terminology/pom.xml @@ -26,7 +26,7 @@ org.ehrbase.openehr.sdk sdk-parent - 2.18.0 + 2.19.0-SNAPSHOT terminology diff --git a/test-coverage/pom.xml b/test-coverage/pom.xml index ac20b1ff7..c27ff7461 100644 --- a/test-coverage/pom.xml +++ b/test-coverage/pom.xml @@ -8,7 +8,7 @@ org.ehrbase.openehr.sdk sdk-parent - 2.18.0 + 2.19.0-SNAPSHOT test-coverage diff --git a/test-data/pom.xml b/test-data/pom.xml index 7c14fdf41..fcc0aae8b 100644 --- a/test-data/pom.xml +++ b/test-data/pom.xml @@ -26,7 +26,7 @@ org.ehrbase.openehr.sdk sdk-parent - 2.18.0 + 2.19.0-SNAPSHOT test-data diff --git a/util/pom.xml b/util/pom.xml index 91db55b91..ae93153c6 100644 --- a/util/pom.xml +++ b/util/pom.xml @@ -25,7 +25,7 @@ org.ehrbase.openehr.sdk sdk-parent - 2.18.0 + 2.19.0-SNAPSHOT util diff --git a/validation/pom.xml b/validation/pom.xml index 768c313f6..0c24bc55a 100644 --- a/validation/pom.xml +++ b/validation/pom.xml @@ -24,7 +24,7 @@ org.ehrbase.openehr.sdk sdk-parent - 2.18.0 + 2.19.0-SNAPSHOT validation diff --git a/web-template/pom.xml b/web-template/pom.xml index 39b5bddfd..9734347c6 100644 --- a/web-template/pom.xml +++ b/web-template/pom.xml @@ -25,7 +25,7 @@ org.ehrbase.openehr.sdk sdk-parent - 2.18.0 + 2.19.0-SNAPSHOT web-template From e93dad4938caa23f98fe85f36939d37c2266a922 Mon Sep 17 00:00:00 2001 From: Holger Reise Date: Wed, 16 Oct 2024 18:35:51 +0200 Subject: [PATCH 14/26] CDR-1421 review revision - validate name constraint of archetype slot - isolate archetype slot validation to ValidationWalker - fix dvquantity_choice composition - cleanup --- .../walker/ToCompositionWalker.java | 14 ---- .../sdk/serialisation/walker/Walker.java | 66 +---------------- .../canonical_json/dvquantity_choice.json | 2 +- .../webtemplate/ValidationWalker.java | 73 ++++++++++++++++++- .../validation/CompositionValidatorTest.java | 58 +++++++-------- .../sdk/webtemplate/parser/OPTParser.java | 14 ++-- 6 files changed, 104 insertions(+), 123 deletions(-) diff --git a/serialisation/src/main/java/org/ehrbase/openehr/sdk/serialisation/walker/ToCompositionWalker.java b/serialisation/src/main/java/org/ehrbase/openehr/sdk/serialisation/walker/ToCompositionWalker.java index 90b260155..3f2d1f9a5 100644 --- a/serialisation/src/main/java/org/ehrbase/openehr/sdk/serialisation/walker/ToCompositionWalker.java +++ b/serialisation/src/main/java/org/ehrbase/openehr/sdk/serialisation/walker/ToCompositionWalker.java @@ -50,10 +50,8 @@ import java.util.Objects; import java.util.Optional; import java.util.stream.Collectors; -import java.util.stream.Stream; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.tuple.ImmutablePair; -import org.apache.commons.lang3.tuple.Pair; import org.ehrbase.openehr.sdk.serialisation.walker.defaultvalues.defaultinserter.DefaultValueInserter; import org.ehrbase.openehr.sdk.util.reflection.ReflectionHelper; import org.ehrbase.openehr.sdk.util.rmconstants.RmConstants; @@ -320,16 +318,4 @@ protected void insertDefaults(Context context) { context.getDefaultValues(), context.getNodeDeque().peek())); } - - @Override - protected final void handleChildrenNotInTemplate(Context context, String name, Locatable c) { - // NOP - } - - @Override - protected final Stream> findChildrenNotInTemplate( - Context context, WebTemplateNode currentNode) { - // NOP - return Stream.empty(); - } } diff --git a/serialisation/src/main/java/org/ehrbase/openehr/sdk/serialisation/walker/Walker.java b/serialisation/src/main/java/org/ehrbase/openehr/sdk/serialisation/walker/Walker.java index 586c4c803..ca46fedc1 100644 --- a/serialisation/src/main/java/org/ehrbase/openehr/sdk/serialisation/walker/Walker.java +++ b/serialisation/src/main/java/org/ehrbase/openehr/sdk/serialisation/walker/Walker.java @@ -28,9 +28,7 @@ import com.nedap.archie.rm.datavalues.quantity.DvInterval; import com.nedap.archie.rminfo.ArchieRMInfoLookup; import com.nedap.archie.rminfo.RMTypeInfo; -import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; -import java.util.Collection; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; @@ -41,7 +39,6 @@ import java.util.stream.Stream; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.tuple.ImmutablePair; -import org.apache.commons.lang3.tuple.Pair; import org.ehrbase.openehr.sdk.aql.webtemplatepath.AqlPath; import org.ehrbase.openehr.sdk.serialisation.jsonencoding.CanonicalJson; import org.ehrbase.openehr.sdk.serialisation.walker.defaultvalues.DefaultValues; @@ -147,10 +144,7 @@ private void handle(Context context) { }); } - Stream> childrenNotInTemplate = - findChildrenNotInTemplate(context, currentNode); - - childrenNotInTemplate.forEach(c -> handleChildrenNotInTemplate(context, c.getLeft(), c.getRight())); + postVisitChildren(context, currentNode); } postHandle(context); @@ -160,64 +154,10 @@ private void handle(Context context) { context.getObjectDeque().remove(); } - protected Stream> findChildrenNotInTemplate( - Context context, WebTemplateNode currentNode) { - RMObject curentRmObject = context.getRmObjectDeque().peek(); - - return getChildLocatable(curentRmObject).filter(Objects::nonNull).filter(c -> currentNode.getChildren().stream() - .noneMatch(n -> matches(c.getLeft(), c.getRight(), n))); - } - - private static boolean matches(String attributeName, Locatable locatable, WebTemplateNode n) { - AqlPath.AqlNode lastNode = n.getAqlPathDto().getLastNode(); - - if (!attributeName.matches(lastNode.getName())) { - return false; - } - - if (!Objects.equals(n.getNodeId(), locatable.getArchetypeNodeId())) { - return false; - } - - String otherPredicate = lastNode.findOtherPredicate("name/value"); - - if (otherPredicate != null - && !Objects.equals(otherPredicate, locatable.getName().getValue())) { - return false; - } - - return true; + protected void postVisitChildren(Context context, WebTemplateNode currentNode) { + // NOOP } - private static Stream> getChildLocatable(RMObject curentRmObject) { - - return ArchieRMInfoLookup.getInstance().getTypeInfo(curentRmObject.getClass()).getAttributes().values().stream() - .filter(s -> !s.isComputed()) - .filter(s -> Locatable.class.isAssignableFrom(s.getTypeInCollection())) - .flatMap(a -> { - Object invoke = null; - try { - - invoke = a.getGetMethod().invoke(curentRmObject); - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } catch (InvocationTargetException e) { - throw new RuntimeException(e); - } - - if (invoke == null) { - return Stream.empty(); - } else if (invoke instanceof Collection c) { - - return c.stream().map(Locatable.class::cast).map(l -> Pair.of(a.getRmName(), l)); - } else { - return Stream.of(invoke).map(Locatable.class::cast).map(l -> Pair.of(a.getRmName(), l)); - } - }); - } - - protected void handleChildrenNotInTemplate(Context context, String name, Locatable c) {} - private Stream streamChildConstellations( Context context, WebTemplateNode currentNode, diff --git a/test-data/src/main/resources/composition/canonical_json/dvquantity_choice.json b/test-data/src/main/resources/composition/canonical_json/dvquantity_choice.json index 628f8f99d..558b1ca34 100644 --- a/test-data/src/main/resources/composition/canonical_json/dvquantity_choice.json +++ b/test-data/src/main/resources/composition/canonical_json/dvquantity_choice.json @@ -93,7 +93,7 @@ "archetype_node_id": "at0005" } ], - "archetype_node_id": "[at0001]" + "archetype_node_id": "at0001" } }, "content": [ diff --git a/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/ValidationWalker.java b/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/ValidationWalker.java index f0a224d64..96f91c87e 100644 --- a/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/ValidationWalker.java +++ b/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/ValidationWalker.java @@ -20,9 +20,15 @@ import com.nedap.archie.rm.RMObject; import com.nedap.archie.rm.archetyped.Locatable; import com.nedap.archie.rm.datavalues.DvCodedText; +import com.nedap.archie.rminfo.ArchieRMInfoLookup; +import java.lang.reflect.InvocationTargetException; +import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.stream.Stream; +import org.apache.commons.lang3.tuple.Pair; +import org.ehrbase.openehr.sdk.aql.webtemplatepath.AqlPath; import org.ehrbase.openehr.sdk.serialisation.walker.Context; import org.ehrbase.openehr.sdk.serialisation.walker.FromCompositionWalker; import org.ehrbase.openehr.sdk.util.reflection.ReflectionHelper; @@ -74,19 +80,22 @@ protected void postHandle(Context> context) { // No-op } - @Override protected void handleChildrenNotInTemplate( Context> context, String attributeName, Locatable locatable) { WebTemplateNode peek = context.getNodeDeque().peek(); - boolean clusterSlot = peek.getChildren().stream() + boolean foundArchetypeSlot = peek.getChildren().stream() .filter(WebTemplateNode::isArchetypeSlot) .filter(n -> Objects.equals(n.getAqlPathDto().getLastNode().getName(), attributeName)) + .filter(n -> { + String otherPredicate = n.getAqlPathDto().getLastNode().findOtherPredicate("name/value"); + return otherPredicate == null + || otherPredicate.equals(locatable.getName().getValue()); + }) .anyMatch(c -> locatable.getArchetypeNodeId().startsWith("openEHR-EHR-" + c.getRmType())); - if (!clusterSlot && !peek.getAqlPath().equals("/context")) { - + if (!foundArchetypeSlot) { context.getObjectDeque() .peek() .add(new ConstraintViolation( @@ -103,4 +112,60 @@ protected void handleChildrenNotInTemplate( private ConstraintValidator getValidator(RMObject object) { return VALIDATORS.getOrDefault(object.getClass(), defaultValidator); } + + @Override + protected void postVisitChildren(Context> context, WebTemplateNode currentNode) { + Stream> childrenNotInTemplate = + findChildrenNotInTemplate(context, currentNode); + + childrenNotInTemplate.forEach(c -> handleChildrenNotInTemplate(context, c.getLeft(), c.getRight())); + } + + protected Stream> findChildrenNotInTemplate( + Context context, WebTemplateNode currentNode) { + RMObject curentRmObject = context.getRmObjectDeque().peek(); + + return getChildLocatable(curentRmObject).filter(Objects::nonNull).filter(c -> currentNode.getChildren().stream() + .filter(n -> !n.isArchetypeSlot()) + .noneMatch(n -> matches(c.getLeft(), c.getRight(), n))); + } + + private static boolean matches(String attributeName, Locatable locatable, WebTemplateNode n) { + AqlPath.AqlNode lastNode = n.getAqlPathDto().getLastNode(); + + if (!attributeName.matches(lastNode.getName())) { + return false; + } + + if (!Objects.equals(n.getNodeId(), locatable.getArchetypeNodeId())) { + return false; + } + + String otherPredicate = lastNode.findOtherPredicate("name/value"); + return otherPredicate == null + || otherPredicate.equals(locatable.getName().getValue()); + } + + private static Stream> getChildLocatable(RMObject curentRmObject) { + + return ArchieRMInfoLookup.getInstance().getTypeInfo(curentRmObject.getClass()).getAttributes().values().stream() + .filter(s -> !s.isComputed()) + .filter(s -> Locatable.class.isAssignableFrom(s.getTypeInCollection())) + .flatMap(a -> { + Object invoke; + try { + invoke = a.getGetMethod().invoke(curentRmObject); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException(e); + } + + if (invoke == null) { + return Stream.empty(); + } else if (invoke instanceof Collection c) { + return c.stream().map(Locatable.class::cast).map(l -> Pair.of(a.getRmName(), l)); + } else { + return Stream.of(invoke).map(Locatable.class::cast).map(l -> Pair.of(a.getRmName(), l)); + } + }); + } } diff --git a/validation/src/test/java/org/ehrbase/openehr/sdk/validation/CompositionValidatorTest.java b/validation/src/test/java/org/ehrbase/openehr/sdk/validation/CompositionValidatorTest.java index 06be3af13..5a59a4c03 100644 --- a/validation/src/test/java/org/ehrbase/openehr/sdk/validation/CompositionValidatorTest.java +++ b/validation/src/test/java/org/ehrbase/openehr/sdk/validation/CompositionValidatorTest.java @@ -18,9 +18,6 @@ package org.ehrbase.openehr.sdk.validation; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.Assert.assertFalse; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; import com.nedap.archie.rm.composition.Composition; import com.nedap.archie.rm.datastructures.Cluster; @@ -59,7 +56,7 @@ void validateInternationalPatientSummary() throws Exception { var composition = getComposition(CompositionTestDataCanonicalJson.IPS); var result = validator.validate(composition, template); - assertTrue(result.isEmpty()); + assertThat(result).isEmpty(); } @Test @@ -68,7 +65,7 @@ void validateReSPECT() throws Exception { var composition = getComposition(CompositionTestDataSimSDTJson.RE_SPECT); var result = validator.validate(composition, template); - assertTrue(result.isEmpty()); + assertThat(result).isEmpty(); } @Test @@ -77,7 +74,7 @@ void validIsmTransition() throws Exception { var composition = getComposition(CompositionTestDataSimSDTJson.ISM_VAILD); var result = validator.validate(composition, template); - assertTrue(result.isEmpty()); + assertThat(result).isEmpty(); } @Test @@ -86,7 +83,7 @@ void ismTransitionWithInvalidCurrentState() throws Exception { var composition = getComposition(CompositionTestDataSimSDTJson.ISM_INVALID_STATE); var result = validator.validate(composition, template); - assertFalse(result.isEmpty()); + assertThat(result).isNotEmpty(); } @Test @@ -95,7 +92,7 @@ void ismTransitionWithWrongState() throws Exception { var composition = getComposition(CompositionTestDataSimSDTJson.ISM_WRONG); var result = validator.validate(composition, template); - assertFalse(result.isEmpty()); + assertThat(result).isNotEmpty(); } @Test @@ -104,7 +101,7 @@ void missingIsmTransition() throws Exception { var composition = getComposition(CompositionTestDataSimSDTJson.ISM_MISSING); var result = validator.validate(composition, template); - assertTrue(result.isEmpty()); + assertThat(result).isEmpty(); } @Test @@ -113,7 +110,7 @@ void validateInternationalPatientSummary_Invalid() throws Exception { var composition = getComposition(CompositionTestDataCanonicalJson.IPS_INVALID); var result = validator.validate(composition, template); - assertEquals(11, result.size()); + assertThat(result).hasSize(11); result.forEach(System.out::println); } @@ -123,7 +120,7 @@ void validateCorona() throws Exception { var composition = getComposition(CompositionTestDataCanonicalJson.CORONA); var result = validator.validate(composition, template); - assertTrue(result.isEmpty()); + assertThat(result).isEmpty(); } @Test @@ -132,7 +129,7 @@ void validateDuration() throws Exception { var composition = getComposition(CompositionTestDataSimSDTJson.DURATION_VALIDATION); var result = validator.validate(composition, template); - assertTrue(result.isEmpty()); + assertThat(result).isEmpty(); } @Test @@ -141,7 +138,7 @@ void cardinality() throws Exception { var composition = getComposition(CompositionTestDataCanonicalJson.SECTION_CARDINALITY); var result = validator.validate(composition, template); - assertEquals(4, result.size()); + assertThat(result).hasSize(4); result.forEach(System.out::println); } @@ -151,7 +148,7 @@ void allTypes() throws Exception { var composition = getComposition(CompositionTestDataCanonicalJson.ALL_TYPES); var result = validator.validate(composition, template); - assertTrue(result.isEmpty()); + assertThat(result).isEmpty(); } @Test @@ -160,7 +157,7 @@ void validateElementWithChoice() throws Exception { var composition = getComposition(CompositionTestDataCanonicalJson.CHOICE_ELEMENT); var result = validator.validate(composition, template); - assertTrue(result.isEmpty()); + assertThat(result).isEmpty(); } @Test @@ -169,7 +166,7 @@ void rippleConformance() throws Exception { var composition = getComposition("RIPPLE-ConformanceTest.xml"); var result = validator.validate(composition, template); - assertEquals(1, result.size()); + assertThat(result).hasSize(1); assertThat(result) .extracting(ConstraintViolation::getAqlPath, ConstraintViolation::getMessage) @@ -184,7 +181,7 @@ void validateLaboratoryTestReport() throws Exception { var template = getOperationalTemplate("IDCR-LaboratoryTestReport.opt"); var result = validator.validate(composition, template); - assertTrue(result.isEmpty()); + assertThat(result).isEmpty(); } @Test @@ -193,7 +190,7 @@ void validateProblemList() throws Exception { var template = getOperationalTemplate("IDCR Problem List.v1.opt"); var result = validator.validate(composition, template); - assertTrue(result.isEmpty()); + assertThat(result).isEmpty(); } @Test @@ -202,7 +199,7 @@ void validateAdverseReaction() throws Exception { var template = getOperationalTemplate("IDCR - Adverse Reaction List.v1.opt"); var result = validator.validate(composition, template); - assertTrue(result.isEmpty()); + assertThat(result).isEmpty(); } @Test @@ -211,7 +208,7 @@ void validateAdverseReaction_BadCodePhrase() throws Exception { var template = getOperationalTemplate("IDCR - Adverse Reaction List.v1.opt"); var result = validator.validate(composition, template); - assertEquals(1, result.size()); + assertThat(result).hasSize(1); result.forEach(System.out::println); } @@ -221,7 +218,7 @@ void validateAdverseReaction_BadCodedValue() throws Exception { var template = getOperationalTemplate("IDCR - Adverse Reaction List.v1.opt"); var result = validator.validate(composition, template); - assertEquals(1, result.size()); + assertThat(result).hasSize(1); result.forEach(System.out::println); } @@ -231,8 +228,7 @@ void validateClusterSlot() throws Exception { var template = getOperationalTemplate("cluster-slot.ehrbase.org.v0.opt"); var result = validator.validate(composition, template); - assertEquals(0, result.size()); - result.forEach(System.out::println); + assertThat(result).isEmpty(); } @Test @@ -241,8 +237,7 @@ void validateName() throws Exception { var template = getOperationalTemplate("name-test.ehrbase.org.v0.opt"); var result = validator.validate(composition, template); - assertEquals(0, result.size()); - result.forEach(System.out::println); + assertThat(result).isEmpty(); } @Test @@ -254,8 +249,7 @@ void validateNameRuntimeName() throws Exception { replaceName(objects, "costume name", new DvText("costume name2")); var result = validator.validate(composition, template); - assertEquals(0, result.size()); - result.forEach(System.out::println); + assertThat(result).isEmpty(); } @Test @@ -267,7 +261,7 @@ void validateNameRuntimeNameForbidden() throws Exception { replaceName(objects, "Fv1", new DvText("costume name2")); var result = validator.validate(composition, template); - assertEquals(1, result.size()); + assertThat(result).hasSize(1); assertThat(result) .extracting(ConstraintViolation::getAqlPath, ConstraintViolation::getMessage) .containsExactly( @@ -295,7 +289,7 @@ void validateNameWrongType() throws Exception { replaceName(objects, "NameOne", new DvText("NameOne")); var result = validator.validate(composition, template); - assertEquals(1, result.size()); + assertThat(result).hasSize(1); assertThat(result) .extracting(ConstraintViolation::getAqlPath, ConstraintViolation::getMessage) @@ -314,7 +308,7 @@ void validateNameNotInTemplate() throws Exception { replaceName(objects, "NameOne", new DvText("not in template")); var result = validator.validate(composition, template); - assertEquals(1, result.size()); + assertThat(result).hasSize(1); assertThat(result) .extracting(ConstraintViolation::getAqlPath, ConstraintViolation::getMessage) @@ -335,7 +329,7 @@ void compositionValidationCRSDK120() throws Exception { var composition = getComposition(CompositionTestDataCanonicalJson.CHOICE_DV_QUANTITY); var result = validator.validate(composition, template); - assertTrue(result.isEmpty()); + assertThat(result).isEmpty(); } @Test @@ -344,7 +338,7 @@ void exampleComposition() throws IOException, XmlException { var composition = getComposition(CompositionTestDataCanonicalJson.MINIMAL_ACTION_2); var result = validator.validate(composition, template); - assertTrue(result.isEmpty()); + assertThat(result).isEmpty(); } private Composition getComposition(CompositionTestDataCanonicalJson composition) throws IOException { diff --git a/web-template/src/main/java/org/ehrbase/openehr/sdk/webtemplate/parser/OPTParser.java b/web-template/src/main/java/org/ehrbase/openehr/sdk/webtemplate/parser/OPTParser.java index 06ecd8a21..a3ee2593d 100644 --- a/web-template/src/main/java/org/ehrbase/openehr/sdk/webtemplate/parser/OPTParser.java +++ b/web-template/src/main/java/org/ehrbase/openehr/sdk/webtemplate/parser/OPTParser.java @@ -355,7 +355,7 @@ private List parseCCOMPLEXOBJECT( ccomplexobject, node.getAqlPathDto(), termDefinitionMap, localNameNode, node); return node; }) - .collect(Collectors.toList()); + .toList(); } else { Optional explicitName = nameValues.stream().findAny(); @@ -444,13 +444,10 @@ private void parseComplexObjectSingle( List childNode = parseCOBJECT(cobject, pathLoop, termDefinitionMap, cattribute.getRmAttributeName()); - if (cobject instanceof ARCHETYPESLOT && childNode != null) { - + if (cobject instanceof ARCHETYPESLOT) { childNode.forEach(c -> c.setArchetypeSlot(true)); } - if (childNode != null) { - newChildren.addAll(childNode); - } + newChildren.addAll(childNode); } if (cattribute instanceof CSINGLEATTRIBUTE @@ -468,7 +465,7 @@ private void parseComplexObjectSingle( List ismTransitionList = newChildren.stream() .filter(n -> RmConstants.ISM_TRANSITION.equals(n.getRmType())) - .collect(Collectors.toList()); + .toList(); if (!ismTransitionList.isEmpty()) { WebTemplateNode firstChild = ismTransitionList.get(0); WebTemplateNode ismTransition = new WebTemplateNode(); @@ -683,7 +680,6 @@ private Optional buildNameNode( .filter(c -> c.getRmAttributeName().equals("name")) .filter(c -> c.getChildrenArray().length == 1) .map(c -> parseCOBJECT(c.getChildrenArray(0), aqlPath, termDefinitionMap, c.getRmAttributeName())) - .filter(Objects::nonNull) .flatMap(List::stream) .findAny(); } @@ -898,7 +894,7 @@ private List parseCOBJECT( MessageFormat.format("The supplied template is not supported: Unsupported type {0}.", "DV_SCALE")); } - return null; + return List.of(); } /** From e201184e4d15999f77ada62e0a3def29675fe0ea Mon Sep 17 00:00:00 2001 From: Holger Reise Date: Wed, 16 Oct 2024 18:42:01 +0200 Subject: [PATCH 15/26] CDR-1421 enhance archetypeNodeId syntax check --- .../openehr/sdk/validation/webtemplate/ValidationWalker.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/ValidationWalker.java b/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/ValidationWalker.java index 96f91c87e..132c6801a 100644 --- a/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/ValidationWalker.java +++ b/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/ValidationWalker.java @@ -93,7 +93,7 @@ protected void handleChildrenNotInTemplate( return otherPredicate == null || otherPredicate.equals(locatable.getName().getValue()); }) - .anyMatch(c -> locatable.getArchetypeNodeId().startsWith("openEHR-EHR-" + c.getRmType())); + .anyMatch(c -> locatable.getArchetypeNodeId().startsWith("openEHR-EHR-" + c.getRmType() + ".")); if (!foundArchetypeSlot) { context.getObjectDeque() From 5d93813216e8b1766a6ab550d03356a3d65dc889 Mon Sep 17 00:00:00 2001 From: "stefan.spiska" Date: Wed, 23 Oct 2024 09:31:17 +0200 Subject: [PATCH 16/26] allow check for missing node to be disabled --- .../sdk/validation/CompositionValidator.java | 21 ++++++++++++++++--- .../webtemplate/ValidationWalker.java | 16 ++++++++++---- .../validation/CompositionValidatorTest.java | 2 +- 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/validation/src/main/java/org/ehrbase/openehr/sdk/validation/CompositionValidator.java b/validation/src/main/java/org/ehrbase/openehr/sdk/validation/CompositionValidator.java index 764947589..0aa56c01d 100644 --- a/validation/src/main/java/org/ehrbase/openehr/sdk/validation/CompositionValidator.java +++ b/validation/src/main/java/org/ehrbase/openehr/sdk/validation/CompositionValidator.java @@ -38,6 +38,8 @@ * This class is NOT thread-safe! */ public class CompositionValidator { + + private final boolean checkForChildrenNotInTemplate; private final ReadWriteLock lock = new ReentrantReadWriteLock(); private ValidationConfiguration validationCfg = new ValidationConfiguration.Builder() @@ -76,11 +78,24 @@ public ConfigurableRMObjectValidator getRmObjectValidator() { } } - ////////////////////////////// - public CompositionValidator() {} + public CompositionValidator() { + this(false); + } + + public CompositionValidator(boolean checkForChildrenNotInTemplate) { + + this(null, checkForChildrenNotInTemplate); + } public CompositionValidator(ExternalTerminologyValidation externalTerminologyValidation) { + + this(externalTerminologyValidation, false); + } + + public CompositionValidator( + ExternalTerminologyValidation externalTerminologyValidation, boolean checkForChildrenNotInTemplate) { this.externalTerminologyValidation = externalTerminologyValidation; + this.checkForChildrenNotInTemplate = checkForChildrenNotInTemplate; } /** @@ -105,7 +120,7 @@ public List validate(Composition composition, WebTemplate t List messages = getRmObjectValidator().validate(composition); if (messages.isEmpty()) { List result = new ArrayList<>(); - new ValidationWalker(externalTerminologyValidation) + new ValidationWalker(externalTerminologyValidation, true) .walk(composition, result, template.getTree(), template.getTemplateId()); return result; } else { diff --git a/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/ValidationWalker.java b/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/ValidationWalker.java index 132c6801a..9c73a21bf 100644 --- a/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/ValidationWalker.java +++ b/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/ValidationWalker.java @@ -51,10 +51,15 @@ public class ValidationWalker extends FromCompositionWalker ConstraintValidator getValidator(RMObject object @Override protected void postVisitChildren(Context> context, WebTemplateNode currentNode) { - Stream> childrenNotInTemplate = - findChildrenNotInTemplate(context, currentNode); - childrenNotInTemplate.forEach(c -> handleChildrenNotInTemplate(context, c.getLeft(), c.getRight())); + if (checkForChildrenNotInTemplate) { + Stream> childrenNotInTemplate = + findChildrenNotInTemplate(context, currentNode); + + childrenNotInTemplate.forEach(c -> handleChildrenNotInTemplate(context, c.getLeft(), c.getRight())); + } } protected Stream> findChildrenNotInTemplate( diff --git a/validation/src/test/java/org/ehrbase/openehr/sdk/validation/CompositionValidatorTest.java b/validation/src/test/java/org/ehrbase/openehr/sdk/validation/CompositionValidatorTest.java index 5a59a4c03..7d2cd3dd2 100644 --- a/validation/src/test/java/org/ehrbase/openehr/sdk/validation/CompositionValidatorTest.java +++ b/validation/src/test/java/org/ehrbase/openehr/sdk/validation/CompositionValidatorTest.java @@ -48,7 +48,7 @@ @SuppressWarnings("java:S5976") class CompositionValidatorTest { - private final CompositionValidator validator = new CompositionValidator(); + private final CompositionValidator validator = new CompositionValidator(true); @Test void validateInternationalPatientSummary() throws Exception { From 8dc27d924886230eda079c54dd6e9aede32b325b Mon Sep 17 00:00:00 2001 From: HolgerReiseVSys <61463838+HolgerReiseVSys@users.noreply.github.com> Date: Thu, 24 Oct 2024 11:34:32 +0200 Subject: [PATCH 17/26] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 214dfa71a..17789020e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ Note: version releases in the 0.x.y range may introduce breaking changes. ## [unreleased] ### Added +- Option to validate compositions for child nodes not defined in template ([631](https://github.com/ehrbase/openEHR_SDK/pull/631)) ### Fixed ## [2.18.0] @@ -17,7 +18,6 @@ Note: version releases in the 0.x.y range may introduce breaking changes. - Deprecated `response-dto` `EHR_(STATUS)` related classes that are only used by EHRbase ([#621](https://github.com/ehrbase/openEHR_SDK/pull/621)) ### Added ### Fixed -- validate for unexpected children ([631](https://github.com/ehrbase/openEHR_SDK/pull/631)) ## [2.16.0] ### Added From 71c24e089330eaabc453b4ebcaee7c570b396b86 Mon Sep 17 00:00:00 2001 From: HolgerReiseVSys <61463838+HolgerReiseVSys@users.noreply.github.com> Date: Thu, 24 Oct 2024 11:40:45 +0200 Subject: [PATCH 18/26] CDR-1421 fixed attribute name matching --- .../openehr/sdk/validation/webtemplate/ValidationWalker.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/ValidationWalker.java b/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/ValidationWalker.java index 9c73a21bf..87d5783f1 100644 --- a/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/ValidationWalker.java +++ b/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/ValidationWalker.java @@ -141,7 +141,7 @@ protected Stream> findChildrenNotInTemplat private static boolean matches(String attributeName, Locatable locatable, WebTemplateNode n) { AqlPath.AqlNode lastNode = n.getAqlPathDto().getLastNode(); - if (!attributeName.matches(lastNode.getName())) { + if (!attributeName.equals(lastNode.getName())) { return false; } From f73eb27602802d74c41025f3c0d41c5a0f062036 Mon Sep 17 00:00:00 2001 From: Holger Reise Date: Thu, 24 Oct 2024 12:06:01 +0200 Subject: [PATCH 19/26] CDR-1421 relay checkForChildrenNotInTemplate --- .../ehrbase/openehr/sdk/validation/CompositionValidator.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/validation/src/main/java/org/ehrbase/openehr/sdk/validation/CompositionValidator.java b/validation/src/main/java/org/ehrbase/openehr/sdk/validation/CompositionValidator.java index 0aa56c01d..682990723 100644 --- a/validation/src/main/java/org/ehrbase/openehr/sdk/validation/CompositionValidator.java +++ b/validation/src/main/java/org/ehrbase/openehr/sdk/validation/CompositionValidator.java @@ -33,7 +33,7 @@ import org.openehr.schemas.v1.OPERATIONALTEMPLATE; /** - * Validator that checks a composition against constraints define in an Operational Template or a + * Validator that checks a composition against constraints defined in an Operational Template or a * Web Template. * This class is NOT thread-safe! */ @@ -120,7 +120,7 @@ public List validate(Composition composition, WebTemplate t List messages = getRmObjectValidator().validate(composition); if (messages.isEmpty()) { List result = new ArrayList<>(); - new ValidationWalker(externalTerminologyValidation, true) + new ValidationWalker(externalTerminologyValidation, checkForChildrenNotInTemplate) .walk(composition, result, template.getTree(), template.getTemplateId()); return result; } else { From 5bd6d2274ad84ca3f2affb05b635674fb835d232 Mon Sep 17 00:00:00 2001 From: Holger Reise Date: Thu, 24 Oct 2024 12:59:29 +0200 Subject: [PATCH 20/26] CDR-1421 cleanup CompositionValidator --- ...ArchetypeNeglectingRMObjectValidator.java} | 43 ++------- .../sdk/validation/CompositionValidator.java | 96 ++++++------------- .../webtemplate/ValidationWalker.java | 4 +- .../validation/CompositionValidatorTest.java | 2 +- 4 files changed, 41 insertions(+), 104 deletions(-) rename validation/src/main/java/org/ehrbase/openehr/sdk/validation/{ConfigurableRMObjectValidator.java => ArchetypeNeglectingRMObjectValidator.java} (54%) diff --git a/validation/src/main/java/org/ehrbase/openehr/sdk/validation/ConfigurableRMObjectValidator.java b/validation/src/main/java/org/ehrbase/openehr/sdk/validation/ArchetypeNeglectingRMObjectValidator.java similarity index 54% rename from validation/src/main/java/org/ehrbase/openehr/sdk/validation/ConfigurableRMObjectValidator.java rename to validation/src/main/java/org/ehrbase/openehr/sdk/validation/ArchetypeNeglectingRMObjectValidator.java index d8df9115e..a2e58836e 100644 --- a/validation/src/main/java/org/ehrbase/openehr/sdk/validation/ConfigurableRMObjectValidator.java +++ b/validation/src/main/java/org/ehrbase/openehr/sdk/validation/ArchetypeNeglectingRMObjectValidator.java @@ -20,59 +20,34 @@ import com.nedap.archie.aom.CObject; import com.nedap.archie.flattener.OperationalTemplateProvider; import com.nedap.archie.rminfo.ModelInfoLookup; -import com.nedap.archie.rmobjectvalidator.RMObjectValidatingProcessor; import com.nedap.archie.rmobjectvalidator.RMObjectValidationMessage; import com.nedap.archie.rmobjectvalidator.RMObjectValidationMessageType; import com.nedap.archie.rmobjectvalidator.RMObjectValidator; import com.nedap.archie.rmobjectvalidator.ValidationConfiguration; import java.util.Collection; -public class ConfigurableRMObjectValidator extends RMObjectValidator { +public class ArchetypeNeglectingRMObjectValidator extends RMObjectValidator { - private final boolean archetypeValidation; - - public ConfigurableRMObjectValidator( + public ArchetypeNeglectingRMObjectValidator( ModelInfoLookup lookup, OperationalTemplateProvider provider, ValidationConfiguration validationConfiguration) { - this(lookup, provider, validationConfiguration, true); - } - - public ConfigurableRMObjectValidator( - ModelInfoLookup lookup, - OperationalTemplateProvider provider, - ValidationConfiguration validationConfiguration, - boolean archetypeValidation) { super(lookup, provider, validationConfiguration); - this.archetypeValidation = archetypeValidation; - } - - public ConfigurableRMObjectValidator(ModelInfoLookup lookup, OperationalTemplateProvider provider) { - this(lookup, provider, null); - } - - public boolean isArchetypeValidation() { - return archetypeValidation; } protected void addMessage(RMObjectValidationMessage message) { - if (!archetypeValidation && message.getType() == RMObjectValidationMessageType.ARCHETYPE_NOT_FOUND) return; - super.addMessage(message); - } - - protected void addMessage(CObject cobject, String actualPath, String message) { - addMessage(new RMObjectValidationMessage(cobject, actualPath, message)); + if (message.getType() != RMObjectValidationMessageType.ARCHETYPE_NOT_FOUND) { + super.addMessage(message); + } } protected void addMessage(CObject cobject, String actualPath, String message, RMObjectValidationMessageType type) { - addMessage(new RMObjectValidationMessage(cobject, actualPath, message, type)); + if (type != RMObjectValidationMessageType.ARCHETYPE_NOT_FOUND) { + super.addMessage(cobject, actualPath, message, type); + } } protected void addAllMessages(Collection messages) { - messages.forEach(msg -> addMessage(msg)); - } - - protected void addAllMessagesFrom(RMObjectValidatingProcessor other) { - addAllMessages(other.getMessages()); + messages.forEach(this::addMessage); } } diff --git a/validation/src/main/java/org/ehrbase/openehr/sdk/validation/CompositionValidator.java b/validation/src/main/java/org/ehrbase/openehr/sdk/validation/CompositionValidator.java index 682990723..c9a657ea6 100644 --- a/validation/src/main/java/org/ehrbase/openehr/sdk/validation/CompositionValidator.java +++ b/validation/src/main/java/org/ehrbase/openehr/sdk/validation/CompositionValidator.java @@ -17,14 +17,14 @@ */ package org.ehrbase.openehr.sdk.validation; +import com.nedap.archie.flattener.OperationalTemplateProvider; import com.nedap.archie.rm.composition.Composition; import com.nedap.archie.rminfo.ArchieRMInfoLookup; import com.nedap.archie.rmobjectvalidator.RMObjectValidationMessage; +import com.nedap.archie.rmobjectvalidator.RMObjectValidator; import com.nedap.archie.rmobjectvalidator.ValidationConfiguration; import java.util.ArrayList; import java.util.List; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.stream.Collectors; import org.ehrbase.openehr.sdk.validation.terminology.ExternalTerminologyValidation; import org.ehrbase.openehr.sdk.validation.webtemplate.ValidationWalker; @@ -40,62 +40,42 @@ public class CompositionValidator { private final boolean checkForChildrenNotInTemplate; - private final ReadWriteLock lock = new ReentrantReadWriteLock(); - private ValidationConfiguration validationCfg = new ValidationConfiguration.Builder() - .validateInvariants(true) - .failOnUnknownTerminologyId(false) - .build(); - - private ConfigurableRMObjectValidator rmObjectValidator; - - { - initObjectValidator(false); - } + private final RMObjectValidator rmObjectValidator; private ExternalTerminologyValidation externalTerminologyValidation; - public void setArchetypeValidation(boolean archetypeValidation) { - initObjectValidator(archetypeValidation); - } - - private void initObjectValidator(boolean archetypeValidation) { - try { - lock.writeLock().lock(); - rmObjectValidator = new ConfigurableRMObjectValidator( - ArchieRMInfoLookup.getInstance(), archetypeId -> null, validationCfg, archetypeValidation); - } finally { - lock.writeLock().unlock(); - } - } - - public ConfigurableRMObjectValidator getRmObjectValidator() { - try { - lock.readLock().lock(); - return rmObjectValidator; - } finally { - lock.readLock().unlock(); - } - } - public CompositionValidator() { - this(false); - } - - public CompositionValidator(boolean checkForChildrenNotInTemplate) { - - this(null, checkForChildrenNotInTemplate); - } - - public CompositionValidator(ExternalTerminologyValidation externalTerminologyValidation) { - - this(externalTerminologyValidation, false); + this(null, false, true, null); } + /** + * + * @param externalTerminologyValidation + * @param checkForChildrenNotInTemplate + * @param validateInvariants perform invariant checks in archie library + * @param archetypeProvider + */ public CompositionValidator( - ExternalTerminologyValidation externalTerminologyValidation, boolean checkForChildrenNotInTemplate) { + ExternalTerminologyValidation externalTerminologyValidation, + boolean checkForChildrenNotInTemplate, + boolean validateInvariants, + OperationalTemplateProvider archetypeProvider) { this.externalTerminologyValidation = externalTerminologyValidation; this.checkForChildrenNotInTemplate = checkForChildrenNotInTemplate; + + ValidationConfiguration validationCfg = new ValidationConfiguration.Builder() + .validateInvariants(validateInvariants) + .failOnUnknownTerminologyId(false) + .build(); + + if (archetypeProvider != null) { + rmObjectValidator = + new RMObjectValidator(ArchieRMInfoLookup.getInstance(), archetypeProvider, validationCfg); + } else { + rmObjectValidator = new ArchetypeNeglectingRMObjectValidator( + ArchieRMInfoLookup.getInstance(), archetypeId -> null, validationCfg); + } } /** @@ -117,7 +97,7 @@ public List validate(Composition composition, OPERATIONALTE * @return the list of constraint violations */ public List validate(Composition composition, WebTemplate template) { - List messages = getRmObjectValidator().validate(composition); + List messages = rmObjectValidator.validate(composition); if (messages.isEmpty()) { List result = new ArrayList<>(); new ValidationWalker(externalTerminologyValidation, checkForChildrenNotInTemplate) @@ -131,24 +111,6 @@ public List validate(Composition composition, WebTemplate t } } - /** - * Enable or disable invariant checks in archie library. - * - * @param validateInvariants the boolean value - */ - public void setRunInvariantChecks(boolean validateInvariants) { - try { - lock.writeLock().lock(); - validationCfg = new ValidationConfiguration.Builder() - .validateInvariants(validateInvariants) - .failOnUnknownTerminologyId(false) - .build(); - initObjectValidator(rmObjectValidator.isArchetypeValidation()); - } finally { - lock.writeLock().unlock(); - } - } - /** * Sets the {@link ExternalTerminologyValidation} used to validate external terminology. * diff --git a/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/ValidationWalker.java b/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/ValidationWalker.java index 87d5783f1..97465539f 100644 --- a/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/ValidationWalker.java +++ b/validation/src/main/java/org/ehrbase/openehr/sdk/validation/webtemplate/ValidationWalker.java @@ -54,12 +54,12 @@ public class ValidationWalker extends FromCompositionWalker Date: Thu, 24 Oct 2024 15:56:51 +0200 Subject: [PATCH 21/26] Bump org.apache.maven.plugins:maven-dependency-plugin (#633) Bumps [org.apache.maven.plugins:maven-dependency-plugin](https://github.com/apache/maven-dependency-plugin) from 3.6.1 to 3.8.0. - [Release notes](https://github.com/apache/maven-dependency-plugin/releases) - [Commits](https://github.com/apache/maven-dependency-plugin/compare/maven-dependency-plugin-3.6.1...maven-dependency-plugin-3.8.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-dependency-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- generator/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generator/pom.xml b/generator/pom.xml index 827a323d9..a10315c4b 100644 --- a/generator/pom.xml +++ b/generator/pom.xml @@ -39,7 +39,7 @@ org.apache.maven.plugins maven-dependency-plugin - 3.6.1 + 3.8.0 copy-dependencies From 358a778be3bd1a048887890633fbdf3131c9294b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 24 Oct 2024 15:57:06 +0200 Subject: [PATCH 22/26] Bump org.sonatype.plugins:nexus-staging-maven-plugin (#635) Bumps org.sonatype.plugins:nexus-staging-maven-plugin from 1.6.13 to 1.7.0. --- updated-dependencies: - dependency-name: org.sonatype.plugins:nexus-staging-maven-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bom/pom.xml b/bom/pom.xml index 7e0c85a2b..b337c4b35 100644 --- a/bom/pom.xml +++ b/bom/pom.xml @@ -67,7 +67,7 @@ 4.11.0 1.7.36 3.1.0 - 1.6.13 + 1.7.0 3.2.4 3.4.1 2.22.2 From 18683a622e16fc81e512cadb7b3d26386d4274be Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 24 Oct 2024 15:57:19 +0200 Subject: [PATCH 23/26] Bump org.apache.maven:maven-plugin-api from 3.9.7 to 3.9.9 (#636) Bumps [org.apache.maven:maven-plugin-api](https://github.com/apache/maven) from 3.9.7 to 3.9.9. - [Release notes](https://github.com/apache/maven/releases) - [Commits](https://github.com/apache/maven/compare/maven-3.9.7...maven-3.9.9) --- updated-dependencies: - dependency-name: org.apache.maven:maven-plugin-api dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- generator-maven-plugin/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generator-maven-plugin/pom.xml b/generator-maven-plugin/pom.xml index 85131d911..af95683b2 100644 --- a/generator-maven-plugin/pom.xml +++ b/generator-maven-plugin/pom.xml @@ -32,7 +32,7 @@ org.apache.maven maven-plugin-api - 3.9.7 + 3.9.9 provided From a3821e0dd5c2ff95a67c53d02c0f02336325b3e5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 24 Oct 2024 15:57:31 +0200 Subject: [PATCH 24/26] Bump org.apache.maven.plugin-tools:maven-plugin-annotations (#642) Bumps [org.apache.maven.plugin-tools:maven-plugin-annotations](https://github.com/apache/maven-plugin-tools) from 3.13.1 to 3.15.0. - [Release notes](https://github.com/apache/maven-plugin-tools/releases) - [Commits](https://github.com/apache/maven-plugin-tools/compare/maven-plugin-tools-3.13.1...maven-plugin-tools-3.15.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugin-tools:maven-plugin-annotations dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- generator-maven-plugin/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generator-maven-plugin/pom.xml b/generator-maven-plugin/pom.xml index af95683b2..db0138877 100644 --- a/generator-maven-plugin/pom.xml +++ b/generator-maven-plugin/pom.xml @@ -26,7 +26,7 @@ org.apache.maven.plugin-tools maven-plugin-annotations - 3.13.1 + 3.15.0 provided From 2f43b6103cb9d5f6ec31be0bd8dad43ad7acf915 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 24 Oct 2024 16:46:27 +0200 Subject: [PATCH 25/26] Bump org.springframework:spring-core from 6.1.6 to 6.1.14 (#643) Bumps [org.springframework:spring-core](https://github.com/spring-projects/spring-framework) from 6.1.6 to 6.1.14. - [Release notes](https://github.com/spring-projects/spring-framework/releases) - [Commits](https://github.com/spring-projects/spring-framework/compare/v6.1.6...v6.1.14) --- updated-dependencies: - dependency-name: org.springframework:spring-core dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- client/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/pom.xml b/client/pom.xml index 8b33846e6..e352ba23e 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -158,7 +158,7 @@ org.springframework spring-core - 6.1.6 + 6.1.14 test From 7396e212ee7ffbf5c02da74fe76888a6a19c33e0 Mon Sep 17 00:00:00 2001 From: bot Date: Mon, 28 Oct 2024 13:43:03 +0000 Subject: [PATCH 26/26] release 2.19.0: updated version to 2.19.0 --- CHANGELOG.md | 4 ++-- aql/pom.xml | 2 +- bom/pom.xml | 2 +- client/pom.xml | 2 +- example-generator/pom.xml | 2 +- generator-commons/pom.xml | 2 +- generator-maven-plugin/pom.xml | 2 +- generator/pom.xml | 2 +- opt-1.4/pom.xml | 2 +- pom.xml | 4 ++-- response-dto/pom.xml | 2 +- serialisation/pom.xml | 2 +- serialisation_conformance_test/pom.xml | 2 +- terminology/pom.xml | 2 +- test-coverage/pom.xml | 2 +- test-data/pom.xml | 2 +- util/pom.xml | 2 +- validation/pom.xml | 2 +- web-template/pom.xml | 2 +- 19 files changed, 21 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 17789020e..244ba0fae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ Note: version releases in the 0.x.y range may introduce breaking changes. -## [unreleased] +## [2.19.0] ### Added - Option to validate compositions for child nodes not defined in template ([631](https://github.com/ehrbase/openEHR_SDK/pull/631)) ### Fixed @@ -453,4 +453,4 @@ Note: version releases in the 0.x.y range may introduce breaking changes. [2.16.0]: https://github.com/ehrbase/openEHR_SDK/compare/v2.15.0...v2.16.0 [2.17.0]: https://github.com/ehrbase/openEHR_SDK/compare/v2.16.0...v2.17.0 [2.18.0]: https://github.com/ehrbase/openEHR_SDK/compare/v2.17.0...v2.18.0 -[unreleased]: https://github.com/ehrbase/openEHR_SDK/compare/v2.18.0...HEAD +[2.19.0]: https://github.com/ehrbase/openEHR_SDK/compare/v2.18.0...v2.19.0 diff --git a/aql/pom.xml b/aql/pom.xml index 072e20af3..178baa83d 100644 --- a/aql/pom.xml +++ b/aql/pom.xml @@ -25,7 +25,7 @@ org.ehrbase.openehr.sdk sdk-parent - 2.19.0-SNAPSHOT + 2.19.0 aql diff --git a/bom/pom.xml b/bom/pom.xml index b337c4b35..c77558675 100644 --- a/bom/pom.xml +++ b/bom/pom.xml @@ -8,7 +8,7 @@ bom org.ehrbase.openehr.sdk - 2.19.0-SNAPSHOT + 2.19.0 pom openEHR SDK diff --git a/client/pom.xml b/client/pom.xml index e352ba23e..b564c8c6c 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -26,7 +26,7 @@ org.ehrbase.openehr.sdk sdk-parent - 2.19.0-SNAPSHOT + 2.19.0 client diff --git a/example-generator/pom.xml b/example-generator/pom.xml index 57f949e52..4d04aae08 100644 --- a/example-generator/pom.xml +++ b/example-generator/pom.xml @@ -5,7 +5,7 @@ sdk-parent org.ehrbase.openehr.sdk - 2.19.0-SNAPSHOT + 2.19.0 4.0.0 diff --git a/generator-commons/pom.xml b/generator-commons/pom.xml index ffc83a5ae..8b3f8ad4b 100644 --- a/generator-commons/pom.xml +++ b/generator-commons/pom.xml @@ -6,7 +6,7 @@ org.ehrbase.openehr.sdk sdk-parent - 2.19.0-SNAPSHOT + 2.19.0 generator-commons diff --git a/generator-maven-plugin/pom.xml b/generator-maven-plugin/pom.xml index db0138877..637a91984 100644 --- a/generator-maven-plugin/pom.xml +++ b/generator-maven-plugin/pom.xml @@ -5,7 +5,7 @@ sdk-parent org.ehrbase.openehr.sdk - 2.19.0-SNAPSHOT + 2.19.0 4.0.0 diff --git a/generator/pom.xml b/generator/pom.xml index a10315c4b..ba3c82b7b 100644 --- a/generator/pom.xml +++ b/generator/pom.xml @@ -25,7 +25,7 @@ org.ehrbase.openehr.sdk sdk-parent - 2.19.0-SNAPSHOT + 2.19.0 generator diff --git a/opt-1.4/pom.xml b/opt-1.4/pom.xml index 8761fba4a..b87105559 100644 --- a/opt-1.4/pom.xml +++ b/opt-1.4/pom.xml @@ -26,7 +26,7 @@ org.ehrbase.openehr.sdk sdk-parent - 2.19.0-SNAPSHOT + 2.19.0 opt-1.4 diff --git a/pom.xml b/pom.xml index 51e512205..3f80dddf7 100644 --- a/pom.xml +++ b/pom.xml @@ -25,13 +25,13 @@ org.ehrbase.openehr.sdk bom - 2.19.0-SNAPSHOT + 2.19.0 ./bom/pom.xml org.ehrbase.openehr.sdk sdk-parent - 2.19.0-SNAPSHOT + 2.19.0 pom openEHR SDK diff --git a/response-dto/pom.xml b/response-dto/pom.xml index d92df2ca2..b9873c015 100644 --- a/response-dto/pom.xml +++ b/response-dto/pom.xml @@ -26,7 +26,7 @@ org.ehrbase.openehr.sdk sdk-parent - 2.19.0-SNAPSHOT + 2.19.0 response-dto diff --git a/serialisation/pom.xml b/serialisation/pom.xml index 3876ea1c0..73f7b071f 100644 --- a/serialisation/pom.xml +++ b/serialisation/pom.xml @@ -26,7 +26,7 @@ org.ehrbase.openehr.sdk sdk-parent - 2.19.0-SNAPSHOT + 2.19.0 serialisation diff --git a/serialisation_conformance_test/pom.xml b/serialisation_conformance_test/pom.xml index b5c7ecf01..bc86da184 100644 --- a/serialisation_conformance_test/pom.xml +++ b/serialisation_conformance_test/pom.xml @@ -26,7 +26,7 @@ org.ehrbase.openehr.sdk sdk-parent - 2.19.0-SNAPSHOT + 2.19.0 serialisation_conformance_test diff --git a/terminology/pom.xml b/terminology/pom.xml index db7c169f2..264cbb8f2 100644 --- a/terminology/pom.xml +++ b/terminology/pom.xml @@ -26,7 +26,7 @@ org.ehrbase.openehr.sdk sdk-parent - 2.19.0-SNAPSHOT + 2.19.0 terminology diff --git a/test-coverage/pom.xml b/test-coverage/pom.xml index c27ff7461..27d702cc5 100644 --- a/test-coverage/pom.xml +++ b/test-coverage/pom.xml @@ -8,7 +8,7 @@ org.ehrbase.openehr.sdk sdk-parent - 2.19.0-SNAPSHOT + 2.19.0 test-coverage diff --git a/test-data/pom.xml b/test-data/pom.xml index fcc0aae8b..99407e3db 100644 --- a/test-data/pom.xml +++ b/test-data/pom.xml @@ -26,7 +26,7 @@ org.ehrbase.openehr.sdk sdk-parent - 2.19.0-SNAPSHOT + 2.19.0 test-data diff --git a/util/pom.xml b/util/pom.xml index ae93153c6..afe70144f 100644 --- a/util/pom.xml +++ b/util/pom.xml @@ -25,7 +25,7 @@ org.ehrbase.openehr.sdk sdk-parent - 2.19.0-SNAPSHOT + 2.19.0 util diff --git a/validation/pom.xml b/validation/pom.xml index 0c24bc55a..b2d7dbeab 100644 --- a/validation/pom.xml +++ b/validation/pom.xml @@ -24,7 +24,7 @@ org.ehrbase.openehr.sdk sdk-parent - 2.19.0-SNAPSHOT + 2.19.0 validation diff --git a/web-template/pom.xml b/web-template/pom.xml index 9734347c6..4628a56e0 100644 --- a/web-template/pom.xml +++ b/web-template/pom.xml @@ -25,7 +25,7 @@ org.ehrbase.openehr.sdk sdk-parent - 2.19.0-SNAPSHOT + 2.19.0 web-template