From 1b67799196e9eb1d9dab9d2318fa793d82149412 Mon Sep 17 00:00:00 2001 From: Renaud Subiger Date: Wed, 6 Oct 2021 11:25:51 +0200 Subject: [PATCH 1/3] Fixes NullPointerException and Sonar issues --- .../dbencoding/CompositionSerializer.java | 315 +++--- .../dbencoding/DBEncodeTest.java | 27 + .../CompositionTestDataCanonicalJson.java | 3 +- .../canonical_json/gecco_personendaten.json | 897 ++++++++++++++++++ 4 files changed, 1105 insertions(+), 137 deletions(-) create mode 100644 test-data/src/main/resources/composition/canonical_json/gecco_personendaten.json diff --git a/serialisation/src/main/java/org/ehrbase/serialisation/dbencoding/CompositionSerializer.java b/serialisation/src/main/java/org/ehrbase/serialisation/dbencoding/CompositionSerializer.java index 10cc934b5..5f92a2ecf 100644 --- a/serialisation/src/main/java/org/ehrbase/serialisation/dbencoding/CompositionSerializer.java +++ b/serialisation/src/main/java/org/ehrbase/serialisation/dbencoding/CompositionSerializer.java @@ -1,36 +1,64 @@ /* -* Modifications copyright (C) 2019 Christian Chevalley, Vitasystems GmbH and Hannover Medical School, -* Stefan Spiska (Vitasystems GmbH). - -* This file is part of Project EHRbase - -* Copyright (c) 2015 Christian Chevalley -* This file is part of Project Ethercis -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ + * Modifications copyright (C) 2019 Christian Chevalley, Vitasystems GmbH and Hannover Medical School, + * Stefan Spiska (Vitasystems GmbH). + * + * This file is part of Project EHRbase + * + * Copyright (c) 2015 Christian Chevalley + * This file is part of Project Ethercis + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.ehrbase.serialisation.dbencoding; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.nedap.archie.rm.RMObject; -import com.nedap.archie.rm.composition.*; -import com.nedap.archie.rm.datastructures.*; +import com.nedap.archie.rm.composition.Action; +import com.nedap.archie.rm.composition.Activity; +import com.nedap.archie.rm.composition.AdminEntry; +import com.nedap.archie.rm.composition.Composition; +import com.nedap.archie.rm.composition.ContentItem; +import com.nedap.archie.rm.composition.Evaluation; +import com.nedap.archie.rm.composition.Instruction; +import com.nedap.archie.rm.composition.Observation; +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.Item; +import com.nedap.archie.rm.datastructures.ItemList; +import com.nedap.archie.rm.datastructures.ItemSingle; +import com.nedap.archie.rm.datastructures.ItemStructure; +import com.nedap.archie.rm.datastructures.ItemTable; +import com.nedap.archie.rm.datastructures.ItemTree; import com.nedap.archie.rm.datavalues.DvText; import com.nedap.archie.rm.integration.GenericEntry; import java.util.Map; -import org.ehrbase.serialisation.attributes.*; +import org.ehrbase.serialisation.attributes.ActionAttributes; +import org.ehrbase.serialisation.attributes.ActivityAttributes; +import org.ehrbase.serialisation.attributes.AdminEntryAttributes; +import org.ehrbase.serialisation.attributes.ClusterAttributes; +import org.ehrbase.serialisation.attributes.ElementAttributes; +import org.ehrbase.serialisation.attributes.EvaluationAttributes; +import org.ehrbase.serialisation.attributes.EventAttributes; +import org.ehrbase.serialisation.attributes.HistoryAttributes; +import org.ehrbase.serialisation.attributes.InstructionAttributes; +import org.ehrbase.serialisation.attributes.ItemStructureAttributes; +import org.ehrbase.serialisation.attributes.ObservationAttributes; +import org.ehrbase.serialisation.attributes.SectionAttributes; import org.ehrbase.serialisation.exception.MarshalException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -52,7 +80,7 @@ public enum WalkerOutputMode { RAW } - private Logger log = LoggerFactory.getLogger(this.getClass()); + private final Logger log = LoggerFactory.getLogger(this.getClass()); protected ItemStack itemStack = new ItemStack(); @@ -128,7 +156,9 @@ public CompositionSerializer() { // @Override private Map traverse(Composition composition) { Map ctree = PathMap.getInstance(); - if (composition == null /* CHC 170426: no content is legit... */) return null; + if (composition == null /* CHC 170426: no content is legit... */) { + return null; + } Map ltree = MultiMap.getInstance(); @@ -164,22 +194,19 @@ private Map traverse(ContentItem item, String tag) { return null; } - log.debug( - "traverse element of class:" - + item.getClass() - + ", tag:" - + tag - + ", nodeid:" - + item.getArchetypeNodeId()); + log.debug("traverse element of class: {}, tag: {}, nodeid: {}", + item.getClass(), tag, item.getArchetypeNodeId()); - if (item.getArchetypeNodeId() == null || item.getArchetypeNodeId().isEmpty()) + if (item.getArchetypeNodeId() == null || item.getArchetypeNodeId().isEmpty()) { throw new IllegalArgumentException( "ContentItem mandatory attribute archetype_node_id null or empty, item:" + item); + } - if (item.getName() == null || item.getName().getValue().isEmpty()) + if (item.getName() == null || item.getName().getValue().isEmpty()) { throw new IllegalArgumentException( "ContentItem mandatory attribute name is null or empty, item:" + item.getArchetypeNodeId()); + } itemStack.pushStacks(tag + "[" + item.getArchetypeNodeId() + "]", item.getName().getValue()); @@ -188,10 +215,11 @@ private Map traverse(ContentItem item, String tag) { Map ltree = PathMap.getInstance(); if (observation.getProtocol() != null) { - ltree = - new EntrySerialTree(ltree, tagMode) - .insert( - observation, TAG_PROTOCOL, traverse(observation.getProtocol(), TAG_PROTOCOL)); + Object protocol = traverse(observation.getProtocol(), TAG_PROTOCOL); + if (protocol != null) { + ltree = new EntrySerialTree(ltree, tagMode) + .insert(observation, TAG_PROTOCOL, traverse(observation.getProtocol(), TAG_PROTOCOL)); + } } if (observation.getData() != null) { @@ -200,24 +228,29 @@ private Map traverse(ContentItem item, String tag) { .insert(observation, TAG_DATA, traverse(observation.getData(), TAG_DATA)); } - if (observation.getState() != null) + if (observation.getState() != null) { ltree = new EntrySerialTree(ltree, tagMode) .insert(observation, TAG_STATE, traverse(observation.getState(), TAG_STATE)); + } ltree = new ObservationAttributes(this, itemStack, ltree).toMap(observation); - if (ltree.size() > 0) retmap = ltree; - else retmap = null; + if (ltree.size() > 0) { + retmap = ltree; + } } else if (item instanceof Evaluation) { Evaluation evaluation = (Evaluation) item; Map ltree = PathMap.getInstance(); - if (evaluation.getProtocol() != null) - ltree = - new EntrySerialTree(ltree, tagMode) - .insert(evaluation, TAG_PROTOCOL, traverse(evaluation.getProtocol(), TAG_PROTOCOL)); + if (evaluation.getProtocol() != null) { + Object protocol = traverse(evaluation.getProtocol(), TAG_PROTOCOL); + if (protocol != null) { + ltree = new EntrySerialTree(ltree, tagMode) + .insert(evaluation, TAG_PROTOCOL, traverse(evaluation.getProtocol(), TAG_PROTOCOL)); + } + } if (evaluation.getData() != null) { ltree = @@ -227,15 +260,16 @@ private Map traverse(ContentItem item, String tag) { ltree = new EvaluationAttributes(this, itemStack, ltree).toMap(evaluation); - if (ltree.size() > 0) retmap = ltree; - else retmap = null; + if (ltree.size() > 0) { + retmap = ltree; + } } else if (item instanceof Instruction) { Map ltree = PathMap.getInstance(); Instruction instruction = (Instruction) item; - if (instruction.getProtocol() != null) + if (instruction.getProtocol() != null) { ltree = new SerialTree(ltree) .insert( @@ -243,6 +277,7 @@ private Map traverse(ContentItem item, String tag) { new NodeEncoding(tagMode) .tag(TAG_PROTOCOL, ((Instruction) item).getProtocol(), ltree), traverse(instruction.getProtocol(), TAG_PROTOCOL)); + } ltree = new InstructionAttributes(this, itemStack, ltree).toMap(instruction); @@ -262,8 +297,9 @@ private Map traverse(ContentItem item, String tag) { ltree = new EntrySerialTree(ltree, tagMode).insert(instruction, TAG_ACTIVITIES, activities); } - if (ltree.size() > 0) retmap = ltree; - else retmap = null; + if (ltree.size() > 0) { + retmap = ltree; + } } else if (item instanceof Action) { Map ltree = PathMap.getInstance(); @@ -273,32 +309,27 @@ private Map traverse(ContentItem item, String tag) { if (action.getProtocol() != null) { Object protocol = traverse(action.getProtocol(), TAG_PROTOCOL); if (protocol != null) { - ltree = - new EntrySerialTree(ltree, tagMode) - .insert(action, TAG_PROTOCOL, traverse(action.getProtocol(), TAG_PROTOCOL)); + ltree = new EntrySerialTree(ltree, tagMode) + .insert(action, TAG_PROTOCOL, traverse(action.getProtocol(), TAG_PROTOCOL)); } } if (action.getDescription() != null) { Object description = traverse(action.getDescription(), TAG_DESCRIPTION); if (description != null) { - ltree = - new EntrySerialTree(ltree, tagMode) - .insert( - action, TAG_DESCRIPTION, traverse(action.getDescription(), TAG_DESCRIPTION)); + ltree = new EntrySerialTree(ltree, tagMode) + .insert(action, TAG_DESCRIPTION, traverse(action.getDescription(), TAG_DESCRIPTION)); } } else { // this should not occur except in test scenario as this is rejected by the validation - log.warn("ACTION requires attribute 'description' at node:" + itemStack.pathStackDump()); + if (log.isWarnEnabled()) { + log.warn("ACTION requires attribute 'description' at node: {}", + itemStack.pathStackDump()); + } } ltree = new ActionAttributes(this, itemStack, ltree).toMap(action); - - if (!ltree.containsKey(TAG_CLASS)) { - // force class as this hasn't been completed since the action is not valid (see above - // comment) - ltree.put(TAG_CLASS, new SimpleClassName(item).toString()); - } + ltree.computeIfAbsent(TAG_CLASS, value -> new SimpleClassName(item).toString()); retmap = ltree; @@ -313,7 +344,7 @@ private Map traverse(ContentItem item, String tag) { contentItem, new NodeEncoding(tagMode).tag(TAG_ITEMS, contentItem, ltree), traverse(contentItem, TAG_ITEMS)); - log.debug("ltree now:" + (ltree != null)); + log.debug("ltree now: {}", ltree != null); } ltree = new SectionAttributes(this, itemStack, ltree).toMap((Section) item); @@ -321,8 +352,7 @@ private Map traverse(ContentItem item, String tag) { ltree.remove(TAG_CLASS); ltree.put(TAG_CLASS, new SimpleClassName(item).toString()); // force the classname - if (ltree.size() > 0) retmap = ltree; - else retmap = null; + retmap = ltree; } else if (item instanceof AdminEntry) { AdminEntry adminEntry = (AdminEntry) item; @@ -339,8 +369,9 @@ private Map traverse(ContentItem item, String tag) { ltree = new AdminEntryAttributes(this, itemStack, ltree).toMap(adminEntry); - if (ltree.size() > 0) retmap = ltree; - else retmap = null; + if (ltree.size() > 0) { + retmap = ltree; + } } else if (item instanceof GenericEntry) { Map ltree = PathMap.getInstance(); @@ -354,11 +385,12 @@ private Map traverse(ContentItem item, String tag) { new NodeEncoding(tagMode).tag(TAG_DATA, genericEntry.getData(), ltree), traverse(genericEntry.getData(), TAG_DATA)); - if (ltree.size() > 0) retmap = ltree; - else retmap = null; + if (ltree.size() > 0) { + retmap = ltree; + } } else { - log.warn("This item is not handled!" + item.getNameAsString()); + log.warn("This item is not handled! {}", item.getNameAsString()); } itemStack.popStacks(); @@ -366,9 +398,11 @@ private Map traverse(ContentItem item, String tag) { } private Map traverse(Activity activity, String tag) { - if (activity == null) return null; + if (activity == null) { + return null; + } - log.debug("traverse activity:" + activity); + log.debug("traverse activity: {}", activity); if (activity.getDescription() == null) { throw new IllegalArgumentException( @@ -383,13 +417,12 @@ private Map traverse(Activity activity, String tag) { tag + "[" + activity.getDescription().getArchetypeNodeId() + "]", activity.getDescription().getName().getValue()); - log.debug( - itemStack.pathStackDump() - + TAG_DESCRIPTION - + "[" - + activity.getArchetypeNodeId() - + "]=" - + activity.getDescription().toString()); + if (log.isDebugEnabled()) { + log.debug("{}{}[{}]={}", itemStack.pathStackDump(), TAG_DESCRIPTION, + activity.getArchetypeNodeId(), + activity.getDescription()); + } + ltree = new EntrySerialTree(ltree, tagMode) .insert( @@ -399,7 +432,7 @@ private Map traverse(Activity activity, String tag) { activity.getDescription(), null)); // don't add a /data in path for description (don't ask me why...) - if (activity.getActionArchetypeId() != null) + if (activity.getActionArchetypeId() != null) { ltree = new SerialTree(ltree) .insert( @@ -407,6 +440,7 @@ private Map traverse(Activity activity, String tag) { activity, TAG_ACTION_ARCHETYPE_ID, activity.getActionArchetypeId().trim()); + } itemStack.popStacks(); return ltree; @@ -424,27 +458,25 @@ private Map traverse(History history, String tag) { return null; } - log.debug("traverse history:" + history); + log.debug("traverse history: {}", history); itemStack.pushStacks( tag + "[" + history.getArchetypeNodeId() + "]", history.getName().getValue()); Map ltree = PathMap.getInstance(); - log.debug( - itemStack.pathStackDump() - + TAG_ORIGIN - + "[" - + history.getArchetypeNodeId() - + "]=" - + history.getOrigin()); + if (log.isDebugEnabled()) { + log.debug("{}{}[{}]={}", itemStack.pathStackDump(), TAG_ORIGIN, history.getArchetypeNodeId(), + history.getOrigin()); + } ltree = new HistoryAttributes(this, itemStack, ltree).toMap(history); - if (history.getSummary() != null) + if (history.getSummary() != null) { ltree = new EntrySerialTree(ltree, tagMode) .insert(history, TAG_SUMMARY, traverse(history.getSummary(), TAG_SUMMARY)); + } if (history.getEvents() != null) { @@ -455,13 +487,11 @@ private Map traverse(History history, String tag) { TAG_EVENTS + "[" + event.getArchetypeNodeId() + "]", event.getName().getValue()); Map subtree = PathMap.getInstance(); - log.debug( - itemStack.pathStackDump() - + TAG_TIME - + "[" - + event.getArchetypeNodeId() - + "]=" - + event.getTime()); + + if (log.isDebugEnabled()) { + log.debug("{}{}[{}]={}", itemStack.pathStackDump(), TAG_TIME, event.getArchetypeNodeId(), + event.getTime()); + } subtree = new EventAttributes(this, itemStack, subtree).toMap(event); @@ -470,10 +500,11 @@ private Map traverse(History history, String tag) { new EntrySerialTree(subtree, tagMode) .insert(event, TAG_DATA, traverse(event.getData(), TAG_DATA)); } - if (event.getState() != null) + if (event.getState() != null) { subtree = new EntrySerialTree(subtree, tagMode) .insert(event, TAG_STATE, traverse(event.getState(), TAG_STATE)); + } if (!subtree.containsKey(TAG_CLASS)) { log.warn("Inserting class type, potentially a test case?"); @@ -512,8 +543,8 @@ private Map compactEntry( if (entry.keySet().size() == 1 && entry.get(TAG_VALUE) != null) { Object o = entry.get(TAG_VALUE); // TAG_VALUE is not required in the properties map representation - target = new SerialTree(target).insert(null, (Object) null, key, o); - } else + target = new SerialTree(target).insert(null, null, key, o); + } else { target = new SerialTree(target) .insert( @@ -521,6 +552,7 @@ private Map compactEntry( null, key, entry); // unchanged and uncompacted + } } return target; @@ -536,7 +568,7 @@ private Map traverse(ItemStructure item, String uppertag) { Map retmap = null; - log.debug("traverse itemstructure:" + item); + log.debug("traverse itemstructure: {}", item); if (item == null) { return null; @@ -560,8 +592,9 @@ private Map traverse(ItemStructure item, String uppertag) { new NodeEncoding(tagMode).tag(TAG_ITEMS, itemSingle, ltree), traverse(itemSingle.getItem(), TAG_ITEMS)); } - if (ltree.size() > 0) retmap = ltree; - else retmap = null; + if (ltree.size() > 0) { + retmap = ltree; + } } else if (item instanceof ItemList) { Map ltree = MultiMap.getInstance(); @@ -578,8 +611,9 @@ private Map traverse(ItemStructure item, String uppertag) { traverse(listItem, TAG_ITEMS)); } } - if (ltree.size() > 0) retmap = ltree; - else retmap = null; + if (ltree.size() > 0) { + retmap = ltree; + } } else if (item instanceof ItemTree) { Map ltree = MultiMap.getInstance(); @@ -597,8 +631,9 @@ private Map traverse(ItemStructure item, String uppertag) { traverse(subItem, TAG_ITEMS)); } } - if (ltree.size() > 0) retmap = ltree; - else retmap = null; + if (ltree.size() > 0) { + retmap = ltree; + } } else if (item instanceof ItemTable) { Map ltree = MultiMap.getInstance(); @@ -616,11 +651,14 @@ private Map traverse(ItemStructure item, String uppertag) { traverse(subItem, TAG_ITEMS)); } } - if (ltree.size() > 0) retmap = ltree; - else retmap = null; + if (ltree.size() > 0) { + retmap = ltree; + } } - if (uppertag != null) itemStack.popStacks(); + if (uppertag != null) { + itemStack.popStacks(); + } if (retmap != null) { if (retmap.containsKey(TAG_CLASS)) { @@ -643,7 +681,7 @@ private Map traverse(ItemStructure item, String uppertag) { private Map traverse(Item item, String tag) { Map retmap = PathMap.getInstance(); - log.debug("traverse item:" + item); + log.debug("traverse item: {}", item); if (item == null) { return null; @@ -665,30 +703,31 @@ private Map traverse(Item item, String tag) { // CHC:160914: fixed issue with cluster encoding as items (generated /value {/name... // /value... /$PATH$... $CLASS$}) // this caused inconsistencies when running AQL queries - for (Object itemInList : cluster.getItems()) { - if (itemInList instanceof Item) { - Item clusterItem = (Item) itemInList; - Map clusterItems = traverse(clusterItem, TAG_ITEMS); - - if (clusterItems != null) { - if (clusterItems.containsKey(TAG_CLASS)) { - clusterItems.put(TAG_CLASS, item.getClass().getSimpleName()); - } - ltree.put( - new NodeEncoding(tagMode).tag(TAG_ITEMS, clusterItem, ltree), - clusterItems.getOrDefault(TAG_VALUE, clusterItems)); - // - } - } else throw new IllegalArgumentException("Found non item in cluster"); + for (Item clusterItem : cluster.getItems()) { + Map clusterItems = traverse(clusterItem, TAG_ITEMS); + + if (clusterItems != null) { + clusterItems.computeIfPresent(TAG_CLASS, + (key, value) -> item.getClass().getSimpleName()); + ltree.put( + new NodeEncoding(tagMode).tag(TAG_ITEMS, clusterItem, ltree), + clusterItems.getOrDefault(TAG_VALUE, clusterItems)); + // + } + } + if (ltree.size() > 0) { + hasContent = true; } - if (ltree.size() > 0) hasContent = true; ltree = new ClusterAttributes(this, itemStack, ltree).toMap(cluster); - if (!ltree.containsKey(TAG_CLASS)) ltree.put(TAG_CLASS, Cluster.class.getSimpleName()); + ltree.computeIfAbsent(TAG_CLASS, value -> Cluster.class.getSimpleName()); + } + if (hasContent) { + retmap = ltree; + } else { + retmap = null; } - if (hasContent) retmap = ltree; - else retmap = null; itemStack.popStacks(); } @@ -702,22 +741,26 @@ public String dbEncode(RMObject rmObject) { Map objectMap; if (rmObject instanceof Composition) { objectMap = traverse((Composition) rmObject); - } else if (rmObject instanceof Item) objectMap = traverse((Item) rmObject, TAG_ITEMS); - else if (rmObject instanceof ItemStructure) { + } else if (rmObject instanceof Item) { + objectMap = traverse((Item) rmObject, TAG_ITEMS); + } else if (rmObject instanceof ItemStructure) { objectMap = traverse((ItemStructure) rmObject, TAG_ITEMS); if (objectMap != null && !objectMap.containsKey(TAG_ARCHETYPE_NODE_ID) - && ((ItemStructure) rmObject).getArchetypeNodeId() != null) + && ((ItemStructure) rmObject).getArchetypeNodeId() != null) { objectMap.put( CompositionSerializer.TAG_ARCHETYPE_NODE_ID, ((ItemStructure) rmObject).getArchetypeNodeId()); + } if (objectMap != null && !objectMap.containsKey(CompositionSerializer.TAG_NAME) - && ((ItemStructure) rmObject).getName() != null) + && ((ItemStructure) rmObject).getName() != null) { objectMap.put(CompositionSerializer.TAG_NAME, ((ItemStructure) rmObject).getName()); - } else + } + } else { throw new MarshalException( String.format("Class %s not supported ", rmObject.getClass()), null); + } GsonBuilder builder = EncodeUtilArchie.getGsonBuilderInstance(); Gson gson = builder.setPrettyPrinting().create(); diff --git a/serialisation/src/test/java/org/ehrbase/serialisation/dbencoding/DBEncodeTest.java b/serialisation/src/test/java/org/ehrbase/serialisation/dbencoding/DBEncodeTest.java index 5b57cb2ab..7eb55835c 100644 --- a/serialisation/src/test/java/org/ehrbase/serialisation/dbencoding/DBEncodeTest.java +++ b/serialisation/src/test/java/org/ehrbase/serialisation/dbencoding/DBEncodeTest.java @@ -798,4 +798,31 @@ public void compositionEncodingFeederAuditDetails() throws Exception { assertEquals(4, ((Map) feederMap.get("other_details[openEHR-EHR-ITEM_TREE.generic.v1]")).size()); } + @Test + public void compositionEncodingEmptyProtocol() throws Exception { + String value = IOUtils.toString(CompositionTestDataCanonicalJson.GECCO_PERSONENDATEN.getStream(), UTF_8); + CanonicalJson cut = new CanonicalJson(); + Composition composition = cut.unmarshal(value, Composition.class); + + assertNotNull(composition); + + CompositionSerializer compositionSerializerRawJson = new CompositionSerializer(); + + String db_encoded = compositionSerializerRawJson.dbEncode(composition); + assertNotNull(db_encoded); + + String converted = new LightRawJsonEncoder(db_encoded).encodeCompositionAsString(); + + assertNotNull(converted); + + //see if this can be interpreted by Archie + Composition object = new CanonicalJson().unmarshal(converted, Composition.class); + + assertNotNull(object); + + String interpreted = new CanonicalXML().marshal(object); + + assertNotNull(interpreted); + } + } diff --git a/test-data/src/main/java/org/ehrbase/test_data/composition/CompositionTestDataCanonicalJson.java b/test-data/src/main/java/org/ehrbase/test_data/composition/CompositionTestDataCanonicalJson.java index f4417187d..cf9f2ca9f 100644 --- a/test-data/src/main/java/org/ehrbase/test_data/composition/CompositionTestDataCanonicalJson.java +++ b/test-data/src/main/java/org/ehrbase/test_data/composition/CompositionTestDataCanonicalJson.java @@ -55,7 +55,8 @@ public enum CompositionTestDataCanonicalJson { DEMO_VITALS("composition to test archetype_details roundtrip", "demo_vitals_352.json"), FEEDER_AUDIT_DETAILS("composition to test feeder audit details", "all_types_systematic_tests_feeder_audit.json"), MINIMAL_INSTRUCTION("minimal instruction (contains DV_DURATION)", "minimal_instruction.json"), - MINIMAL_ACTION_2("Minimal Action 2", "minimal_action2_1.json"); + MINIMAL_ACTION_2("Minimal Action 2", "minimal_action2_1.json"), + GECCO_PERSONENDATEN("GECCO_Personendaten", "gecco_personendaten.json"); private final String filename; diff --git a/test-data/src/main/resources/composition/canonical_json/gecco_personendaten.json b/test-data/src/main/resources/composition/canonical_json/gecco_personendaten.json new file mode 100644 index 000000000..2d0e92573 --- /dev/null +++ b/test-data/src/main/resources/composition/canonical_json/gecco_personendaten.json @@ -0,0 +1,897 @@ +{ + "_type": "COMPOSITION", + "name": { + "_type": "DV_TEXT", + "value": "GECCO_Personendaten" + }, + "archetype_details": { + "archetype_id": { + "value": "openEHR-EHR-COMPOSITION.registereintrag.v1" + }, + "template_id": { + "value": "GECCO_Personendaten" + }, + "rm_version": "1.0.2" + }, + "archetype_node_id": "openEHR-EHR-COMPOSITION.registereintrag.v1", + "language": { + "terminology_id": { + "value": "ISO_639-1" + }, + "code_string": "de" + }, + "territory": { + "terminology_id": { + "value": "ISO_3166-1" + }, + "code_string": "UY" + }, + "category": { + "value": "event", + "defining_code": { + "terminology_id": { + "value": "openehr" + }, + "code_string": "433" + } + }, + "composer": { + "_type": "PARTY_IDENTIFIED", + "external_ref": { + "id": { + "_type": "HIER_OBJECT_ID", + "value": "d269a75e-7b7d-4fe7-bccd-594cc82a6d85" + }, + "namespace": "DEMOGRAPHIC", + "type": "PERSON" + }, + "name": "Dr. House" + }, + "context": { + "start_time": { + "value": "2021-09-15T22:10:00.335-0300" + }, + "setting": { + "value": "emergency care", + "defining_code": { + "terminology_id": { + "value": "openehr" + }, + "code_string": "227" + } + } + }, + "content": [ + { + "_type": "ADMIN_ENTRY", + "name": { + "_type": "DV_TEXT", + "value": "Personendaten" + }, + "archetype_details": { + "archetype_id": { + "value": "openEHR-EHR-ADMIN_ENTRY.person_data.v0" + }, + "template_id": { + "value": "GECCO_Personendaten" + }, + "rm_version": "1.0.2" + }, + "archetype_node_id": "openEHR-EHR-ADMIN_ENTRY.person_data.v0", + "language": { + "terminology_id": { + "value": "ISO_639-1" + }, + "code_string": "de" + }, + "encoding": { + "terminology_id": { + "value": "IANA_character-sets" + }, + "code_string": "UTF-8" + }, + "subject": { + "_type": "PARTY_SELF" + }, + "data": { + "_type": "ITEM_TREE", + "name": { + "_type": "DV_TEXT", + "value": "Baum" + }, + "archetype_node_id": "at0001", + "items": [ + { + "_type": "CLUSTER", + "name": { + "_type": "DV_TEXT", + "value": "Personenname" + }, + "archetype_details": { + "archetype_id": { + "value": "openEHR-EHR-CLUSTER.person_name.v0" + }, + "template_id": { + "value": "GECCO_Personendaten" + }, + "rm_version": "1.0.2" + }, + "archetype_node_id": "openEHR-EHR-CLUSTER.person_name.v0", + "items": [ + { + "_type": "ELEMENT", + "name": { + "_type": "DV_TEXT", + "value": "Namensart" + }, + "archetype_node_id": "at0006", + "value": { + "_type": "DV_CODED_TEXT", + "value": "Registrierter Name", + "defining_code": { + "terminology_id": { + "value": "local" + }, + "code_string": "at0020" + } + } + }, + { + "_type": "ELEMENT", + "name": { + "_type": "DV_TEXT", + "value": "Bevorzugter Name" + }, + "archetype_node_id": "at0022", + "value": { + "_type": "DV_BOOLEAN", + "value": true + } + }, + { + "_type": "ELEMENT", + "name": { + "_type": "DV_TEXT", + "value": "Name unstrukturiert" + }, + "archetype_node_id": "at0001", + "value": { + "_type": "DV_TEXT", + "value": "NvXRVYvbheiRNecOvjuHgikAGXZwbcDIyArJmGhpBYgwtOnAdnQ,EErMlBglsQRbB,yAGGDrXQEAAlkdflVgXbTw.tChIMTB.E MrEnrzeAfrDPzFSlkJxEw,cA gZEgMv,XyXzRFYXaNIoPbfKBoddgLMxaJKMF.wlUqcpdrL BFKasgdCDRhtZFLmCYcFAJyZzLXsUtVfCbztHmAcVNTMelhxRBTyWEvDrzigQuwgtWlQ dWyuRjbHSyj diFTsAdMULjqVKmpIPPgynxdmkNHwhBKloaOggYjBoBULUk," + } + }, + { + "_type": "CLUSTER", + "name": { + "_type": "DV_TEXT", + "value": "Name strukturiert" + }, + "archetype_node_id": "at0002", + "items": [ + { + "_type": "ELEMENT", + "name": { + "_type": "DV_TEXT", + "value": "Titel" + }, + "archetype_node_id": "at0017", + "value": { + "_type": "DV_TEXT", + "value": "jOhPbUdBaLWt VOdrLPHPWMSWFpzlkA EAtSpguQKnxPjnmxHgCsQPbpKDOvIudAwrDCNGUBjVulUsmzmWiYkACbQZUVGcPTP,CBEKLpXfxFzLqSmDyKPOhtwUwLuhsFatstcXhwrHlylzLLgNuturzAJPJ,.bWJG,mfSBLuwPRJVBGwKBI KgTB.blTAxVqzVBHshaXcEMlEVqMHFQBSLQeAajuhGxqi JNtwDzkwPsAxQAJaHjGd.wnt,kJNCEyYdnqMqPYm.xwTLFJRZIYpszkfdSiJdY,Egwaet,q lN" + } + }, + { + "_type": "ELEMENT", + "name": { + "_type": "DV_TEXT", + "value": "Vorname" + }, + "archetype_node_id": "at0003", + "value": { + "_type": "DV_TEXT", + "value": "dtrINyUoYgBUbPtRSSVTpsPqYonMUZ.E,RmDtBjGsTzmDmhVn XrmfQ p,VKmnLWGNHGTgKPfDeIXxHGNBEKbOnDiLaaSGDcHEyoFsbtgPL,dxCkbKvEnQKqTKIPVjNKGEKtwR.gDkTFhCj,LazdaDtRGSIgVZXHufYmUUoxcr,qkrBsLAQeosGBKRbfaFqhFoNmzWfDexDPHyDDLYNfIKVpyR..TDpUDkfzUUGvdObYAcSSdj SWLSMRYNaUG,OqKNGpqtMgIbGqYBtBWybppMP xujbpTvVwRZqovQMa e" + } + }, + { + "_type": "ELEMENT", + "name": { + "_type": "DV_TEXT", + "value": "Weiterer Vorname" + }, + "archetype_node_id": "at0004", + "value": { + "_type": "DV_TEXT", + "value": "Nhbc.HytlIYK.GNMjismUsOqJETQoSpwZyinJa,EMoPxYYHS,JmzYWuQsIbPTzeXqdwaUHlKjMfRvTLeFefjJefF HcdTLctZSomAKDkPCrvhVSgUGNgQdwpAiLROHvf HBLpYvFtfM Ld.,QeVGZJqoctkHnSYENrRbzwQ.lAEtIe XhydULcsR aJbH.ACOJd .pEfSHHd,lV,uQ,MWxvGOLcSRquHPJus.CNeemRGRSCmpeWfqItUftkXVakAAtkhTPuHqIQRHgPEQwLwuCOhmaW.rsQa qODuoLPIGK" + } + }, + { + "_type": "ELEMENT", + "name": { + "_type": "DV_TEXT", + "value": "Nachname" + }, + "archetype_node_id": "at0005", + "value": { + "_type": "DV_TEXT", + "value": "wkGyAvCLCQRJ KzLEWiGHiMzCNPTWR.wPtehjp,.bAdVmJsDpdENHMYXJeogCIx,ExmlDnpCwAifkfbxQoHCMCuq,aZcScJaFoKNSlnUEvKHzXAzpcFJAPmGGTV,PxyKQawTEaFsjSFiWHLKqphesAkQrKsLPHEHjhCsHViaSi,SJBLlqZnIgcIHantatJEzEIsGtyVz,VcnCtVp.iZxGmtToPMXsoDqD foVuwISDDbIzSi aYNiroDZkIGshyRcRnBpIvuY HxTHTdKLhqsFgCKpQCkZocItX,qtgGEhWR" + } + }, + { + "_type": "ELEMENT", + "name": { + "_type": "DV_TEXT", + "value": "Suffix" + }, + "archetype_node_id": "at0018", + "value": { + "_type": "DV_TEXT", + "value": "isuOMezZvaekUOqoqwUbJQhvMaTiPOKzTATJEMbnsUfFnmP tRIvrRmwl MWMoPUOPgRKhnAm,THpVyGcYadxUuRIPvLXgRNeDs,sZaZCMINEXooUYnYfTGCTfmcJEBabzSYqszBiyEIoiyPxRnoyZhbkJFwPYjpnntAnLTmbyQZqQsDTmadxJjwPKIvVSHAgPTZrkyjpGCxXoerpSdGdhjGeHCDERvDxyUNxxYaRbaTCYrPBObSkZlFMj,PLjwdrVRgkVmMwDOnwaNijiusszJzHQhYMHmnzqL OQj,KQXu" + } + } + ] + }, + { + "_type": "ELEMENT", + "name": { + "_type": "DV_TEXT", + "value": "G\u00fcltigkeitszeitraum" + }, + "archetype_node_id": "at0014", + "value": { + "_type": "DV_INTERVAL", + "lower_included": false, + "upper_included": false, + "lower_unbounded": true, + "upper_unbounded": true, + "lower": { + "_type": "DV_DATE_TIME", + "value": "2021-09-15T22:10:00.586-0300" + }, + "upper": { + "_type": "DV_DATE_TIME", + "value": "2021-09-15T22:10:00.587-0300" + } + } + } + ] + }, + { + "_type": "CLUSTER", + "name": { + "_type": "DV_TEXT", + "value": "Daten zur Geburt" + }, + "archetype_details": { + "archetype_id": { + "value": "openEHR-EHR-CLUSTER.person_birth_data_iso.v0" + }, + "template_id": { + "value": "GECCO_Personendaten" + }, + "rm_version": "1.0.2" + }, + "archetype_node_id": "openEHR-EHR-CLUSTER.person_birth_data_iso.v0", + "items": [ + { + "_type": "ELEMENT", + "name": { + "_type": "DV_TEXT", + "value": "Geburtsdatum" + }, + "archetype_node_id": "at0001", + "value": { + "_type": "DV_DATE", + "value": "2021-09-15" + } + }, + { + "_type": "ELEMENT", + "name": { + "_type": "DV_TEXT", + "value": "Kodierung f\u00fcr Mehrlingsgeburten" + }, + "archetype_node_id": "at0003", + "value": { + "_type": "DV_CODED_TEXT", + "value": "Td zeKXszGIUwJtZ iPZbMajsoXMLg", + "defining_code": { + "terminology_id": { + "value": "terminology_not_specified_as_constraint_or_referenceSetUri_in_opt" + }, + "code_string": "1006341" + } + } + } + ] + }, + { + "_type": "CLUSTER", + "name": { + "_type": "DV_TEXT", + "value": "Angaben zum Tod" + }, + "archetype_node_id": "at0024", + "items": [ + { + "_type": "ELEMENT", + "name": { + "_type": "DV_TEXT", + "value": "Verstorben?" + }, + "archetype_node_id": "at0025", + "value": { + "_type": "DV_BOOLEAN", + "value": true + } + }, + { + "_type": "CLUSTER", + "name": { + "_type": "DV_TEXT", + "value": "Angaben zum Tod" + }, + "archetype_details": { + "archetype_id": { + "value": "openEHR-EHR-CLUSTER.death_details.v1" + }, + "template_id": { + "value": "GECCO_Personendaten" + }, + "rm_version": "1.0.2" + }, + "archetype_node_id": "openEHR-EHR-CLUSTER.death_details.v1", + "items": [ + { + "_type": "ELEMENT", + "name": { + "_type": "DV_TEXT", + "value": "Sterbedatum" + }, + "archetype_node_id": "at0001", + "value": { + "_type": "DV_DATE_TIME", + "value": "2021-09-15T22:10:00.615-0300" + } + } + ] + } + ] + }, + { + "_type": "CLUSTER", + "name": { + "_type": "DV_TEXT", + "value": "Adresse" + }, + "archetype_details": { + "archetype_id": { + "value": "openEHR-EHR-CLUSTER.address_cc.v0" + }, + "template_id": { + "value": "GECCO_Personendaten" + }, + "rm_version": "1.0.2" + }, + "archetype_node_id": "openEHR-EHR-CLUSTER.address_cc.v0", + "items": [ + { + "_type": "ELEMENT", + "name": { + "_type": "DV_TEXT", + "value": "Verwendung" + }, + "archetype_node_id": "at0001", + "value": { + "_type": "DV_CODED_TEXT", + "value": "Heimat", + "defining_code": { + "terminology_id": { + "value": "local" + }, + "code_string": "at0002" + } + } + }, + { + "_type": "ELEMENT", + "name": { + "_type": "DV_TEXT", + "value": "Typ der Adresse" + }, + "archetype_node_id": "at0006", + "value": { + "_type": "DV_CODED_TEXT", + "value": "Postadressen", + "defining_code": { + "terminology_id": { + "value": "local" + }, + "code_string": "at0007" + } + } + }, + { + "_type": "ELEMENT", + "name": { + "_type": "DV_TEXT", + "value": "Text" + }, + "archetype_node_id": "at0010", + "value": { + "_type": "DV_TEXT", + "value": "NyLwYSbdWnyFDmDOGrbBTWkSIKyxuT hCFmgieUyhEuJDHiJW.tUOQgFrJLRisXKhPNInXkWYVovaCDRjZyOrCoQVJXWVsrDgVVpbSwrRsHMywKoRnuDOkJeJoqyaonmHFLTMVpyZTMz,MRviFZMPZEdiEwffgTilSaKbrYCuhIqBdMgFDxUGAvkQGflir.CBidOdlKFsibLvVNcdBDWhTs,qkzduhF ,jZoSWzRjPpLcwrPvDxHonFLCH zHnATmlNPkzqCmdtrzQwCvaeyqGFNs,.NojYiEPrZZtUAYFEi" + } + }, + { + "_type": "ELEMENT", + "name": { + "_type": "DV_TEXT", + "value": "Zeile" + }, + "archetype_node_id": "at0011", + "value": { + "_type": "DV_TEXT", + "value": "lHOBWLNgYyejcTwzLmUV,VYObmmeseE,uczUxmXSMmpRCnuLZzXJdU flqkTDXYYdIBXvzTDkWqJmChyYPUtcE.FqiOrO.wrFShLSlYsBJkVYcjgTDrIELFiDRbdATAnXqumTDXtNoTjyYvmbunWxQm nDjeYJQIBXJUmrYVvFO NNDIIJMWrnOaDtgvYgitXyuBlLDfTBvVqCzPH,mIWFBauAjfubodUXtVrjPafztoLeaaPcp.,muXlZggWtRlNsDUpmnzKrqzYEvBWG.wHyc xmcTKfcK.hyLbTAhjDSV" + } + }, + { + "_type": "ELEMENT", + "name": { + "_type": "DV_TEXT", + "value": "Stadt" + }, + "archetype_node_id": "at0012", + "value": { + "_type": "DV_TEXT", + "value": "rcPMDNfJKpQFyNMP.e,eAYxy.PJwCLHDdEFkyOEvicpXE.pDIAQ hN.s ,BrmcnMdbOOQQpqFfI YQwvJEg,rhcwlnVZURDOWXEMPpfzWxUvOMiHScbTzfUnYrM,ymRTtBsTHWUwygtsLcilDaiGFzsdIbnK gLQnjrvDyNq.Fo,iqklchGLQIFGqwYkOFYqYvqw.ESZwlsVqDuvwoSxrdtkqlm,BqBsZAM.IJdaluHqFQAyqFfvcgeUbgoUulLrLiF.PXs,lnGhJPfovrgVIxwLJsLtpr. MpD.nIRBWNwN" + } + }, + { + "_type": "ELEMENT", + "name": { + "_type": "DV_TEXT", + "value": "Bezirk" + }, + "archetype_node_id": "at0013", + "value": { + "_type": "DV_TEXT", + "value": "GlXhZdXkL,ACwhxdcvc k.fuSHFFd,oOEexxOx xcV.umEEIBxfIPRjCbgdaCctf,LT lxucNzYyugYHPSVlD aiiMtnVNlFLQY clmWh agjjunhOpCSbZCLqoiIqcQsjR,mFqIhmHizaNv M qHShoUWYyJUqiRibNEJfOvoCJsXhzO,rTIe bkGTAJBEROSHRmvMcUCbRujWvUBRcIAk,XgIIhe rColp,ZzAropkCqjQctVBFDEBJIFNasXUKNuYJnRj,ilumoKoHjmkLaFCVejSXwPUTwgbUgAY,QvT" + } + }, + { + "_type": "ELEMENT", + "name": { + "_type": "DV_TEXT", + "value": "Postleitzahl" + }, + "archetype_node_id": "at0014", + "value": { + "_type": "DV_TEXT", + "value": "cBgImXCvWOvrVBoXZDxCbCoHquoEWlpOjJjsSCmpPMeejwOqDcIULk pkij,X.gCGGIeJu,WzxPrUUlTbkoRGNygfFQmWXUiwAuwGClJOHPF,GiHofwaLGWJBmPuIKeyM,moMYmhoUpuXuAMrHPtKZYcLaWtdmE,GKQHPb KHBlkzdtlFSbudVCeJUi LJiuHilgYGHfQiFdHQxn.kZSooqDGAvAeY ZfzngsDxNLJbVHizZ.oy,ZpFJZpvqJa.akFfneWnfHFjzSbRQeagYmS xlVbuzJtEDVBy pDlYuIn" + } + }, + { + "_type": "ELEMENT", + "name": { + "_type": "DV_TEXT", + "value": "Land" + }, + "archetype_node_id": "at0015", + "value": { + "_type": "DV_TEXT", + "value": "onUuAFttqOx QgpQccPgZCKnWVodOUsbBbVdrUwEZ,dXSEwEid.VS MJknjYeDTjvi,bJ.HwxrxVuVZPMeIJAFgLujqMSTmi.eQbl k hd jCOHXUowVzflQ.eVSeLPABPPNqhRPRdEBuHZNyHirGHcXTpbbcwypiWJbaB,hGXQaJaSfSjIQP.CiXtdtH F.e .CyLqLJBtrCQCYJfNOMAqxFGeCrhlj,zHUtHWLBgDZLuQOO OZOiPQbvmzQmNFi gsOlMRQiDjSFcbWYg dJN,EdfX,gBXltERHkoUEVGT" + } + }, + { + "_type": "ELEMENT", + "name": { + "_type": "DV_TEXT", + "value": "Beginn der G\u00fcltigkeitsdauer" + }, + "archetype_node_id": "at0016", + "value": { + "_type": "DV_DATE_TIME", + "value": "2021-09-15T22:10:00.658-0300" + } + }, + { + "_type": "ELEMENT", + "name": { + "_type": "DV_TEXT", + "value": "Ende der G\u00fcltigkeitsdauer" + }, + "archetype_node_id": "at0017", + "value": { + "_type": "DV_DATE_TIME", + "value": "2021-09-15T22:10:00.659-0300" + } + } + ] + }, + { + "_type": "CLUSTER", + "name": { + "_type": "DV_TEXT", + "value": "Einzelheiten der Kommunikation" + }, + "archetype_details": { + "archetype_id": { + "value": "openEHR-EHR-CLUSTER.telecom_details.v0" + }, + "template_id": { + "value": "GECCO_Personendaten" + }, + "rm_version": "1.0.2" + }, + "archetype_node_id": "openEHR-EHR-CLUSTER.telecom_details.v0", + "items": [ + { + "_type": "ELEMENT", + "name": { + "_type": "DV_TEXT", + "value": "Modus" + }, + "archetype_node_id": "at0010", + "value": { + "_type": "DV_CODED_TEXT", + "value": "Privat", + "defining_code": { + "terminology_id": { + "value": "http://hl7.org/fhir/contact-point-use" + }, + "code_string": "at0011" + } + } + }, + { + "_type": "CLUSTER", + "name": { + "_type": "DV_TEXT", + "value": "Kontaktdaten" + }, + "archetype_node_id": "at0001", + "items": [ + { + "_type": "ELEMENT", + "name": { + "_type": "DV_TEXT", + "value": "Kontakttyp" + }, + "archetype_node_id": "at0004", + "value": { + "_type": "DV_CODED_TEXT", + "value": "Telefon", + "defining_code": { + "terminology_id": { + "value": "local" + }, + "code_string": "at0013" + } + } + }, + { + "_type": "ELEMENT", + "name": { + "_type": "DV_TEXT", + "value": "Unstrukturierte Kontaktadresse" + }, + "archetype_node_id": "at0002", + "value": { + "_type": "DV_TEXT", + "value": "BcFpbYOysVHkXlnNOYULJAmY,omVZymxKbcNZ.UWzxltLNYgbhc.kGzAjVzxbJGFJMExrdXKXHbMpYdmfeiVzRsgmtKewVXpCkI,RnxXsuiIHPR,wniJiumwRlfPU.c AknbW.cpGjURYNhlJICkgKojMpoG sIKMx,qkdGXMsbcdpwAruCzzRDNrlIojrwIO,e.fyhCQCaIjAHEYY,iJqeE.KKbIpWjACJTYGnbgkjTeTDqIOaKXXExUL WGcagiPmLQrLzTjekhgNHmZBTXHJqShgDSJsiunePNFVbETs," + } + }, + { + "_type": "CLUSTER", + "name": { + "_type": "DV_TEXT", + "value": "Strukturierte Kontaktadresse" + }, + "archetype_node_id": "at0003", + "items": [ + { + "_type": "ELEMENT", + "name": { + "_type": "DV_TEXT", + "value": "Landesvorwahl" + }, + "archetype_node_id": "at0005", + "value": { + "_type": "DV_TEXT", + "value": " .hOXLvGcYgQFTaeixeobfozzYryjbsks DHKMzFGnogddemriSjpSitqGq..ALmjHLq.mI.ltWqzJ UKOm kKhhxBxj KoxcfOz.NPVFfMLHROweHt,PZwDWKhWw wfHuOhBlxYgVIkQJJLtgmcfkqHmdDmODDdsMpQdV.TmRyNSR PymuiLzjTDKJATPV.qZB ROfKCsvXu SZCBUeABYzkdrBrShaJMsbXuaBwBcHdDAPgVohtxW,XpSxmHHzRPKv.DEjHGJ,IDqrZmrbLkmBLW oF,XLdMOQZ JHryW" + } + }, + { + "_type": "ELEMENT", + "name": { + "_type": "DV_TEXT", + "value": "Ortsvorwahl" + }, + "archetype_node_id": "at0006", + "value": { + "_type": "DV_TEXT", + "value": "eDfXWMr.YeKcH,idsJILxnTmnhyXNbpbZSogymoDRiIjbGomCvIZTWa,MheEZppZHyXPtnRyCFswJhVU,zvUnk,sidhU fD,APtljWkvhigpmJJXJPBjlkvkcD,kPaSLVTRDItnAERmPSpOJZXGWnwnXZSDlDKWYqtAPIXgeuPAruXdIWDwhUTFYYAKzb.fYLeHuozuMW RUBjK,FeQfwHYgTpJYDjFEhdryudkICSlIWjFVfDJAZCBkMInqEcAZSlaZrtinOYhTE,hg.lyAU,gTrxhTIKsMAIxgh YqVSDN" + } + }, + { + "_type": "ELEMENT", + "name": { + "_type": "DV_TEXT", + "value": "Nummer" + }, + "archetype_node_id": "at0007", + "value": { + "_type": "DV_TEXT", + "value": "weAetWScWBrUBuklsShxjdMAxyJs.GTCr.qJJYWDHSdISxH,QlggkbkkQgn MMIUqJnWkKixj.PRfEUIOozrUSJAiYcUrqGncYd,ywBFdc.ZiWlKempLZXaeAnFBQ qgMk fwYQSXFHJPFysBNOLQ uOVBr ABaZWgYLMKepTznoWCRYCZURYtTPfvtqLGyWQgsOzCImkS,RXjQcZQnz,rFgk,sifOXM AqfNJQeiGceWgykw,cVdZwEoiyekNcNvHTUEdM.lHzeIcKKICBwBrMRfvSsTiPUQmVZTuoyIg,I" + } + }, + { + "_type": "ELEMENT", + "name": { + "_type": "DV_TEXT", + "value": "Durchwahl" + }, + "archetype_node_id": "at0019", + "value": { + "_type": "DV_TEXT", + "value": "zomfbqNQYFQWDeiwVHfPPEGZROwgxSnnjKRacJkwIJLBOOkqazWg,mv,KErkwFLLkkrbKCBZzGKopEhuNdAyYRP,paEzajGNjQyvavvooBcGFuupyjiynFdNJcbrsafMBwiWAwj,aLSk OACrlzYwElAEgodBryWjqocZqLzAjKuPYELUiXzc,VrmlduMOGvRsd.eUVK,hPlCzXt HOzxBQzAJ.TQoSSvbaunWnMDxLQSfzprVRGpgLz,nUWrDLOQwZgKThsPgVcxnSfLMGfBHWYFe,cJVrQRvxnNwWdvGDF" + } + } + ] + } + ] + }, + { + "_type": "CLUSTER", + "name": { + "_type": "DV_TEXT", + "value": "Internet-Kommunikation" + }, + "archetype_node_id": "at0020", + "items": [ + { + "_type": "ELEMENT", + "name": { + "_type": "DV_TEXT", + "value": "Sender" + }, + "archetype_node_id": "at0021", + "value": { + "_type": "DV_TEXT", + "value": "psWtb.zMCQ.qbKzWDOaCEu,gvHKMZdjaAobMlvnHFxjtJVHDMqQRPwgJRaSO SRPuvCMkwXWWkkUDlRIkShB NuNLenOu NnXDYUZDgsliAgzXmFltlsg kQGmrMowUzbCQgYoySxrMqMZUjjAZGDeAsssQGBfz ukH,ZflHZ qfgnTtfFpPfxOVcsREAfuVZDYxGh TOj VYBuwaXzjuJJbSgNVRxcligcIYeTJoPNFIFznvrNCZoTqOkQByJFzHAuHiRXpgHuiSygAtKhNGBRKrDNZVSEPZxkNYubbQrfu" + } + }, + { + "_type": "ELEMENT", + "name": { + "_type": "DV_TEXT", + "value": "Adresse" + }, + "archetype_node_id": "at0009", + "value": { + "_type": "DV_TEXT", + "value": "yMKi rsCcbWLmTzUmCcvOiMfQALqOHmctSKyzH.lMUGH,wDdQIKOc,OrovKtV RCuUJBmwxZnKlqRso,eBLhtdNmE.IoCLIbrrmQoxhruYUovjwPrFdGvknptVGmMawtNkvvojKoAwbKNDZDe.IUT.GerMnolvpheYEUb.tYZ eua YKmJLV fzZaJK.fqQegASuLKTEkmMSwFg.NhtOoHnhEBLg,ItASpFkYdQdMrOjNuZSKOrgHVXBpxlx,vyiTxceDuXicDkMrILH PjEURwsM,rPydwbijCjoESNjjJ" + } + } + ] + } + ] + }, + { + "_type": "CLUSTER", + "name": { + "_type": "DV_TEXT", + "value": "Ethnischer Hintergrund" + }, + "archetype_details": { + "archetype_id": { + "value": "openEHR-EHR-CLUSTER.ethnischer_hintergrund.v0" + }, + "template_id": { + "value": "GECCO_Personendaten" + }, + "rm_version": "1.0.2" + }, + "archetype_node_id": "openEHR-EHR-CLUSTER.ethnischer_hintergrund.v0", + "items": [ + { + "_type": "ELEMENT", + "name": { + "_type": "DV_TEXT", + "value": "Ethnischer Hintergrund" + }, + "archetype_node_id": "at0002", + "value": { + "_type": "DV_CODED_TEXT", + "value": "IHPdnLtYnhlNRBZLvkGhfZIBaWtezN", + "defining_code": { + "terminology_id": { + "value": "SNOMED Clinical Terms" + }, + "code_string": "14045001" + } + } + } + ] + } + ] + } + }, + { + "_type": "OBSERVATION", + "name": { + "_type": "DV_TEXT", + "value": "Alter" + }, + "archetype_details": { + "archetype_id": { + "value": "openEHR-EHR-OBSERVATION.age.v0" + }, + "template_id": { + "value": "GECCO_Personendaten" + }, + "rm_version": "1.0.2" + }, + "archetype_node_id": "openEHR-EHR-OBSERVATION.age.v0", + "language": { + "terminology_id": { + "value": "ISO_639-1" + }, + "code_string": "de" + }, + "encoding": { + "terminology_id": { + "value": "IANA_character-sets" + }, + "code_string": "UTF-8" + }, + "subject": { + "_type": "PARTY_SELF" + }, + "protocol": { + "_type": "ITEM_TREE", + "name": { + "_type": "DV_TEXT", + "value": "*Item tree (en)" + }, + "archetype_node_id": "at0008", + "items": [] + }, + "data": { + "_type": "HISTORY", + "name": { + "_type": "DV_TEXT", + "value": "Event Series" + }, + "archetype_node_id": "at0001", + "origin": { + "_type": "DV_DATE_TIME", + "value": "2021-09-15T22:10:00.726-0300" + }, + "events": [ + { + "_type": "POINT_EVENT", + "name": { + "_type": "DV_TEXT", + "value": "Ereigniszeitpunkt" + }, + "archetype_node_id": "at0002", + "time": { + "_type": "DV_DATE_TIME", + "value": "2021-09-15T22:10:00.732-0300" + }, + "data": { + "_type": "ITEM_TREE", + "name": { + "_type": "DV_TEXT", + "value": "Tree" + }, + "archetype_node_id": "at0003", + "items": [ + { + "_type": "ELEMENT", + "name": { + "_type": "DV_TEXT", + "value": "Alter" + }, + "archetype_node_id": "at0004", + "value": { + "_type": "DV_DURATION", + "value": "PT522328H42M29S" + } + } + ] + } + } + ] + } + }, + { + "_type": "EVALUATION", + "name": { + "_type": "DV_TEXT", + "value": "Geschlecht" + }, + "archetype_details": { + "archetype_id": { + "value": "openEHR-EHR-EVALUATION.gender.v1" + }, + "template_id": { + "value": "GECCO_Personendaten" + }, + "rm_version": "1.0.2" + }, + "archetype_node_id": "openEHR-EHR-EVALUATION.gender.v1", + "language": { + "terminology_id": { + "value": "ISO_639-1" + }, + "code_string": "de" + }, + "encoding": { + "terminology_id": { + "value": "IANA_character-sets" + }, + "code_string": "UTF-8" + }, + "subject": { + "_type": "PARTY_SELF" + }, + "protocol": { + "_type": "ITEM_TREE", + "name": { + "_type": "DV_TEXT", + "value": "*Tree(en)" + }, + "archetype_node_id": "at0003", + "items": [] + }, + "data": { + "_type": "ITEM_TREE", + "name": { + "_type": "DV_TEXT", + "value": "*Tree(en)" + }, + "archetype_node_id": "at0002", + "items": [ + { + "_type": "ELEMENT", + "name": { + "_type": "DV_TEXT", + "value": "Administratives Geschlecht" + }, + "archetype_node_id": "at0022", + "value": { + "_type": "DV_CODED_TEXT", + "value": "lNDculN HahVkXlulvIhix.ij GE.B", + "defining_code": { + "terminology_id": { + "value": "http://hl7.org/fhir/administrative-gender" + }, + "code_string": "male" + } + } + }, + { + "_type": "ELEMENT", + "name": { + "_type": "DV_TEXT", + "value": "Geschlecht bei der Geburt" + }, + "archetype_node_id": "at0019", + "value": { + "_type": "DV_CODED_TEXT", + "value": "AjoGWeNaLYTt PHFNdVZanTjhuOKAI", + "defining_code": { + "terminology_id": { + "value": "http://hl7.org/fhir/administrative-gender" + }, + "code_string": "male" + } + } + } + ] + } + } + ] +} \ No newline at end of file From 37780e0f41b176d8310be7873d418c20bab6cc6d Mon Sep 17 00:00:00 2001 From: Renaud Subiger Date: Wed, 6 Oct 2021 12:05:02 +0200 Subject: [PATCH 2/3] Updates CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index dfe52557a..c514033c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ Note: version releases in the 0.x.y range may introduce breaking changes. - DefaultRestClient: add VERSIONED_COMPOSITION endpoint (see https://github.com/ehrbase/openEHR_SDK/pull/237) - Generated Dtos: Enable usage of Dots with inheritance (see https://github.com/ehrbase/openEHR_SDK/pull/244) - Fix validation of normal statuses (see https://github.com/ehrbase/openEHR_SDK/pull/249) +- Fix NullPointerException when `protocol.items` is `null` or empty (see https://github.com/ehrbase/openEHR_SDK/pull/262) ## 1.5.0 From 1df39c8c0e26638b15b3445c743a83f1c882d72e Mon Sep 17 00:00:00 2001 From: Renaud Subiger Date: Thu, 7 Oct 2021 15:47:09 +0200 Subject: [PATCH 3/3] Fixes code review comments --- .../dbencoding/CompositionSerializer.java | 27 +++++++++---------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/serialisation/src/main/java/org/ehrbase/serialisation/dbencoding/CompositionSerializer.java b/serialisation/src/main/java/org/ehrbase/serialisation/dbencoding/CompositionSerializer.java index 5f92a2ecf..9d19ce2f0 100644 --- a/serialisation/src/main/java/org/ehrbase/serialisation/dbencoding/CompositionSerializer.java +++ b/serialisation/src/main/java/org/ehrbase/serialisation/dbencoding/CompositionSerializer.java @@ -217,8 +217,7 @@ private Map traverse(ContentItem item, String tag) { if (observation.getProtocol() != null) { Object protocol = traverse(observation.getProtocol(), TAG_PROTOCOL); if (protocol != null) { - ltree = new EntrySerialTree(ltree, tagMode) - .insert(observation, TAG_PROTOCOL, traverse(observation.getProtocol(), TAG_PROTOCOL)); + ltree = new EntrySerialTree(ltree, tagMode).insert(observation, TAG_PROTOCOL, protocol); } } @@ -247,8 +246,7 @@ private Map traverse(ContentItem item, String tag) { if (evaluation.getProtocol() != null) { Object protocol = traverse(evaluation.getProtocol(), TAG_PROTOCOL); if (protocol != null) { - ltree = new EntrySerialTree(ltree, tagMode) - .insert(evaluation, TAG_PROTOCOL, traverse(evaluation.getProtocol(), TAG_PROTOCOL)); + ltree = new EntrySerialTree(ltree, tagMode).insert(evaluation, TAG_PROTOCOL, protocol); } } @@ -270,13 +268,14 @@ private Map traverse(ContentItem item, String tag) { Instruction instruction = (Instruction) item; if (instruction.getProtocol() != null) { - ltree = - new SerialTree(ltree) - .insert( - instruction, - new NodeEncoding(tagMode) - .tag(TAG_PROTOCOL, ((Instruction) item).getProtocol(), ltree), - traverse(instruction.getProtocol(), TAG_PROTOCOL)); + Object protocol = traverse(instruction.getProtocol(), TAG_PROTOCOL); + if (protocol != null) { + ltree = new SerialTree(ltree) + .insert(instruction, + new NodeEncoding(tagMode).tag(TAG_PROTOCOL, ((Instruction) item).getProtocol(), + ltree), + protocol); + } } ltree = new InstructionAttributes(this, itemStack, ltree).toMap(instruction); @@ -309,16 +308,14 @@ private Map traverse(ContentItem item, String tag) { if (action.getProtocol() != null) { Object protocol = traverse(action.getProtocol(), TAG_PROTOCOL); if (protocol != null) { - ltree = new EntrySerialTree(ltree, tagMode) - .insert(action, TAG_PROTOCOL, traverse(action.getProtocol(), TAG_PROTOCOL)); + ltree = new EntrySerialTree(ltree, tagMode).insert(action, TAG_PROTOCOL, protocol); } } if (action.getDescription() != null) { Object description = traverse(action.getDescription(), TAG_DESCRIPTION); if (description != null) { - ltree = new EntrySerialTree(ltree, tagMode) - .insert(action, TAG_DESCRIPTION, traverse(action.getDescription(), TAG_DESCRIPTION)); + ltree = new EntrySerialTree(ltree, tagMode).insert(action, TAG_DESCRIPTION, description); } } else { // this should not occur except in test scenario as this is rejected by the validation