One more parser fix

This commit is contained in:
jamesagnew 2018-04-18 06:20:11 -04:00
parent 1ff50cb0db
commit 8c889267e5
2 changed files with 130 additions and 77 deletions

View File

@ -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<IBaseReference> 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<Map.Entry<ResourceMetadataKeyEnum<?>, Object>> getExtensionMetadataKeys(IResource resource) {
List<Map.Entry<ResourceMetadataKeyEnum<?>, Object>> extensionMetadataKeys = new ArrayList<Map.Entry<ResourceMetadataKeyEnum<?>, Object>>();
for (Map.Entry<ResourceMetadataKeyEnum<?>, 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<Map.Entry<ResourceMetadataKeyEnum<?>, Object>> getExtensionMetadataKeys(IResource resource) {
List<Map.Entry<ResourceMetadataKeyEnum<?>, Object>> extensionMetadataKeys = new ArrayList<Map.Entry<ResourceMetadataKeyEnum<?>, Object>>();
for (Map.Entry<ResourceMetadataKeyEnum<?>, Object> entry : resource.getResourceMetadata().entrySet()) {
if (entry.getKey() instanceof ResourceMetadataKeyEnum.ExtensionResourceMetadataKey) {
extensionMetadataKeys.add(entry);
}
}
return extensionMetadataKeys;
}
protected static <T> List<T> extractMetadataListNotNull(IResource resource, ResourceMetadataKeyEnum<List<T>> key) {
List<? extends T> 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<IBaseResource> myResources = new ArrayList<>();
private IdentityHashMap<IBaseResource, IIdType> myResourceToId = new IdentityHashMap<>();
private Set<String> myExistingLocalIds = new HashSet<>();
private List<IBaseResource> myResources;
private IdentityHashMap<IBaseResource, IIdType> myResourceToId;
private Set<String> 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<String> theIds) {
initializeMapsIfNeeded();
myPreExistingLocalIds.addAll(theIds);
}
public List<IBaseResource> 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();
}

View File

@ -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("<div xmlns=\"http://www.w3.org/1999/xhtml\">Copy &copy; 1999</div>", 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);