* Parser: Reporting unexpected repeating element for choice (#4574) IParserErrorHandler.unexpectedRepeatingElement is now also called for unexpected repeating elements of type choice, where concrete names may be different based on the choice's data type. * setting test-utilities java version to the test version * added changelog * added Max to the developer liss * removed unneeded dependency --------- Co-authored-by: patrick-werner <pa.f.werner@gmail.com>
This commit is contained in:
parent
9ae71aba95
commit
648d14c52c
|
@ -25,6 +25,7 @@ import ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition;
|
|||
import ca.uhn.fhir.context.BaseRuntimeElementDefinition;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import ca.uhn.fhir.context.RuntimeChildChoiceDefinition;
|
||||
import ca.uhn.fhir.context.RuntimeChildDeclaredExtensionDefinition;
|
||||
import ca.uhn.fhir.context.RuntimePrimitiveDatatypeDefinition;
|
||||
import ca.uhn.fhir.context.RuntimePrimitiveDatatypeNarrativeDefinition;
|
||||
|
@ -583,10 +584,19 @@ class ParserState<T> {
|
|||
return;
|
||||
}
|
||||
|
||||
if ((child.getMax() == 0 || child.getMax() == 1) && !myParsedNonRepeatableNames.add(theChildName)) {
|
||||
myErrorHandler.unexpectedRepeatingElement(null, theChildName);
|
||||
push(new SwallowChildrenWholeState(getPreResourceState()));
|
||||
return;
|
||||
if ((child.getMax() == 0 || child.getMax() == 1)) {
|
||||
String nameToCheck;
|
||||
if (child instanceof RuntimeChildChoiceDefinition) {
|
||||
RuntimeChildChoiceDefinition choiceChild = (RuntimeChildChoiceDefinition) child;
|
||||
nameToCheck = choiceChild.getField().getName();
|
||||
} else {
|
||||
nameToCheck = theChildName;
|
||||
}
|
||||
if(!myParsedNonRepeatableNames.add(nameToCheck)) {
|
||||
myErrorHandler.unexpectedRepeatingElement(null, nameToCheck);
|
||||
push(new SwallowChildrenWholeState(getPreResourceState()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
BaseRuntimeElementDefinition<?> target = child.getChildByName(theChildName);
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
type: fix
|
||||
issue: 4468
|
||||
title: "When parsing a FHIR resource which has multiple value[x] choice fields, the parser does not call the IParserErrorHandler#unexpectedRepeatingElement method on the configured parser error handler. Thanks to Max Bureck for the
|
||||
pull request!"
|
|
@ -0,0 +1,13 @@
|
|||
package ca.uhn.fhir.parser;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
|
||||
public class Dstu2_1JsonParserErrorHandlerTest extends AbstractJsonParserErrorHandlerTest {
|
||||
|
||||
private static FhirContext ourCtx = FhirContext.forDstu2_1();
|
||||
|
||||
@Override
|
||||
protected FhirContext getFhirContext() {
|
||||
return ourCtx;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package ca.uhn.fhir.parser;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
|
||||
public class Dstu2_1XmlParserErrorHandlerTest extends AbstractXmlParserErrorHandlerTest {
|
||||
|
||||
private static FhirContext ourCtx = FhirContext.forDstu2_1();
|
||||
|
||||
@Override
|
||||
protected FhirContext getFhirContext() {
|
||||
return ourCtx;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package ca.uhn.fhir.parser;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
|
||||
public class Dstu2JsonParserErrorHandlerTest extends AbstractJsonParserErrorHandlerTest {
|
||||
|
||||
private static FhirContext ourCtx = FhirContext.forDstu2();
|
||||
|
||||
@Override
|
||||
protected FhirContext getFhirContext() {
|
||||
return ourCtx;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package ca.uhn.fhir.parser;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
|
||||
public class Dstu2XmlParserErrorHandlerTest extends AbstractXmlParserErrorHandlerTest {
|
||||
|
||||
private static FhirContext ourCtx = FhirContext.forDstu2();
|
||||
|
||||
@Override
|
||||
protected FhirContext getFhirContext() {
|
||||
return ourCtx;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package ca.uhn.fhir.parser;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
|
||||
public class Dstu3JsonParserErrorHandlerTest extends AbstractJsonParserErrorHandlerTest {
|
||||
|
||||
private static FhirContext ourCtx = FhirContext.forDstu3();
|
||||
|
||||
@Override
|
||||
protected FhirContext getFhirContext() {
|
||||
return ourCtx;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package ca.uhn.fhir.parser;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
|
||||
public class Dstu3XmlParserErrorHandlerTest extends AbstractXmlParserErrorHandlerTest {
|
||||
|
||||
private static FhirContext ourCtx = FhirContext.forDstu3();
|
||||
|
||||
@Override
|
||||
protected FhirContext getFhirContext() {
|
||||
return ourCtx;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package ca.uhn.fhir.parser;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
|
||||
public class Dstu2Hl7OrgJsonParserErrorHandlerTest extends AbstractJsonParserErrorHandlerTest {
|
||||
|
||||
private static FhirContext ourCtx = FhirContext.forDstu2Hl7Org();
|
||||
|
||||
@Override
|
||||
protected FhirContext getFhirContext() {
|
||||
return ourCtx;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package ca.uhn.fhir.parser;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
|
||||
public class Dstu2Hl7OrgXmlParserErrorHandlerTest extends AbstractXmlParserErrorHandlerTest {
|
||||
|
||||
private static FhirContext ourCtx = FhirContext.forDstu2Hl7Org();
|
||||
|
||||
@Override
|
||||
protected FhirContext getFhirContext() {
|
||||
return ourCtx;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package ca.uhn.fhir.parser;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
|
||||
public class R4JsonParserErrorHandlerTest extends AbstractJsonParserErrorHandlerTest {
|
||||
|
||||
private static FhirContext ourCtx = FhirContext.forR4();
|
||||
|
||||
@Override
|
||||
protected FhirContext getFhirContext() {
|
||||
return ourCtx;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package ca.uhn.fhir.parser;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
|
||||
public class R4XmlParserErrorHandlerTest extends AbstractXmlParserErrorHandlerTest {
|
||||
|
||||
private static FhirContext ourCtx = FhirContext.forR4();
|
||||
|
||||
@Override
|
||||
protected FhirContext getFhirContext() {
|
||||
return ourCtx;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package ca.uhn.fhir.parser;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
|
||||
public class R4BJsonParserErrorHandlerTest extends AbstractJsonParserErrorHandlerTest {
|
||||
|
||||
private static FhirContext ourCtx = FhirContext.forR4B();
|
||||
|
||||
@Override
|
||||
protected FhirContext getFhirContext() {
|
||||
return ourCtx;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package ca.uhn.fhir.parser;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
|
||||
public class R4BXmlParserErrorHandlerTest extends AbstractXmlParserErrorHandlerTest {
|
||||
|
||||
private static FhirContext ourCtx = FhirContext.forR4B();
|
||||
|
||||
@Override
|
||||
protected FhirContext getFhirContext() {
|
||||
return ourCtx;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package ca.uhn.fhir.parser;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
|
||||
public class R5JsonParserErrorHandlerTest extends AbstractJsonParserErrorHandlerTest {
|
||||
|
||||
private static FhirContext ourCtx = FhirContext.forR5();
|
||||
|
||||
@Override
|
||||
protected FhirContext getFhirContext() {
|
||||
return ourCtx;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package ca.uhn.fhir.parser;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
|
||||
public class R5XmlParserErrorHandlerTest extends AbstractXmlParserErrorHandlerTest {
|
||||
|
||||
private static FhirContext ourCtx = FhirContext.forR5();
|
||||
|
||||
@Override
|
||||
protected FhirContext getFhirContext() {
|
||||
return ourCtx;
|
||||
}
|
||||
}
|
|
@ -15,6 +15,13 @@
|
|||
<name>HAPI FHIR Test Utilities</name>
|
||||
<url>http://jamesagnew.github.io/hapi-fhir/</url>
|
||||
|
||||
<properties>
|
||||
<!-- this is a test jar, so use our test settings -->
|
||||
<maven.compiler.source>${maven.compiler.testSource}</maven.compiler.source>
|
||||
<maven.compiler.target>${maven.compiler.testTarget}</maven.compiler.target>
|
||||
<maven.compiler.release>${maven.compiler.testRelease}</maven.compiler.release>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
package ca.uhn.fhir.parser;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
|
||||
abstract public non-sealed class AbstractJsonParserErrorHandlerTest extends AbstractParserErrorHandlerTest {
|
||||
|
||||
private static String PATIENT_DUPLICATE_CHOICE =
|
||||
"""
|
||||
{
|
||||
"resourceType": "Patient",
|
||||
"deceasedBoolean": "true",
|
||||
"deceasedDateTime": "2022-02-07T13:28:17-05:00"
|
||||
}
|
||||
""";
|
||||
|
||||
protected abstract FhirContext getFhirContext();
|
||||
|
||||
@Override
|
||||
protected IParser createParser() {
|
||||
return getFhirContext().newJsonParser();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String createResourceWithRepeatingChoice() {
|
||||
return PATIENT_DUPLICATE_CHOICE;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package ca.uhn.fhir.parser;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
/**
|
||||
* Defines FHIR version independent tests for testing parser error handling. In version dependent
|
||||
* projects, the sub-types {@link AbstractXmlParserErrorHandlerTest}, {@link
|
||||
* AbstractJsonParserErrorHandlerTest} can be sub-classed to create a complete test.
|
||||
*/
|
||||
public abstract sealed class AbstractParserErrorHandlerTest
|
||||
permits AbstractXmlParserErrorHandlerTest, AbstractJsonParserErrorHandlerTest {
|
||||
|
||||
protected abstract IParser createParser();
|
||||
|
||||
protected abstract String createResourceWithRepeatingChoice();
|
||||
|
||||
@Test
|
||||
public void testRepeatingChoiceHandled() {
|
||||
|
||||
// Let error handler throw custom exception on unexpectedRepeatingElement
|
||||
@SuppressWarnings("serial")
|
||||
class RepeatingChoiceHandledException extends RuntimeException {}
|
||||
IParserErrorHandler errorHandler = new ErrorHandlerAdapter() {
|
||||
@Override
|
||||
public void unexpectedRepeatingElement(IParseLocation theLocation, String theElementName) {
|
||||
throw new RepeatingChoiceHandledException();
|
||||
}
|
||||
};
|
||||
|
||||
IParser parser = createParser();
|
||||
parser.setParserErrorHandler(errorHandler);
|
||||
|
||||
String resourceStr = createResourceWithRepeatingChoice();
|
||||
assertThrows(
|
||||
RepeatingChoiceHandledException.class,
|
||||
() -> {
|
||||
parser.parseResource(resourceStr);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package ca.uhn.fhir.parser;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
|
||||
public abstract non-sealed class AbstractXmlParserErrorHandlerTest extends AbstractParserErrorHandlerTest {
|
||||
|
||||
private static String PATIENT_DUPLICATE_CHOICE =
|
||||
"""
|
||||
<Patient xmlns="http://hl7.org/fhir">
|
||||
<deceasedBoolean value="true"></deceasedBoolean>
|
||||
<deceasedDateTime value="2022-02-07T13:28:17-05:00"></deceasedDateTime>
|
||||
</Patient>""";
|
||||
|
||||
protected abstract FhirContext getFhirContext();
|
||||
|
||||
@Override
|
||||
protected IParser createParser() {
|
||||
return getFhirContext().newXmlParser();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String createResourceWithRepeatingChoice() {
|
||||
return PATIENT_DUPLICATE_CHOICE;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue