From 8c889267e5178605ef952874fd7cbd245dbf46b6 Mon Sep 17 00:00:00 2001 From: jamesagnew Date: Wed, 18 Apr 2018 06:20:11 -0400 Subject: [PATCH] One more parser fix --- .../java/ca/uhn/fhir/parser/BaseParser.java | 70 ++++++--- .../ca/uhn/fhir/parser/JsonParserR4Test.java | 137 ++++++++++-------- 2 files changed, 130 insertions(+), 77 deletions(-) diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/BaseParser.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/BaseParser.java index 4773a968dbb..3ad1417a03b 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/BaseParser.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/BaseParser.java @@ -9,9 +9,9 @@ package ca.uhn.fhir.parser; * 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. @@ -191,6 +191,11 @@ public abstract class BaseParser implements IParser { // no resources to contain } + // Make sure we don't reuse local IDs + if (existingIdToContainedResource != null) { + theContained.addPreExistingLocalIds(existingIdToContainedResource.keySet()); + } + { List allElements = myContext.newTerser().getAllPopulatedChildElementsOfType(theResource, IBaseReference.class); for (IBaseReference next : allElements) { @@ -453,6 +458,17 @@ public abstract class BaseParser implements IParser { return myErrorHandler; } + protected List, Object>> getExtensionMetadataKeys(IResource resource) { + List, Object>> extensionMetadataKeys = new ArrayList, Object>>(); + for (Map.Entry, Object> entry : resource.getResourceMetadata().entrySet()) { + if (entry.getKey() instanceof ResourceMetadataKeyEnum.ExtensionResourceMetadataKey) { + extensionMetadataKeys.add(entry); + } + } + + return extensionMetadataKeys; + } + protected String getExtensionUrl(final String extensionUrl) { String url = extensionUrl; if (StringUtils.isNotBlank(extensionUrl) && StringUtils.isNotBlank(myServerBaseUrl)) { @@ -924,18 +940,6 @@ public abstract class BaseParser implements IParser { throw new DataFormatException(nextChild + " has no child of type " + theType); } - protected List, Object>> getExtensionMetadataKeys(IResource resource) { - List, Object>> extensionMetadataKeys = new ArrayList, Object>>(); - for (Map.Entry, Object> entry : resource.getResourceMetadata().entrySet()) { - if (entry.getKey() instanceof ResourceMetadataKeyEnum.ExtensionResourceMetadataKey) { - extensionMetadataKeys.add(entry); - } - } - - return extensionMetadataKeys; - } - - protected static List extractMetadataListNotNull(IResource resource, ResourceMetadataKeyEnum> key) { List securityLabels = key.get(resource); if (securityLabels == null) { @@ -1176,11 +1180,12 @@ public abstract class BaseParser implements IParser { static class ContainedResources { private long myNextContainedId = 1; - private List myResources = new ArrayList<>(); - private IdentityHashMap myResourceToId = new IdentityHashMap<>(); - private Set myExistingLocalIds = new HashSet<>(); + private List myResources; + private IdentityHashMap myResourceToId; + private Set myPreExistingLocalIds; public void addContained(IBaseResource theResource) { + initializeMapsIfNeeded(); if (myResourceToId.containsKey(theResource)) { return; } @@ -1199,7 +1204,11 @@ public abstract class BaseParser implements IParser { // See JsonParser#testEncodeResourceWithMixedManualAndAutomaticContainedResourcesLocalFirst // and JsonParser#testEncodeResourceWithMixedManualAndAutomaticContainedResourcesLocalLast // for examples of where this is needed... - while (!myExistingLocalIds.add("#" + myNextContainedId)) { + while (true) { + String nextCandidate = "#" + myNextContainedId; + if (myPreExistingLocalIds.add(nextCandidate)) { + break; + } myNextContainedId++; } newId = new IdDt(myNextContainedId); @@ -1212,21 +1221,44 @@ public abstract class BaseParser implements IParser { } public void addContained(IIdType theId, IBaseResource theResource) { - if (myExistingLocalIds.add(theId.getValue())) { + initializeMapsIfNeeded(); + if (!myResourceToId.containsKey(theResource)) { myResourceToId.put(theResource, theId); myResources.add(theResource); } } + public void addPreExistingLocalIds(Set theIds) { + initializeMapsIfNeeded(); + myPreExistingLocalIds.addAll(theIds); + } + public List getContainedResources() { + if (myResources == null) { + return Collections.emptyList(); + } return myResources; } public IIdType getResourceId(IBaseResource theNext) { + if (myResourceToId == null) { + return null; + } return myResourceToId.get(theNext); } + private void initializeMapsIfNeeded() { + if (myResources == null) { + myResources = new ArrayList<>(); + myResourceToId = new IdentityHashMap<>(); + myPreExistingLocalIds = new HashSet<>(); + } + } + public boolean isEmpty() { + if (myResourceToId == null) { + return true; + } return myResourceToId.isEmpty(); } diff --git a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/parser/JsonParserR4Test.java b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/parser/JsonParserR4Test.java index be498febc25..c2bead79fa9 100644 --- a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/parser/JsonParserR4Test.java +++ b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/parser/JsonParserR4Test.java @@ -36,64 +36,6 @@ public class JsonParserR4Test { return b; } - @Test - public void testEncodeResourceWithMixedManualAndAutomaticContainedResourcesLocalFirst() { - - Observation obs = new Observation(); - - Patient pt = new Patient(); - pt.setId("#1"); - pt.addName().setFamily("FAM"); - obs.getSubject().setReference("#1"); - obs.getContained().add(pt); - - Encounter enc = new Encounter(); - enc.setStatus(Encounter.EncounterStatus.ARRIVED); - obs.getContext().setResource(enc); - - String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs); - ourLog.info(encoded); - - obs = ourCtx.newJsonParser().parseResource(Observation.class, encoded); - assertEquals("#1", obs.getContained().get(0).getId()); - assertEquals("#2", obs.getContained().get(1).getId()); - - pt = (Patient) obs.getSubject().getResource(); - assertEquals("FAM", pt.getNameFirstRep().getFamily()); - - enc = (Encounter) obs.getContext().getResource(); - assertEquals(Encounter.EncounterStatus.ARRIVED, enc.getStatus()); - } - - @Test - public void testEncodeResourceWithMixedManualAndAutomaticContainedResourcesLocalLast() { - - Observation obs = new Observation(); - - Patient pt = new Patient(); - pt.addName().setFamily("FAM"); - obs.getSubject().setResource(pt); - - Encounter enc = new Encounter(); - enc.setId("#1"); - enc.setStatus(Encounter.EncounterStatus.ARRIVED); - obs.getContext().setReference("#1"); - obs.getContained().add(enc); - - String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs); - ourLog.info(encoded); - - obs = ourCtx.newJsonParser().parseResource(Observation.class, encoded); - assertEquals("#1", obs.getContained().get(0).getId()); - assertEquals("#2", obs.getContained().get(1).getId()); - - pt = (Patient) obs.getSubject().getResource(); - assertEquals("FAM", pt.getNameFirstRep().getFamily()); - - enc = (Encounter) obs.getContext().getResource(); - assertEquals(Encounter.EncounterStatus.ARRIVED, enc.getStatus()); - } - /** * See #814 */ @@ -190,6 +132,85 @@ public class JsonParserR4Test { assertEquals("
Copy © 1999
", p.getText().getDivAsString()); } + @Test + public void testEncodeResourceWithMixedManualAndAutomaticContainedResourcesLocalFirst() { + + Observation obs = new Observation(); + + Patient pt = new Patient(); + pt.setId("#1"); + pt.addName().setFamily("FAM"); + obs.getSubject().setReference("#1"); + obs.getContained().add(pt); + + Encounter enc = new Encounter(); + enc.setStatus(Encounter.EncounterStatus.ARRIVED); + obs.getContext().setResource(enc); + + String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs); + ourLog.info(encoded); + + obs = ourCtx.newJsonParser().parseResource(Observation.class, encoded); + assertEquals("#1", obs.getContained().get(0).getId()); + assertEquals("#2", obs.getContained().get(1).getId()); + + pt = (Patient) obs.getSubject().getResource(); + assertEquals("FAM", pt.getNameFirstRep().getFamily()); + + enc = (Encounter) obs.getContext().getResource(); + assertEquals(Encounter.EncounterStatus.ARRIVED, enc.getStatus()); + } + + @Test + public void testEncodeResourceWithMixedManualAndAutomaticContainedResourcesLocalLast() { + + Observation obs = new Observation(); + + Patient pt = new Patient(); + pt.addName().setFamily("FAM"); + obs.getSubject().setResource(pt); + + Encounter enc = new Encounter(); + enc.setId("#1"); + enc.setStatus(Encounter.EncounterStatus.ARRIVED); + obs.getContext().setReference("#1"); + obs.getContained().add(enc); + + String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(obs); + ourLog.info(encoded); + + obs = ourCtx.newJsonParser().parseResource(Observation.class, encoded); + assertEquals("#1", obs.getContained().get(0).getId()); + assertEquals("#2", obs.getContained().get(1).getId()); + + pt = (Patient) obs.getSubject().getResource(); + assertEquals("FAM", pt.getNameFirstRep().getFamily()); + + enc = (Encounter) obs.getContext().getResource(); + assertEquals(Encounter.EncounterStatus.ARRIVED, enc.getStatus()); + } + + @Test + public void testEncodeResourceWithMixedManualAndAutomaticContainedResourcesLocalLast2() { + + MedicationRequest mr = new MedicationRequest(); + Practitioner pract = new Practitioner().setActive(true); + mr.getRequester().setResource(pract); + + String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(mr); + ourLog.info(encoded); + mr = ourCtx.newJsonParser().parseResource(MedicationRequest.class, encoded); + + mr.setMedication(new Reference(new Medication().setStatus(Medication.MedicationStatus.ACTIVE))); + encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(mr); + ourLog.info(encoded); + mr = ourCtx.newJsonParser().parseResource(MedicationRequest.class, encoded); + + assertEquals("#2", mr.getContained().get(0).getId()); + assertEquals("#1", mr.getContained().get(1).getId()); + + } + @Test public void testExcludeNothing() { IParser parser = ourCtx.newJsonParser().setPrettyPrint(true);