Merge branch 'master' of github.com:jamesagnew/hapi-fhir

This commit is contained in:
James Agnew 2016-08-25 18:27:32 -04:00
commit a1105fac1e
5 changed files with 137 additions and 66 deletions

View File

@ -40,7 +40,7 @@ public enum FhirVersionEnum {
DSTU2_HL7ORG("org.hl7.fhir.instance.FhirDstu2Hl7Org", DSTU2, true, "1.0.2"), DSTU2_HL7ORG("org.hl7.fhir.instance.FhirDstu2Hl7Org", DSTU2, true, "1.0.2"),
DSTU3("org.hl7.fhir.dstu3.hapi.ctx.FhirDstu3", null, true, "1.5.0"); DSTU3("org.hl7.fhir.dstu3.hapi.ctx.FhirDstu3", null, true, "1.6.0");
private final FhirVersionEnum myEquivalent; private final FhirVersionEnum myEquivalent;
private final String myFhirVersionString; private final String myFhirVersionString;

View File

@ -105,6 +105,7 @@ class ParserState<T> {
private final IParser myParser; private final IParser myParser;
private IBase myPreviousElement; private IBase myPreviousElement;
private BaseState myState; private BaseState myState;
private ParserState(IParser theParser, FhirContext theContext, boolean theJsonMode, IParserErrorHandler theErrorHandler) { private ParserState(IParser theParser, FhirContext theContext, boolean theJsonMode, IParserErrorHandler theErrorHandler) {
myParser = theParser; myParser = theParser;
myContext = theContext; myContext = theContext;
@ -223,7 +224,8 @@ class ParserState<T> {
} }
} }
static ParserState<Bundle> getPreAtomInstance(IParser theParser, FhirContext theContext, Class<? extends IBaseResource> theResourceType, boolean theJsonMode, IParserErrorHandler theErrorHandler) throws DataFormatException { static ParserState<Bundle> getPreAtomInstance(IParser theParser, FhirContext theContext, Class<? extends IBaseResource> theResourceType, boolean theJsonMode, IParserErrorHandler theErrorHandler)
throws DataFormatException {
ParserState<Bundle> retVal = new ParserState<Bundle>(theParser, theContext, theJsonMode, theErrorHandler); ParserState<Bundle> retVal = new ParserState<Bundle>(theParser, theContext, theJsonMode, theErrorHandler);
if (theContext.getVersion().getVersion() == FhirVersionEnum.DSTU1) { if (theContext.getVersion().getVersion() == FhirVersionEnum.DSTU1) {
retVal.push(retVal.new PreAtomState(theResourceType)); retVal.push(retVal.new PreAtomState(theResourceType));
@ -237,7 +239,8 @@ class ParserState<T> {
* @param theResourceType * @param theResourceType
* May be null * May be null
*/ */
static <T extends IBaseResource> ParserState<T> getPreResourceInstance(IParser theParser, Class<T> theResourceType, FhirContext theContext, boolean theJsonMode, IParserErrorHandler theErrorHandler) throws DataFormatException { static <T extends IBaseResource> ParserState<T> getPreResourceInstance(IParser theParser, Class<T> theResourceType, FhirContext theContext, boolean theJsonMode, IParserErrorHandler theErrorHandler)
throws DataFormatException {
ParserState<T> retVal = new ParserState<T>(theParser, theContext, theJsonMode, theErrorHandler); ParserState<T> retVal = new ParserState<T>(theParser, theContext, theJsonMode, theErrorHandler);
if (theResourceType == null) { if (theResourceType == null) {
if (theContext.getVersion().getVersion().isRi()) { if (theContext.getVersion().getVersion().isRi()) {
@ -1742,10 +1745,10 @@ class ParserState<T> {
} }
if ("id".equals(theName)) { if ("id".equals(theName)) {
if (getCurrentElement() instanceof IBaseElement) { if (getCurrentElement() instanceof IBaseElement) {
((IBaseElement)getCurrentElement()).setId(theValue); ((IBaseElement) getCurrentElement()).setId(theValue);
return; return;
} else if (getCurrentElement() instanceof IIdentifiableElement) { } else if (getCurrentElement() instanceof IIdentifiableElement) {
((IIdentifiableElement)getCurrentElement()).setElementSpecificId(theValue); ((IIdentifiableElement) getCurrentElement()).setElementSpecificId(theValue);
return; return;
} }
} }
@ -1773,12 +1776,8 @@ class ParserState<T> {
} }
BaseRuntimeElementDefinition<?> target = myContext.getRuntimeChildUndeclaredExtensionDefinition().getChildByName(theLocalPart); BaseRuntimeElementDefinition<?> target = myContext.getRuntimeChildUndeclaredExtensionDefinition().getChildByName(theLocalPart);
if (target == null) {
myErrorHandler.unknownElement(null, theLocalPart);
push(new SwallowChildrenWholeState(getPreResourceState()));
return;
}
if (target != null) {
switch (target.getChildType()) { switch (target.getChildType()) {
case COMPOSITE_DATATYPE: { case COMPOSITE_DATATYPE: {
BaseRuntimeElementCompositeDefinition<?> compositeTarget = (BaseRuntimeElementCompositeDefinition<?>) target; BaseRuntimeElementCompositeDefinition<?> compositeTarget = (BaseRuntimeElementCompositeDefinition<?>) target;
@ -1788,6 +1787,7 @@ class ParserState<T> {
push(newState); push(newState);
return; return;
} }
case ID_DATATYPE:
case PRIMITIVE_DATATYPE: { case PRIMITIVE_DATATYPE: {
RuntimePrimitiveDatatypeDefinition primitiveTarget = (RuntimePrimitiveDatatypeDefinition) target; RuntimePrimitiveDatatypeDefinition primitiveTarget = (RuntimePrimitiveDatatypeDefinition) target;
IPrimitiveType<?> newChildInstance = primitiveTarget.newInstance(); IPrimitiveType<?> newChildInstance = primitiveTarget.newInstance();
@ -1796,19 +1796,15 @@ class ParserState<T> {
push(newState); push(newState);
return; return;
} }
case PRIMITIVE_XHTML:
case RESOURCE:
case RESOURCE_BLOCK:
case UNDECL_EXT:
case EXTENSION_DECLARED:
case CONTAINED_RESOURCES:
case CONTAINED_RESOURCE_LIST:
case ID_DATATYPE:
case PRIMITIVE_XHTML_HL7ORG:
break;
} }
} }
// We hit an invalid type for the extension
myErrorHandler.unknownElement(null, theLocalPart);
push(new SwallowChildrenWholeState(getPreResourceState()));
return;
}
@Override @Override
protected IBaseExtension<?, ?> getCurrentElement() { protected IBaseExtension<?, ?> getCurrentElement() {
return myExtension; return myExtension;
@ -2138,7 +2134,7 @@ class ParserState<T> {
if (wantedProfileType != null && !wantedProfileType.equals(myInstance.getClass())) { if (wantedProfileType != null && !wantedProfileType.equals(myInstance.getClass())) {
if (myResourceType == null || myResourceType.isAssignableFrom(wantedProfileType)) { if (myResourceType == null || myResourceType.isAssignableFrom(wantedProfileType)) {
ourLog.debug("Converting resource of type {} to type defined for profile \"{}\": {}", new Object[] {myInstance.getClass().getName(), usedProfile, wantedProfileType}); ourLog.debug("Converting resource of type {} to type defined for profile \"{}\": {}", new Object[] { myInstance.getClass().getName(), usedProfile, wantedProfileType });
/* /*
* This isn't the most efficient thing really.. If we want a specific * This isn't the most efficient thing really.. If we want a specific
@ -2229,11 +2225,11 @@ class ParserState<T> {
assert theResourceType == null || IResource.class.isAssignableFrom(theResourceType); assert theResourceType == null || IResource.class.isAssignableFrom(theResourceType);
} }
// @Override // @Override
// public void enteringNewElement(String theNamespaceUri, String theLocalPart) throws DataFormatException { // public void enteringNewElement(String theNamespaceUri, String theLocalPart) throws DataFormatException {
// super.enteringNewElement(theNamespaceUri, theLocalPart); // super.enteringNewElement(theNamespaceUri, theLocalPart);
// populateTarget(); // populateTarget();
// } // }
@Override @Override
protected void populateTarget() { protected void populateTarget() {

View File

@ -802,6 +802,21 @@ public class FhirSystemDaoDstu3Test extends BaseJpaDstu3SystemTest {
myPatientDao.read(new IdType("Patient/" + methodName), mySrd); myPatientDao.read(new IdType("Patient/" + methodName), mySrd);
} }
@Test
public void testTransactionCreateWithPutUsingAbsoluteUrl() {
String methodName = "testTransactionCreateWithPutUsingAbsoluteUrl";
Bundle request = new Bundle();
request.setType(BundleType.TRANSACTION);
Patient p = new Patient();
p.addIdentifier().setSystem("urn:system").setValue(methodName);
request.addEntry().setResource(p).getRequest().setMethod(HTTPVerb.PUT).setUrl("http://localhost/server/base/Patient/" + methodName);
mySystemDao.transaction(mySrd, request);
myPatientDao.read(new IdType("Patient/" + methodName), mySrd);
}
@Test @Test
public void testTransactionCreateWithPutUsingUrl2() throws Exception { public void testTransactionCreateWithPutUsingUrl2() throws Exception {
String req = IOUtils.toString(FhirSystemDaoDstu3Test.class.getResourceAsStream("/bundle-dstu3.xml"), StandardCharsets.UTF_8); String req = IOUtils.toString(FhirSystemDaoDstu3Test.class.getResourceAsStream("/bundle-dstu3.xml"), StandardCharsets.UTF_8);

View File

@ -254,7 +254,6 @@ public class XmlParserDstu3Test {
assertEquals("ValueB", pat.getFooParentExtension().getChildB().getValue()); assertEquals("ValueB", pat.getFooParentExtension().getChildB().getValue());
} }
@Test @Test
public void testEncodeAndParseContained() { public void testEncodeAndParseContained() {
IParser xmlParser = ourCtx.newXmlParser().setPrettyPrint(true); IParser xmlParser = ourCtx.newXmlParser().setPrettyPrint(true);
@ -379,6 +378,7 @@ public class XmlParserDstu3Test {
ourCtx = null; ourCtx = null;
} }
@Test @Test
public void testEncodeAndParseContainedNonCustomTypes() { public void testEncodeAndParseContainedNonCustomTypes() {
ourCtx = FhirContext.forDstu3(); ourCtx = FhirContext.forDstu3();
@ -2742,6 +2742,62 @@ public class XmlParserDstu3Test {
assertNotNull(((Reference) actual.getContent().get(0).getP()).getResource()); assertNotNull(((Reference) actual.getContent().get(0).getP()).getResource());
} }
/**
* See #426
*/
@Test
public void testParseExtensionWithIdType() {
//@formatter:off
String input =
"<Patient xmlns=\"http://hl7.org/fhir\">\n" +
" <extension url=\"http://aaa.ch/fhir/Patient#mangedcare\">\n" +
" <extension url=\"http://aaa.ch/fhir/Patient#mangedcare-aaa-id\">\n" +
" <valueId value=\"mc1\"/>\n" +
" </extension>\n" +
" </extension>\n" +
" <identifier>\n" +
" <value value=\"ais111\"/>\n" +
" </identifier>\n" +
"</Patient>";
//@formatter:on
Patient pt = ourCtx.newXmlParser().parseResource(Patient.class, input);
List<Extension> extList = pt.getExtensionsByUrl("http://aaa.ch/fhir/Patient#mangedcare");
extList = extList.get(0).getExtensionsByUrl("http://aaa.ch/fhir/Patient#mangedcare-aaa-id");
Extension ext = extList.get(0);
IdType value = (IdType) ext.getValue();
assertEquals("mc1", value.getValueAsString());
}
/**
* See #426
*
* Value type of FOO isn't a valid datatype
*/
@Test
public void testParseExtensionWithInvalidType() {
//@formatter:off
String input =
"<Patient xmlns=\"http://hl7.org/fhir\">\n" +
" <extension url=\"http://aaa.ch/fhir/Patient#mangedcare\">\n" +
" <extension url=\"http://aaa.ch/fhir/Patient#mangedcare-aaa-id\">\n" +
" <valueFOO value=\"mc1\"/>\n" +
" </extension>\n" +
" </extension>\n" +
" <identifier>\n" +
" <value value=\"ais111\"/>\n" +
" </identifier>\n" +
"</Patient>";
//@formatter:on
Patient pt = ourCtx.newXmlParser().parseResource(Patient.class, input);
List<Extension> extList = pt.getExtensionsByUrl("http://aaa.ch/fhir/Patient#mangedcare");
extList = extList.get(0).getExtensionsByUrl("http://aaa.ch/fhir/Patient#mangedcare-aaa-id");
Extension ext = extList.get(0);
IdType value = (IdType) ext.getValue();
assertEquals(null, value);
}
/** /**
* See #342 * See #342
*/ */

View File

@ -31,7 +31,7 @@
</action> </action>
<action type="add"> <action type="add">
STU3 structure definitions have been updated to the STU3 structure definitions have been updated to the
STU3 ballot candidate versions (1.5.0 - SVN 9395) STU3 ballot candidate versions (1.6.0 - SVN 9395)
</action> </action>
<action type="add"> <action type="add">
Both client and server now support the new Content Types decided in Both client and server now support the new Content Types decided in
@ -206,6 +206,10 @@
Improve performance when parsing resources containing contained resources Improve performance when parsing resources containing contained resources
by eliminating a step where references were woven twice by eliminating a step where references were woven twice
</action> </action>
<action type="fix" issue="426">
Parser failed to parse resources containing an extension with a value type of
"id". Thanks to Raphael Mäder for reporting!
</action>
</release> </release>
<release version="1.6" date="2016-07-07"> <release version="1.6" date="2016-07-07">
<action type="fix"> <action type="fix">
@ -1457,7 +1461,7 @@
search. This is experimental, since it is not a part of the core search. This is experimental, since it is not a part of the core
FHIR specification. FHIR specification.
</action> </action>
<action type="add" fix="250"> <action type="add" issue="250">
Process "Accept: text/xml" and "Accept: text/json" headers was Process "Accept: text/xml" and "Accept: text/json" headers was
wanting the equivalent FHIR encoding styles. These are not wanting the equivalent FHIR encoding styles. These are not
correct, but the intention is clear so we will honour them correct, but the intention is clear so we will honour them
@ -1468,13 +1472,13 @@
codes (specifically, ValueSets which defined concepts containing codes (specifically, ValueSets which defined concepts containing
child concepts did not result in Enum values for the child concepts) child concepts did not result in Enum values for the child concepts)
</action> </action>
<action type="fix" fix="253"> <action type="fix" issue="253">
In the JPA server, order of transaction processing should be In the JPA server, order of transaction processing should be
DELETE, POST, PUT, GET, and the order should not matter DELETE, POST, PUT, GET, and the order should not matter
within entries with the same verb. Thanks to Bill de Beaubien within entries with the same verb. Thanks to Bill de Beaubien
for reporting! for reporting!
</action> </action>
<action type="add" fix="254"> <action type="add" issue="254">
Add the ability to wire JPA conformance providers Add the ability to wire JPA conformance providers
using Spring (basically, add default constructors using Spring (basically, add default constructors
and setters to the conformance providers). Thanks and setters to the conformance providers). Thanks
@ -1571,11 +1575,11 @@
<action type="add"> <action type="add">
JPA server now implements the $validate-code operation JPA server now implements the $validate-code operation
</action> </action>
<action type="add" fix="125"> <action type="add" issue="125">
HAPI-FHIR now has support for _summary and _elements parameters, in server, client, HAPI-FHIR now has support for _summary and _elements parameters, in server, client,
and JPA server. and JPA server.
</action> </action>
<action type="fix" fix="209"> <action type="fix" issue="209">
_revinclude results from JPA server should have a Bundle.entry.search.mode of _revinclude results from JPA server should have a Bundle.entry.search.mode of
"include" and not "match". Thanks to Josh Mandel for reporting! "include" and not "match". Thanks to Josh Mandel for reporting!
</action> </action>
@ -1785,7 +1789,7 @@
Generic/fluent client and JPA server now both support _lastUpdated search parameter Generic/fluent client and JPA server now both support _lastUpdated search parameter
which was added in DSTU2 which was added in DSTU2
</action> </action>
<action name="fix" issue="188"> <action type="fix" issue="188">
JPA server now supports sorting on reference parameters. Thanks to JPA server now supports sorting on reference parameters. Thanks to
Vishal Kachroo for reporting that this wasn't working! Vishal Kachroo for reporting that this wasn't working!
</action> </action>
@ -1869,7 +1873,7 @@
the new syntax required in DSTU2: [resource name]:[search param NAME] the new syntax required in DSTU2: [resource name]:[search param NAME]
insead of the DSTU1 style [resource name].[search param PATH] insead of the DSTU1 style [resource name].[search param PATH]
</action> </action>
<action type="add" fix="124"> <action type="add" issue="124">
When encoding resources, the parser will now convert any resource When encoding resources, the parser will now convert any resource
references to versionless references automatically (i.e. it will references to versionless references automatically (i.e. it will
omit the version part automatically if one is present in the reference) omit the version part automatically if one is present in the reference)
@ -1878,7 +1882,7 @@
reference if the base matches the base for the server giving reference if the base matches the base for the server giving
the response. the response.
</action> </action>
<action type="fix" fix="130"> <action type="fix" issue="130">
Narrative generator incorrectly sets the Resource.text.status to 'generated' even if the Narrative generator incorrectly sets the Resource.text.status to 'generated' even if the
given resource type does not have a template (and therefore no narrative is actually generated). given resource type does not have a template (and therefore no narrative is actually generated).
Thanks to Bill de Beaubien for reporting! Thanks to Bill de Beaubien for reporting!
@ -1886,7 +1890,7 @@
<action type="fix"> <action type="fix">
Searching in JPA server with no search parameter returns deleted resources when it should exclude them. Searching in JPA server with no search parameter returns deleted resources when it should exclude them.
</action> </action>
<action type="add" fix="135"> <action type="add" issue="135">
Remove Eclipse and IntelliJ artifacts (.project, *.iml, etc) from version control. Thanks Remove Eclipse and IntelliJ artifacts (.project, *.iml, etc) from version control. Thanks
to Doug Martin for the suggestion! to Doug Martin for the suggestion!
</action> </action>
@ -2075,7 +2079,7 @@
the method type was a custom resource definition type (instead of a built-in the method type was a custom resource definition type (instead of a built-in
HAPI type). Thanks to Neal Acharya for the analysis. HAPI type). Thanks to Neal Acharya for the analysis.
</action> </action>
<action type="add" fix="79"> <action type="add" issue="79">
JPA server module now supports JPA server module now supports
<![CDATA[<code>_include</code>]]> <![CDATA[<code>_include</code>]]>
value of value of