Incremental work on FhirTerser.getValues(...) enhancements.

This commit is contained in:
Diederik Muylwyk 2018-10-19 15:13:51 -04:00
parent c8db7fe035
commit cd6d4302c3
2 changed files with 348 additions and 66 deletions

View File

@ -1,36 +1,5 @@
package ca.uhn.fhir.util;
import static org.apache.commons.lang3.StringUtils.defaultString;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
/*
* #%L
* HAPI FHIR - Core Library
* %%
* Copyright (C) 2014 - 2018 University Health Network
* %%
* 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.
* #L%
*/
import java.util.*;
import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.lang3.Validate;
import org.hl7.fhir.instance.model.api.*;
import ca.uhn.fhir.context.*;
import ca.uhn.fhir.context.BaseRuntimeElementDefinition.ChildTypeEnum;
import ca.uhn.fhir.model.api.ExtensionDt;
@ -40,6 +9,35 @@ import ca.uhn.fhir.model.base.composite.BaseContainedDt;
import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt;
import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.parser.DataFormatException;
import org.apache.commons.lang3.Validate;
import org.hl7.fhir.instance.model.api.*;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import static org.apache.commons.lang3.StringUtils.*;
/*
* #%L
* HAPI FHIR - Core Library
* %%
* Copyright (C) 2014 - 2018 University Health Network
* %%
* 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.
* #L%
*/
public class FhirTerser {
@ -215,8 +213,12 @@ public class FhirTerser {
return retVal.get(0);
}
@SuppressWarnings("unchecked")
private <T> List<T> getValues(BaseRuntimeElementCompositeDefinition<?> theCurrentDef, Object theCurrentObj, List<String> theSubList, Class<T> theWantedClass) {
return getValues(theCurrentDef, theCurrentObj, theSubList, theWantedClass, false);
}
@SuppressWarnings("unchecked")
private <T> List<T> getValues(BaseRuntimeElementCompositeDefinition<?> theCurrentDef, Object theCurrentObj, List<String> theSubList, Class<T> theWantedClass, boolean theCreate) {
String name = theSubList.get(0);
List<T> retVal = new ArrayList<>();
@ -227,14 +229,71 @@ public class FhirTerser {
extensionUrl = extensionUrl.substring(0, endIndex);
}
List<ExtensionDt> extensions= Collections.emptyList();
// DSTU2
List<ExtensionDt> extensionDts = Collections.emptyList();
if (theCurrentObj instanceof ISupportsUndeclaredExtensions) {
extensions = ((ISupportsUndeclaredExtensions) theCurrentObj).getUndeclaredExtensionsByUrl(extensionUrl);
extensionDts = ((ISupportsUndeclaredExtensions) theCurrentObj).getUndeclaredExtensionsByUrl(extensionUrl);
if (extensionDts.isEmpty() && theCreate) {
// FIXME: Add a new extension with extensionUrl and null value.
// FIXME: Discern between extensions and modifier extensions.
}
} else if (theCurrentObj instanceof IBaseExtension) {
extensions = ((IBaseExtension)theCurrentObj).getExtension();
extensionDts = ((IBaseExtension) theCurrentObj).getExtension();
if (extensionDts.isEmpty() && theCreate) {
// FIXME: Add a new extension with extensionUrl and null value.
}
}
for (ExtensionDt next : extensions) {
for (ExtensionDt next : extensionDts) {
if (theWantedClass.isAssignableFrom(next.getClass())) {
retVal.add((T) next);
}
}
// DSTU3+
final String extensionUrlForLambda = extensionUrl;
List<IBaseExtension> extensions = Collections.emptyList();
if (theCurrentObj instanceof IBaseHasExtensions) {
extensions = ((IBaseHasExtensions) theCurrentObj).getExtension()
.stream()
.filter(t -> t.getUrl().equals(extensionUrlForLambda))
.distinct()
.collect(Collectors.toList());
if (extensions.isEmpty() && theCreate) {
IBaseExtension extension = ((IBaseHasExtensions) theCurrentObj).addExtension();
extension.setUrl(extensionUrl);
extensions.add(extension);
}
}
// List<IBaseExtension> modifierExtensions = Collections.emptyList();
// if (theCurrentObj instanceof IBaseHasModifierExtensions) {
// modifierExtensions = ((IBaseHasModifierExtensions) theCurrentObj).getModifierExtension()
// .stream()
// .filter(t -> t.getUrl().equals(extensionUrlForLambda))
// .collect(Collectors.toList());
//
// if (modifierExtensions.isEmpty() && theCreate) {
// IBaseExtension modifierExtension = ((IBaseHasModifierExtensions) theCurrentObj).addModifierExtension();
// modifierExtension.setUrl(extensionUrl);
// modifierExtensions.add(modifierExtension);
// }
// }
//
// List<IBaseExtension> allExtensions = Stream.of(extensions, modifierExtensions)
// .flatMap(Collection::stream)
// .distinct()
// .collect(Collectors.toList());
//
// for (IBaseExtension next : allExtensions) {
// if (theWantedClass.isAssignableFrom(next.getClass())) {
// retVal.add((T) next);
// }
// }
for (IBaseExtension next : extensions) {
if (theWantedClass.isAssignableFrom(next.getClass())) {
retVal.add((T) next);
}
@ -256,6 +315,14 @@ public class FhirTerser {
BaseRuntimeChildDefinition nextDef = theCurrentDef.getChildByNameOrThrowDataFormatException(name);
List<? extends IBase> values = nextDef.getAccessor().getValues(theCurrentObj);
if (values.isEmpty() && theCreate) {
IBase value = nextDef.getChildByName(name).newInstance();
nextDef.getMutator().addValue(theCurrentObj, value);
List<IBase> list = new ArrayList<>();
list.add(value);
values = list;
}
if (theSubList.size() == 1) {
if (nextDef instanceof RuntimeChildChoiceDefinition) {
for (IBase next : values) {
@ -297,7 +364,12 @@ public class FhirTerser {
Class<Object> wantedClass = Object.class;
return getValues(theResource, thePath, wantedClass);
}
public List<Object> getValues(IBaseResource theResource, String thePath, boolean theCreate) {
Class<Object> wantedClass = Object.class;
return getValues(theResource, thePath, wantedClass, theCreate);
}
public <T> List<T> getValues(IBaseResource theResource, String thePath, Class<T> theWantedClass) {
@ -306,6 +378,12 @@ public class FhirTerser {
return getValues(def, theResource, parts, theWantedClass);
}
public <T> List<T> getValues(IBaseResource theResource, String thePath, Class<T> theWantedClass, boolean theCreate) {
RuntimeResourceDefinition def = myContext.getResourceDefinition(theResource);
List<String> parts = parsePath(def, thePath);
return getValues(def, theResource, parts, theWantedClass, theCreate);
}
private List<String> parsePath(BaseRuntimeElementCompositeDefinition<?> theElementDef, String thePath) {
List<String> parts = new ArrayList<>();

View File

@ -1,41 +1,27 @@
package ca.uhn.fhir.util;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
import ca.uhn.fhir.context.BaseRuntimeElementDefinition;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.parser.DataFormatException;
import org.hl7.fhir.dstu3.model.*;
import org.hl7.fhir.dstu3.model.Patient.LinkType;
import org.hl7.fhir.instance.model.api.IBase;
import org.hl7.fhir.instance.model.api.IBaseExtension;
import org.hl7.fhir.instance.model.api.IBaseReference;
import org.junit.AfterClass;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import org.hl7.fhir.dstu3.model.Bundle;
import org.hl7.fhir.dstu3.model.Extension;
import org.hl7.fhir.dstu3.model.Identifier;
import org.hl7.fhir.dstu3.model.MarkdownType;
import org.hl7.fhir.dstu3.model.Money;
import org.hl7.fhir.dstu3.model.Observation;
import org.hl7.fhir.dstu3.model.Organization;
import org.hl7.fhir.dstu3.model.Patient;
import org.hl7.fhir.dstu3.model.Patient.LinkType;
import org.hl7.fhir.dstu3.model.Quantity;
import org.hl7.fhir.dstu3.model.Reference;
import org.hl7.fhir.dstu3.model.StringType;
import org.hl7.fhir.instance.model.api.IBase;
import org.hl7.fhir.instance.model.api.IBaseReference;
import org.junit.AfterClass;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
import ca.uhn.fhir.context.BaseRuntimeElementDefinition;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.parser.DataFormatException;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.junit.Assert.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class FhirTerserDstu3Test {
@ -183,6 +169,224 @@ public class FhirTerserDstu3Test {
assertSame(ref, refs.get(0));
}
@Test
public void testGetValues() {
Patient p = new Patient();
p.setActive(true);
p.addExtension()
.setUrl("http://acme.org/extension")
.setValue(new StringType("value"));
p.addExtension()
.setUrl("http://acme.org/otherExtension")
.setValue(new StringType("otherValue"));
// p.addModifierExtension()
// .setUrl("http://acme.org/extension")
// .setValue(new StringType("modifierValue"));
System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p));
List<Object> values = ourCtx.newTerser().getValues(p, "Patient.active");
assertEquals(1, values.size());
assertTrue(values.get(0) instanceof PrimitiveType);
assertTrue(values.get(0) instanceof BooleanType);
assertTrue(((BooleanType) values.get(0)).booleanValue());
values = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/extension')");
assertEquals(1, values.size());
assertTrue(values.get(0) instanceof IBaseExtension);
assertTrue(values.get(0) instanceof Extension);
assertEquals("http://acme.org/extension", ((Extension) values.get(0)).getUrl());
assertEquals("value", ((StringType) ((Extension) values.get(0)).getValue()).getValueAsString());
// values = ourCtx.newTerser().getValues(p, "Patient.modifierExtension('http://acme.org/extension')");
// assertEquals(1, values.size());
// assertTrue(values.get(0) instanceof IBaseExtension);
// assertTrue(values.get(0) instanceof Extension);
// assertEquals("http://acme.org/extension", ((Extension) values.get(0)).getUrl());
// assertEquals("value", ((StringType) ((Extension) values.get(0)).getValue()).getValueAsString());
}
@Test
public void testGetValuesAndModify() {
Patient p = new Patient();
p.setActive(true);
p.addExtension()
.setUrl("http://acme.org/extension")
.setValue(new StringType("value"));
p.addExtension()
.setUrl("http://acme.org/otherExtension")
.setValue(new StringType("otherValue"));
System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p));
List<Object> values = ourCtx.newTerser().getValues(p, "Patient.active");
assertEquals(1, values.size());
assertTrue(values.get(0) instanceof PrimitiveType);
assertTrue(values.get(0) instanceof BooleanType);
assertTrue(((BooleanType) values.get(0)).booleanValue());
((BooleanType) values.get(0)).setValue(Boolean.FALSE);
System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p));
values = ourCtx.newTerser().getValues(p, "Patient.active");
assertEquals(1, values.size());
assertTrue(values.get(0) instanceof PrimitiveType);
assertTrue(values.get(0) instanceof BooleanType);
assertFalse(((BooleanType) values.get(0)).booleanValue());
values = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/extension')");
assertEquals(1, values.size());
assertTrue(values.get(0) instanceof IBaseExtension);
assertTrue(values.get(0) instanceof Extension);
assertEquals("http://acme.org/extension", ((Extension) values.get(0)).getUrl());
assertEquals("value", ((StringType) ((Extension) values.get(0)).getValue()).getValueAsString());
((Extension) values.get(0)).setValue(new StringType("modifiedValue"));
System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p));
values = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/extension')");
assertEquals(1, values.size());
assertTrue(values.get(0) instanceof IBaseExtension);
assertTrue(values.get(0) instanceof Extension);
assertEquals("http://acme.org/extension", ((Extension) values.get(0)).getUrl());
assertEquals("modifiedValue", ((StringType) ((Extension) values.get(0)).getValue()).getValueAsString());
}
@Test
public void testGetValuesWithWantedClass() {
Patient p = new Patient();
p.setActive(true);
p.addExtension()
.setUrl("http://acme.org/extension")
.setValue(new StringType("value"));
p.addExtension()
.setUrl("http://acme.org/otherExtension")
.setValue(new StringType("otherValue"));
System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p));
List<PrimitiveType> values = ourCtx.newTerser().getValues(p, "Patient.active", PrimitiveType.class);
assertEquals(1, values.size());
assertTrue(values.get(0) instanceof BooleanType);
assertTrue(((BooleanType) values.get(0)).booleanValue());
List<Extension> extValues = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/extension')", Extension.class);
assertEquals(1, extValues.size());
assertTrue(extValues.get(0).getValue() instanceof StringType);
assertEquals("http://acme.org/extension", extValues.get(0).getUrl());
assertEquals("value", ((StringType) (extValues.get(0).getValue())).getValueAsString());
}
@Test
public void testGetValuesWithWantedClassAndModify() {
Patient p = new Patient();
p.setActive(true);
p.addExtension()
.setUrl("http://acme.org/extension")
.setValue(new StringType("value"));
p.addExtension()
.setUrl("http://acme.org/otherExtension")
.setValue(new StringType("otherValue"));
System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p));
List<PrimitiveType> values = ourCtx.newTerser().getValues(p, "Patient.active", PrimitiveType.class);
assertEquals(1, values.size());
assertTrue(values.get(0) instanceof BooleanType);
assertTrue(((BooleanType) values.get(0)).booleanValue());
((BooleanType) values.get(0)).setValue(Boolean.FALSE);
System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p));
values = ourCtx.newTerser().getValues(p, "Patient.active", PrimitiveType.class);
assertEquals(1, values.size());
assertTrue(values.get(0) instanceof BooleanType);
assertFalse(((BooleanType) values.get(0)).booleanValue());
List<Extension> extValues = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/extension')", Extension.class);
assertEquals(1, extValues.size());
assertTrue(extValues.get(0).getValue() instanceof StringType);
assertEquals("http://acme.org/extension", extValues.get(0).getUrl());
assertEquals("value", ((StringType) (extValues.get(0).getValue())).getValueAsString());
extValues.get(0).setValue(new StringType("modifiedValue"));
System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p));
extValues = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/extension')", Extension.class);
assertEquals(1, extValues.size());
assertTrue(extValues.get(0).getValue() instanceof StringType);
assertEquals("http://acme.org/extension", extValues.get(0).getUrl());
assertEquals("modifiedValue", ((StringType) (extValues.get(0).getValue())).getValueAsString());
}
@Test
public void testGetValuesWithWantedClassAndTheCreate() {
Patient p = new Patient();
System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p));
List<PrimitiveType> values = ourCtx.newTerser().getValues(p, "Patient.active", PrimitiveType.class, true);
assertEquals(1, values.size());
assertTrue(values.get(0) instanceof BooleanType);
assertNull(((BooleanType) values.get(0)).getValue());
List<Extension> extValues = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/extension')", Extension.class, true);
assertEquals(1, extValues.size());
assertEquals("http://acme.org/extension", extValues.get(0).getUrl());
assertNull(extValues.get(0).getValue());
}
@Test
public void testGetValuesWithTheCreate() {
Patient p = new Patient();
System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p));
List<Object> values = ourCtx.newTerser().getValues(p, "Patient.active", true);
assertEquals(1, values.size());
assertTrue(values.get(0) instanceof PrimitiveType);
assertTrue(values.get(0) instanceof BooleanType);
assertNull(((BooleanType) values.get(0)).getValue());
values = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/extension')", true);
assertEquals(1, values.size());
assertTrue(values.get(0) instanceof IBaseExtension);
assertTrue(values.get(0) instanceof Extension);
assertEquals("http://acme.org/extension", ((Extension) values.get(0)).getUrl());
assertNull(((Extension) values.get(0)).getValue());
}
@Test
public void testGetValuesWithTheCreateAndNoOverwrite() {
Patient p = new Patient();
p.setActive(true);
p.addExtension()
.setUrl("http://acme.org/extension")
.setValue(new StringType("value"));
p.addExtension()
.setUrl("http://acme.org/otherExtension")
.setValue(new StringType("otherValue"));
System.out.println(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p));
List<Object> values = ourCtx.newTerser().getValues(p, "Patient.active", true);
assertEquals(1, values.size());
assertTrue(values.get(0) instanceof PrimitiveType);
assertTrue(values.get(0) instanceof BooleanType);
assertTrue(((BooleanType) values.get(0)).booleanValue());
values = ourCtx.newTerser().getValues(p, "Patient.extension('http://acme.org/extension')");
assertEquals(1, values.size());
assertTrue(values.get(0) instanceof IBaseExtension);
assertTrue(values.get(0) instanceof Extension);
assertEquals("http://acme.org/extension", ((Extension) values.get(0)).getUrl());
assertEquals("value", ((StringType) ((Extension) values.get(0)).getValue()).getValueAsString());
}
@Test
public void testVisitWithModelVisitor2() {
IModelVisitor2 visitor = mock(IModelVisitor2.class);