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"),
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 String myFhirVersionString;

View File

@ -10,7 +10,7 @@ package ca.uhn.fhir.parser;
* 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
* 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,
@ -105,6 +105,7 @@ class ParserState<T> {
private final IParser myParser;
private IBase myPreviousElement;
private BaseState myState;
private ParserState(IParser theParser, FhirContext theContext, boolean theJsonMode, IParserErrorHandler theErrorHandler) {
myParser = theParser;
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);
if (theContext.getVersion().getVersion() == FhirVersionEnum.DSTU1) {
retVal.push(retVal.new PreAtomState(theResourceType));
@ -237,7 +239,8 @@ class ParserState<T> {
* @param theResourceType
* 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);
if (theResourceType == null) {
if (theContext.getVersion().getVersion().isRi()) {
@ -1389,7 +1392,7 @@ class ParserState<T> {
@Override
public void wereBack() {
super.wereBack();
IResource res = (IResource) getCurrentElement();
assert res != null;
if (res.getId() == null || res.getId().isEmpty()) {
@ -1582,7 +1585,7 @@ class ParserState<T> {
return;
}
}
/*
* This means we've found an element that doesn't exist on the structure. If the error handler doesn't throw
* an exception, swallow the element silently along with any child elements
@ -1742,10 +1745,10 @@ class ParserState<T> {
}
if ("id".equals(theName)) {
if (getCurrentElement() instanceof IBaseElement) {
((IBaseElement)getCurrentElement()).setId(theValue);
((IBaseElement) getCurrentElement()).setId(theValue);
return;
} else if (getCurrentElement() instanceof IIdentifiableElement) {
((IIdentifiableElement)getCurrentElement()).setElementSpecificId(theValue);
((IIdentifiableElement) getCurrentElement()).setElementSpecificId(theValue);
return;
}
}
@ -1773,42 +1776,35 @@ class ParserState<T> {
}
BaseRuntimeElementDefinition<?> target = myContext.getRuntimeChildUndeclaredExtensionDefinition().getChildByName(theLocalPart);
if (target == null) {
myErrorHandler.unknownElement(null, theLocalPart);
push(new SwallowChildrenWholeState(getPreResourceState()));
return;
if (target != null) {
switch (target.getChildType()) {
case COMPOSITE_DATATYPE: {
BaseRuntimeElementCompositeDefinition<?> compositeTarget = (BaseRuntimeElementCompositeDefinition<?>) target;
ICompositeType newChildInstance = (ICompositeType) compositeTarget.newInstance();
myExtension.setValue(newChildInstance);
ElementCompositeState newState = new ElementCompositeState(getPreResourceState(), compositeTarget, newChildInstance);
push(newState);
return;
}
case ID_DATATYPE:
case PRIMITIVE_DATATYPE: {
RuntimePrimitiveDatatypeDefinition primitiveTarget = (RuntimePrimitiveDatatypeDefinition) target;
IPrimitiveType<?> newChildInstance = primitiveTarget.newInstance();
myExtension.setValue(newChildInstance);
PrimitiveState newState = new PrimitiveState(getPreResourceState(), newChildInstance);
push(newState);
return;
}
}
}
switch (target.getChildType()) {
case COMPOSITE_DATATYPE: {
BaseRuntimeElementCompositeDefinition<?> compositeTarget = (BaseRuntimeElementCompositeDefinition<?>) target;
ICompositeType newChildInstance = (ICompositeType) compositeTarget.newInstance();
myExtension.setValue(newChildInstance);
ElementCompositeState newState = new ElementCompositeState(getPreResourceState(), compositeTarget, newChildInstance);
push(newState);
return;
}
case PRIMITIVE_DATATYPE: {
RuntimePrimitiveDatatypeDefinition primitiveTarget = (RuntimePrimitiveDatatypeDefinition) target;
IPrimitiveType<?> newChildInstance = primitiveTarget.newInstance();
myExtension.setValue(newChildInstance);
PrimitiveState newState = new PrimitiveState(getPreResourceState(), newChildInstance);
push(newState);
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
protected IBaseExtension<?, ?> getCurrentElement() {
return myExtension;
@ -2135,11 +2131,11 @@ class ParserState<T> {
}
}
}
if (wantedProfileType != null && !wantedProfileType.equals(myInstance.getClass())) {
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
* type we just re-parse into that type. The problem is that we don't know
@ -2162,7 +2158,7 @@ class ParserState<T> {
private void stitchBundleCrossReferences() {
final boolean bundle = "Bundle".equals(myContext.getResourceDefinition(myInstance).getName());
if (bundle) {
/*
* Stitch together resource references
*/
@ -2200,7 +2196,7 @@ class ParserState<T> {
}
}
}
}
}
@ -2229,11 +2225,11 @@ class ParserState<T> {
assert theResourceType == null || IResource.class.isAssignableFrom(theResourceType);
}
// @Override
// public void enteringNewElement(String theNamespaceUri, String theLocalPart) throws DataFormatException {
// super.enteringNewElement(theNamespaceUri, theLocalPart);
// populateTarget();
// }
// @Override
// public void enteringNewElement(String theNamespaceUri, String theLocalPart) throws DataFormatException {
// super.enteringNewElement(theNamespaceUri, theLocalPart);
// populateTarget();
// }
@Override
protected void populateTarget() {

View File

@ -802,6 +802,21 @@ public class FhirSystemDaoDstu3Test extends BaseJpaDstu3SystemTest {
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
public void testTransactionCreateWithPutUsingUrl2() throws Exception {
String req = IOUtils.toString(FhirSystemDaoDstu3Test.class.getResourceAsStream("/bundle-dstu3.xml"), StandardCharsets.UTF_8);

View File

@ -185,7 +185,7 @@ public class XmlParserDstu3Test {
o = (Organization) rr.getResource();
assertEquals("ORG", o.getName());
}
@Test
public void testDuration() {
Encounter enc = new Encounter();
@ -236,7 +236,7 @@ public class XmlParserDstu3Test {
assertEquals("Organization/orgid", pt.getManagingOrganization().getReferenceElement().getValue());
assertSame(org, pt.getManagingOrganization().getResource());
}
@Test
public void testEncodeAndParseCompositeExtension() {
PatientWithCustomCompositeExtension pat = new PatientWithCustomCompositeExtension();
@ -253,8 +253,7 @@ public class XmlParserDstu3Test {
assertEquals("ValueA", pat.getFooParentExtension().getChildA().getValue());
assertEquals("ValueB", pat.getFooParentExtension().getChildB().getValue());
}
@Test
public void testEncodeAndParseContained() {
IParser xmlParser = ourCtx.newXmlParser().setPrettyPrint(true);
@ -379,6 +378,7 @@ public class XmlParserDstu3Test {
ourCtx = null;
}
@Test
public void testEncodeAndParseContainedNonCustomTypes() {
ourCtx = FhirContext.forDstu3();
@ -2742,6 +2742,62 @@ public class XmlParserDstu3Test {
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
*/

View File

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