Fix #720 - Failure to parse custom type

This commit is contained in:
James Agnew 2017-10-21 13:47:03 -04:00
parent 5f5475fb17
commit 16e19a9fed
8 changed files with 196 additions and 2 deletions

View File

@ -606,7 +606,7 @@ class ParserState<T> {
return;
}
case RESOURCE: {
if (myInstance instanceof IAnyResource || myInstance instanceof IBaseBackboneElement) {
if (myInstance instanceof IAnyResource || myInstance instanceof IBaseBackboneElement || myInstance instanceof IBaseElement) {
ParserState<T>.PreResourceStateHl7Org state = new PreResourceStateHl7Org(myInstance, child.getMutator(), null);
push(state);
} else {

View File

@ -0,0 +1,30 @@
package ca.uhn.fhir.parser;
import ca.uhn.fhir.model.api.annotation.Child;
import ca.uhn.fhir.model.api.annotation.DatatypeDef;
import ca.uhn.fhir.model.api.annotation.Description;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import org.hl7.fhir.dstu3.model.Person;
import org.hl7.fhir.dstu3.model.Type;
import org.hl7.fhir.instance.model.api.ICompositeType;
/**
* See #720
*/
@DatatypeDef(name = "ConsentTemplate")
public class Bug720Datatype extends Type implements ICompositeType {
@Child(name = "contact", order = 8, min = 0, max = 1)
@Description(shortDefinition = "responsible contact for this consent template")
private Person contact = new Person();
public Person getContact() {
return contact;
}
@Override
protected Type typedCopy() {
throw new InternalErrorException("");
}
}

View File

@ -0,0 +1,38 @@
package ca.uhn.fhir.parser;
import ca.uhn.fhir.model.api.annotation.Child;
import ca.uhn.fhir.model.api.annotation.Description;
import ca.uhn.fhir.model.api.annotation.ResourceDef;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import org.hl7.fhir.dstu3.model.DomainResource;
import org.hl7.fhir.dstu3.model.ResourceType;
import org.hl7.fhir.dstu3.model.Type;
import java.util.ArrayList;
import java.util.List;
/**
* See #720
*/
@ResourceDef(name = "Bug720ResourceType", profile = "http://example.com/StructureDefinition/dontuse#Bug720ResourceType")
public class Bug720ResourceType extends DomainResource {
@Child(name = "templates", order = 4, min = 1, max = Child.MAX_UNLIMITED, type = {Bug720Datatype.class})
@Description(shortDefinition = "import information for 1-n consent templates")
private List<Type> templates = new ArrayList<Type>();
@Override
public DomainResource copy() {
throw new InternalErrorException("");
}
@Override
public ResourceType getResourceType() {
throw new InternalErrorException("");
}
public List<Type> getTemplates() {
return templates;
}
}

View File

@ -77,6 +77,22 @@ public class JsonParserDstu3Test {
}
}
/**
* See #720
*/
@Test
public void testParseCustomResourceType() {
String input = "{\"resourceType\":\"Bug720ResourceType\",\"meta\":{\"profile\":[\"http://example.com/StructureDefinition/dontuse#Bug720ResourceType\"]},\"supportedVersion\":\"2.5.x\",\"templatesConsentTemplate\":[{\"domainName\":\"name\",\"Name\":\"template_01\",\"version\":\"1.0\",\"title\":\"title\",\"comment\":\"comment\",\"contact\":{\"resourceType\":\"Person\",\"name\":[{\"family\":\"Mustermann\",\"given\":[\"Max\"]}],\"telecom\":[{\"system\":\"email\",\"value\":\"max.mustermann@mail.de\"},{\"system\":\"phone\",\"value\":\"+49 1234 23232\"}],\"address\":[{\"text\":\"street 1-2\",\"city\":\"city\",\"postalCode\":\"12345\",\"country\":\"Germany\"}]}}]}";
Bug720ResourceType parsed = ourCtx.newJsonParser().parseResource(Bug720ResourceType.class, input);
assertEquals(1, parsed.getTemplates().size());
assertEquals(Bug720Datatype.class, parsed.getTemplates().get(0).getClass());
assertEquals("Mustermann", ((Bug720Datatype)parsed.getTemplates().get(0)).getContact().getNameFirstRep().getFamily());
ourLog.info(ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(parsed));
}
/**
* See #563
*/

View File

@ -1221,7 +1221,8 @@ public class FHIRPathEngine {
return result;
case Concatenate:
result = new TypeDetails(CollectionStatus.SINGLETON, "");
return result;
// return result;
// fall through
case Plus:
result = new TypeDetails(CollectionStatus.SINGLETON);
if (left.hasType(worker, "integer") && right.hasType(worker, "integer"))

View File

@ -877,6 +877,18 @@ public class FhirInstanceValidatorDstu3Test {
}
@Test
public void testGoal() {
Goal goal = new Goal();
goal.setSubject(new Reference("Patient/123"));
goal.setDescription(new CodeableConcept().addCoding(new Coding("http://foo","some other goal","")));
goal.setStatus(Goal.GoalStatus.INPROGRESS);
ValidationResult results = myVal.validateWithResult(goal);
List<SingleValidationMessage> outcome = logResultsAndReturnNonInformationalOnes(results);
assertEquals(0, outcome.size());
}
@AfterClass
public static void afterClassClearContext() {
myDefaultValidationSupport.flush();

View File

@ -0,0 +1,92 @@
package org.hl7.fhir.r4.utils;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.util.TestUtil;
import org.hl7.fhir.dstu3.utils.FhirPathEngineTest;
import org.hl7.fhir.r4.hapi.ctx.DefaultProfileValidationSupport;
import org.hl7.fhir.r4.hapi.ctx.HapiWorkerContext;
import org.hl7.fhir.r4.model.*;
import org.hl7.fhir.r4.utils.FHIRPathEngine;
import org.hl7.fhir.exceptions.FHIRException;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import java.util.List;
import static org.junit.Assert.*;
public class FhirPathEngineR4Test {
private static FhirContext ourCtx = FhirContext.forR4();
private static FHIRPathEngine ourEngine;
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirPathEngineTest.class);
@Test
public void testAs() throws Exception {
Observation obs = new Observation();
obs.setValue(new StringType("FOO"));
List<Base> value = ourEngine.evaluate(obs, "Observation.value.as(String)");
assertEquals(1, value.size());
assertEquals("FOO", ((StringType)value.get(0)).getValue());
}
@Test
public void testExistsWithNoValue() throws FHIRException {
Patient patient = new Patient();
patient.setDeceased(new BooleanType());
List<Base> eval = ourEngine.evaluate(patient, "Patient.deceased.exists()");
ourLog.info(eval.toString());
assertFalse(((BooleanType)eval.get(0)).getValue());
}
@Test
public void testExistsWithValue() throws FHIRException {
Patient patient = new Patient();
patient.setDeceased(new BooleanType(false));
List<Base> eval = ourEngine.evaluate(patient, "Patient.deceased.exists()");
ourLog.info(eval.toString());
assertTrue(((BooleanType)eval.get(0)).getValue());
}
@Test
public void testConcatenation() throws FHIRException {
String exp = "Patient.name.family & '.'";
Patient p = new Patient();
p.addName().setFamily("TEST");
String result = ourEngine.evaluateToString(p, exp);
assertEquals("TEST.", result);
}
@Test
public void testConcatenationFunction() throws FHIRException {
String exp = "element.first().path.startsWith(%resource.type) and element.tail().all(path.startsWith(%resource.type&'.'))";
StructureDefinition sd = new StructureDefinition();
StructureDefinition.StructureDefinitionDifferentialComponent diff = sd.getDifferential();
diff.addElement().setPath("Patient.name");
Patient p = new Patient();
p.addName().setFamily("TEST");
List<Base> result = ourEngine.evaluate(null, p, diff, exp);
ourLog.info(result.toString());
// assertEquals("TEST.", result);
}
@AfterClass
public static void afterClassClearContext() throws Exception {
TestUtil.clearAllStaticFieldsForUnitTest();
}
@BeforeClass
public static void beforeClass() {
ourEngine = new FHIRPathEngine(new HapiWorkerContext(ourCtx, new DefaultProfileValidationSupport()));
}
}

View File

@ -125,6 +125,11 @@
a real resource type, and caused conflicts with the .NET client. Thanks to
Vlad Ignatov for reporting!
</action>
<action type="fix" issue="720">
Parsing a DSTU3/R4 custom structure which contained a field of
a custom type caused a crash during parsing. Thanks to
GitHub user @mosaic-hgw for reporting!
</action>
</release>
<release version="3.0.0" date="2017-09-27">
<action type="add">