Handle unexpected extensions when parsing using IParserErrorHandler
This commit is contained in:
parent
4573b86972
commit
3fd9f9518a
|
@ -867,7 +867,7 @@ class ParserState<T> {
|
||||||
ParserState<T>.ExtensionState newState = new ExtensionState(myPreResourceState, ext);
|
ParserState<T>.ExtensionState newState = new ExtensionState(myPreResourceState, ext);
|
||||||
push(newState);
|
push(newState);
|
||||||
} else {
|
} else {
|
||||||
throw new DataFormatException("Type " + getCurrentElement() + " does not support undeclared extentions, and found an extension with URL: " + theUrlAttr);
|
logAndSwallowUnexpectedElement("extension");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (getCurrentElement() instanceof IBaseHasModifierExtensions) {
|
if (getCurrentElement() instanceof IBaseHasModifierExtensions) {
|
||||||
|
@ -876,7 +876,7 @@ class ParserState<T> {
|
||||||
ParserState<T>.ExtensionState newState = new ExtensionState(myPreResourceState, ext);
|
ParserState<T>.ExtensionState newState = new ExtensionState(myPreResourceState, ext);
|
||||||
push(newState);
|
push(newState);
|
||||||
} else {
|
} else {
|
||||||
throw new DataFormatException("Type " + getCurrentElement() + " does not support undeclared extentions, and found an extension with URL: " + theUrlAttr);
|
logAndSwallowUnexpectedElement("modifierExtension");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,6 +76,24 @@ public class ElementUtil {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
public static <T> void validateAllElementsAreOfTypeOrThrowClassCastExceptionForModelSetter(List<T> theList, Class<T> theType) {
|
||||||
|
if (theList == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (T next : theList) {
|
||||||
|
if (next != null && theType.isAssignableFrom(next.getClass()) == false) {
|
||||||
|
StringBuilder b = new StringBuilder();
|
||||||
|
b.append("Failed to set invalid value, found element in list of type ");
|
||||||
|
b.append(next.getClass().getSimpleName());
|
||||||
|
b.append(" but expected ");
|
||||||
|
b.append(theType.getName());
|
||||||
|
throw new ClassCastException(b.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
public static boolean isEmpty(List<? extends IBase> theElements) {
|
public static boolean isEmpty(List<? extends IBase> theElements) {
|
||||||
if (theElements == null) {
|
if (theElements == null) {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
package ca.uhn.fhir.model.dstu2;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
||||||
|
|
||||||
|
public class ModelDstu2Test {
|
||||||
|
|
||||||
|
private static FhirContext ourCtx = FhirContext.forDstu2();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See #304
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("rawtypes")
|
||||||
|
@Test
|
||||||
|
public void testPopulateWrongGenericType() {
|
||||||
|
Patient p = new Patient();
|
||||||
|
List names = Arrays.asList("name");
|
||||||
|
|
||||||
|
p.setName(null);
|
||||||
|
|
||||||
|
ourCtx.newXmlParser().encodeResourceToString(p);
|
||||||
|
|
||||||
|
try {
|
||||||
|
p.setName(names);
|
||||||
|
fail();
|
||||||
|
} catch (ClassCastException e) {
|
||||||
|
assertEquals("Failed to set invalid value, found element in list of type String but expected ca.uhn.fhir.model.dstu2.composite.HumanNameDt", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -2,7 +2,6 @@ package ca.uhn.fhir.parser;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.contains;
|
import static org.hamcrest.Matchers.contains;
|
||||||
import static org.hamcrest.Matchers.containsString;
|
import static org.hamcrest.Matchers.containsString;
|
||||||
import static org.hamcrest.Matchers.emptyString;
|
|
||||||
import static org.hamcrest.Matchers.not;
|
import static org.hamcrest.Matchers.not;
|
||||||
import static org.hamcrest.Matchers.stringContainsInOrder;
|
import static org.hamcrest.Matchers.stringContainsInOrder;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
@ -11,6 +10,9 @@ import static org.junit.Assert.assertNull;
|
||||||
import static org.junit.Assert.assertSame;
|
import static org.junit.Assert.assertSame;
|
||||||
import static org.junit.Assert.assertThat;
|
import static org.junit.Assert.assertThat;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.times;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -21,6 +23,8 @@ import org.apache.commons.io.IOUtils;
|
||||||
import org.hamcrest.Matchers;
|
import org.hamcrest.Matchers;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.mockito.ArgumentCaptor;
|
||||||
|
import org.mockito.Mockito;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.ConfigurationException;
|
import ca.uhn.fhir.context.ConfigurationException;
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
@ -56,6 +60,7 @@ import ca.uhn.fhir.model.primitive.DateTimeDt;
|
||||||
import ca.uhn.fhir.model.primitive.IdDt;
|
import ca.uhn.fhir.model.primitive.IdDt;
|
||||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||||
import ca.uhn.fhir.model.primitive.StringDt;
|
import ca.uhn.fhir.model.primitive.StringDt;
|
||||||
|
import ca.uhn.fhir.parser.IParserErrorHandler.IParseLocation;
|
||||||
import ca.uhn.fhir.rest.server.Constants;
|
import ca.uhn.fhir.rest.server.Constants;
|
||||||
import net.sf.json.JSON;
|
import net.sf.json.JSON;
|
||||||
import net.sf.json.JSONSerializer;
|
import net.sf.json.JSONSerializer;
|
||||||
|
@ -109,10 +114,8 @@ public class JsonParserDstu2Test {
|
||||||
assertThat(enc, Matchers.stringContainsInOrder("{\"resourceType\":\"Patient\",", "\"extension\":[{\"url\":\"http://example.com/extensions#someext\",\"valueDateTime\":\"2011-01-02T11:13:15\"}",
|
assertThat(enc, Matchers.stringContainsInOrder("{\"resourceType\":\"Patient\",", "\"extension\":[{\"url\":\"http://example.com/extensions#someext\",\"valueDateTime\":\"2011-01-02T11:13:15\"}",
|
||||||
"{\"url\":\"http://example.com#parent\",\"extension\":[{\"url\":\"http://example.com#child\",\"valueString\":\"value1\"},{\"url\":\"http://example.com#child\",\"valueString\":\"value2\"}]}"));
|
"{\"url\":\"http://example.com#parent\",\"extension\":[{\"url\":\"http://example.com#child\",\"valueString\":\"value1\"},{\"url\":\"http://example.com#child\",\"valueString\":\"value2\"}]}"));
|
||||||
assertThat(enc, Matchers.stringContainsInOrder("\"modifierExtension\":[" + "{" + "\"url\":\"http://example.com/extensions#modext\"," + "\"valueDate\":\"1995-01-02\"" + "}" + "],"));
|
assertThat(enc, Matchers.stringContainsInOrder("\"modifierExtension\":[" + "{" + "\"url\":\"http://example.com/extensions#modext\"," + "\"valueDate\":\"1995-01-02\"" + "}" + "],"));
|
||||||
assertThat(enc,
|
assertThat(enc, containsString("\"_given\":[" + "{" + "\"extension\":[" + "{" + "\"url\":\"http://examples.com#givenext\"," + "\"valueString\":\"given\"" + "}" + "]" + "}," + "{" + "\"extension\":[" + "{" + "\"url\":\"http://examples.com#givenext_parent\"," + "\"extension\":[" + "{"
|
||||||
containsString("\"_given\":[" + "{" + "\"extension\":[" + "{" + "\"url\":\"http://examples.com#givenext\"," + "\"valueString\":\"given\"" + "}" + "]" + "}," + "{" + "\"extension\":[" + "{"
|
+ "\"url\":\"http://examples.com#givenext_child\"," + "\"valueString\":\"CHILD\"" + "}" + "]" + "}" + "]" + "}"));
|
||||||
+ "\"url\":\"http://examples.com#givenext_parent\"," + "\"extension\":[" + "{" + "\"url\":\"http://examples.com#givenext_child\"," + "\"valueString\":\"CHILD\"" + "}" + "]" + "}"
|
|
||||||
+ "]" + "}"));
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now parse this back
|
* Now parse this back
|
||||||
|
@ -431,8 +434,7 @@ public class JsonParserDstu2Test {
|
||||||
ourLog.info(encoded);
|
ourLog.info(encoded);
|
||||||
|
|
||||||
assertThat(encoded, containsString("Patient"));
|
assertThat(encoded, containsString("Patient"));
|
||||||
assertThat(encoded, stringContainsInOrder("\"tag\"", "\"system\":\"foo\",", "\"code\":\"bar\"", "\"system\":\"" + Constants.TAG_SUBSETTED_SYSTEM + "\",",
|
assertThat(encoded, stringContainsInOrder("\"tag\"", "\"system\":\"foo\",", "\"code\":\"bar\"", "\"system\":\"" + Constants.TAG_SUBSETTED_SYSTEM + "\",", "\"code\":\"" + Constants.TAG_SUBSETTED_CODE + "\","));
|
||||||
"\"code\":\"" + Constants.TAG_SUBSETTED_CODE + "\","));
|
|
||||||
assertThat(encoded, not(containsString("THE DIV")));
|
assertThat(encoded, not(containsString("THE DIV")));
|
||||||
assertThat(encoded, containsString("family"));
|
assertThat(encoded, containsString("family"));
|
||||||
assertThat(encoded, not(containsString("maritalStatus")));
|
assertThat(encoded, not(containsString("maritalStatus")));
|
||||||
|
@ -453,8 +455,7 @@ public class JsonParserDstu2Test {
|
||||||
String enc = ourCtx.newJsonParser().encodeResourceToString(pt);
|
String enc = ourCtx.newJsonParser().encodeResourceToString(pt);
|
||||||
ourLog.info(enc);
|
ourLog.info(enc);
|
||||||
|
|
||||||
assertEquals("{\"resourceType\":\"Patient\",\"meta\":{\"tag\":[{\"system\":\"scheme\",\"code\":\"term\",\"display\":\"display\"}]},\"identifier\":[{\"system\":\"sys\",\"value\":\"val\"}]}",
|
assertEquals("{\"resourceType\":\"Patient\",\"meta\":{\"tag\":[{\"system\":\"scheme\",\"code\":\"term\",\"display\":\"display\"}]},\"identifier\":[{\"system\":\"sys\",\"value\":\"val\"}]}", enc);
|
||||||
enc);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1067,6 +1068,30 @@ public class JsonParserDstu2Test {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParseWithExtensions() throws Exception {
|
||||||
|
String input = IOUtils.toString(getClass().getResourceAsStream("/patient1.json"));
|
||||||
|
IParser parser = ourCtx.newJsonParser();
|
||||||
|
IParserErrorHandler peh = mock(IParserErrorHandler.class);
|
||||||
|
parser.setParserErrorHandler(peh);
|
||||||
|
Patient p = parser.parseResource(Patient.class, input);
|
||||||
|
|
||||||
|
ArgumentCaptor<String> capt = ArgumentCaptor.forClass(String.class);
|
||||||
|
verify(peh, times(4)).unknownElement(Mockito.isNull(IParseLocation.class), capt.capture());
|
||||||
|
|
||||||
|
//@formatter:off
|
||||||
|
List<String> strings = capt.getAllValues();
|
||||||
|
assertThat(strings, contains(
|
||||||
|
"extension",
|
||||||
|
"extension",
|
||||||
|
"modifierExtension",
|
||||||
|
"modifierExtension"
|
||||||
|
));
|
||||||
|
//@formatter:off
|
||||||
|
|
||||||
|
assertEquals("Smith", p.getName().get(0).getGiven().get(0).getValue());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testParseWithWrongTypeObjectShouldBeArray() throws Exception {
|
public void testParseWithWrongTypeObjectShouldBeArray() throws Exception {
|
||||||
String input = IOUtils.toString(getClass().getResourceAsStream("/invalid_metadata.json"));
|
String input = IOUtils.toString(getClass().getResourceAsStream("/invalid_metadata.json"));
|
||||||
|
|
|
@ -97,6 +97,7 @@ public class XmlParserDstu2Test {
|
||||||
private static final FhirContext ourCtx = FhirContext.forDstu2();
|
private static final FhirContext ourCtx = FhirContext.forDstu2();
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(XmlParserDstu2Test.class);
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(XmlParserDstu2Test.class);
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBundleWithBinary() {
|
public void testBundleWithBinary() {
|
||||||
//@formatter:off
|
//@formatter:off
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
{
|
||||||
|
"id": "73b551fb-46f5-4fb8-b735-2399344e9717",
|
||||||
|
"meta": {
|
||||||
|
"extension": [
|
||||||
|
{
|
||||||
|
"url": "fhir-request-method",
|
||||||
|
"valueString": "POST"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "fhir-request-uri",
|
||||||
|
"valueUri": "Patient"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"modifierExtension": [
|
||||||
|
{
|
||||||
|
"url": "fhir-request-method",
|
||||||
|
"valueString": "POST"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "fhir-request-uri",
|
||||||
|
"valueUri": "Patient"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"versionId": "01e5253d-d258-494c-8d8e-f22ad6d8f19b",
|
||||||
|
"lastUpdated": "2016-02-20T11:01:56.155Z"
|
||||||
|
},
|
||||||
|
"name": [
|
||||||
|
{
|
||||||
|
"given": [
|
||||||
|
"Smith"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"resourceType": "Patient"
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
package ca.uhn.fhir.model;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.hl7.fhir.dstu3.model.Patient;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class ModelDstu3Test {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See #304
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("rawtypes")
|
||||||
|
@Test
|
||||||
|
public void testPopulateWrongGenericType() {
|
||||||
|
Patient p = new Patient();
|
||||||
|
List names = Arrays.asList("name");
|
||||||
|
|
||||||
|
p.setName(null);
|
||||||
|
try {
|
||||||
|
p.setName(names);
|
||||||
|
fail();
|
||||||
|
} catch (ClassCastException e) {
|
||||||
|
assertEquals("Failed to set invalid value, found element in list of type String but expected ca.uhn.fhir.model.dstu2.composite.HumanNameDt", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -123,7 +123,9 @@ public abstract class Child extends BaseElement {
|
||||||
public String getSingleType() {
|
public String getSingleType() {
|
||||||
String retVal;
|
String retVal;
|
||||||
String elemName = this.getType().get(0);
|
String elemName = this.getType().get(0);
|
||||||
|
if (elemName.startsWith("ca.") == false) {
|
||||||
elemName = elemName.substring(0, 1).toUpperCase() + elemName.substring(1);
|
elemName = elemName.substring(0, 1).toUpperCase() + elemName.substring(1);
|
||||||
|
}
|
||||||
// if (this instanceof ResourceBlock) {
|
// if (this instanceof ResourceBlock) {
|
||||||
retVal = (elemName);
|
retVal = (elemName);
|
||||||
// } else {
|
// } else {
|
||||||
|
|
|
@ -158,6 +158,12 @@
|
||||||
buttom will no longer show a "loading" spinner, but there doesn't seem to
|
buttom will no longer show a "loading" spinner, but there doesn't seem to
|
||||||
be another way of fixing this. Thanks to Mark Scrimshire for reporting!
|
be another way of fixing this. Thanks to Mark Scrimshire for reporting!
|
||||||
</action>
|
</action>
|
||||||
|
<action type="fix">
|
||||||
|
Extensions found while parsing an object that doesn't support extensions are now
|
||||||
|
reported using the IParserErrorHandler framework in the same way that
|
||||||
|
other similar errors are handled. This allows the parser to be more lenient
|
||||||
|
when needed.
|
||||||
|
</action>
|
||||||
</release>
|
</release>
|
||||||
<release version="1.4" date="2016-02-04">
|
<release version="1.4" date="2016-02-04">
|
||||||
<action type="add">
|
<action type="add">
|
||||||
|
|
Loading…
Reference in New Issue