Skip to content

Commit

Permalink
Merge 11dc917 into 256d541
Browse files Browse the repository at this point in the history
  • Loading branch information
sjanic committed Nov 2, 2017
2 parents 256d541 + 11dc917 commit 9ef3f6a
Show file tree
Hide file tree
Showing 8 changed files with 352 additions and 210 deletions.
Expand Up @@ -613,5 +613,30 @@ public ResourceMetadataKeySupportingAnyResource(String theValue) {
public abstract void put(IAnyResource theResource, T2 theObject);

}

public static final class ExtensionResourceMetadataKey extends ResourceMetadataKeyEnum<ExtensionDt> {
public ExtensionResourceMetadataKey(String url) {
super(url);
}

@Override
public ExtensionDt get(IResource theResource) {
Object retValObj = theResource.getResourceMetadata().get(this);
if (retValObj == null) {
return null;
} else if (retValObj instanceof ExtensionDt) {
return (ExtensionDt) retValObj;
}
throw new InternalErrorException("Found an object of type '" + retValObj.getClass().getCanonicalName()
+ "' in resource metadata for key " + this.name() + " - Expected "
+ ExtensionDt.class.getCanonicalName());
}

@Override
public void put(IResource theResource, ExtensionDt theObject) {
theResource.getResourceMetadata().put(this, theObject);
}
}


}
12 changes: 12 additions & 0 deletions hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/BaseParser.java
Expand Up @@ -911,6 +911,18 @@ protected void throwExceptionForUnknownChildType(BaseRuntimeChildDefinition next
throw new DataFormatException(nextChild + " has no child of type " + theType);
}

protected List<Map.Entry<ResourceMetadataKeyEnum<?>, Object>> getExtensionMetadataKeys(IResource resource) {
List<Map.Entry<ResourceMetadataKeyEnum<?>, Object>> extensionMetadataKeys = new ArrayList<Map.Entry<ResourceMetadataKeyEnum<?>, Object>>();
for (Map.Entry<ResourceMetadataKeyEnum<?>, Object> entry : resource.getResourceMetadata().entrySet()) {
if (entry.getKey() instanceof ResourceMetadataKeyEnum.ExtensionResourceMetadataKey) {
extensionMetadataKeys.add(entry);
}
}

return extensionMetadataKeys;
}


protected static <T> List<T> extractMetadataListNotNull(IResource resource, ResourceMetadataKeyEnum<List<T>> key) {
List<? extends T> securityLabels = key.get(resource);
if (securityLabels == null) {
Expand Down
40 changes: 39 additions & 1 deletion hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/JsonParser.java
Expand Up @@ -651,8 +651,9 @@ private void encodeResourceToJsonStreamWriter(RuntimeResourceDefinition theResDe
if (isBlank(versionIdPart)) {
versionIdPart = ResourceMetadataKeyEnum.VERSION.get(resource);
}
List<Map.Entry<ResourceMetadataKeyEnum<?>, Object>> extensionMetadataKeys = getExtensionMetadataKeys(resource);

if (super.shouldEncodeResourceMeta(resource) && ElementUtil.isEmpty(versionIdPart, updated, securityLabels, tags, profiles) == false) {
if (super.shouldEncodeResourceMeta(resource) && (ElementUtil.isEmpty(versionIdPart, updated, securityLabels, tags, profiles) == false) || !extensionMetadataKeys.isEmpty()) {
beginObject(theEventWriter, "meta");
writeOptionalTagWithTextNode(theEventWriter, "versionId", versionIdPart);
writeOptionalTagWithTextNode(theEventWriter, "lastUpdated", updated);
Expand Down Expand Up @@ -692,6 +693,8 @@ private void encodeResourceToJsonStreamWriter(RuntimeResourceDefinition theResDe
theEventWriter.endArray();
}

addExtensionMetadata(extensionMetadataKeys, theEventWriter);

theEventWriter.endObject(); // end meta
}
}
Expand Down Expand Up @@ -728,6 +731,41 @@ private void encodeResourceToJsonStreamWriter(RuntimeResourceDefinition theResDe
theEventWriter.endObject();
}

private void addExtensionMetadata(List<Map.Entry<ResourceMetadataKeyEnum<?>, Object>> extensionMetadataKeys, JsonLikeWriter theEventWriter) throws IOException {
if (extensionMetadataKeys.isEmpty()) {
return;
}

List<Map.Entry<ResourceMetadataKeyEnum<?>, Object>> extensionKeys = new ArrayList<>(extensionMetadataKeys.size());
List<Map.Entry<ResourceMetadataKeyEnum<?>, Object>> modifierExtensionKeys = new ArrayList<>(extensionKeys.size());
for (Map.Entry<ResourceMetadataKeyEnum<?>, Object> entry : extensionMetadataKeys) {
if (!((ExtensionDt) entry.getValue()).isModifier()) {
extensionKeys.add(entry);
} else {
modifierExtensionKeys.add(entry);
}
}

writeMetadataExtensions(extensionKeys, "extension", theEventWriter);
writeMetadataExtensions(extensionKeys, "modifierExtension", theEventWriter);
}

private void writeMetadataExtensions(List<Map.Entry<ResourceMetadataKeyEnum<?>, Object>> extensions, String arrayName, JsonLikeWriter theEventWriter) throws IOException {
if (extensions.isEmpty()) {
return;
}
beginArray(theEventWriter, arrayName);
for (Map.Entry<ResourceMetadataKeyEnum<?>, Object> key : extensions) {
ExtensionDt extension = (ExtensionDt) key.getValue();
theEventWriter.beginObject();
writeOptionalTagWithTextNode(theEventWriter, "url", extension.getUrl());
String extensionDatatype = myContext.getRuntimeChildUndeclaredExtensionDefinition().getChildNameByDatatype(extension.getValue().getClass());
writeOptionalTagWithTextNode(theEventWriter, extensionDatatype, extension.getValueAsPrimitive());
theEventWriter.endObject();
}
theEventWriter.endArray();
}

/**
* This is useful only for the two cases where extensions are encoded as direct children (e.g. not in some object
* called _name): resource extensions, and extension extensions
Expand Down
19 changes: 19 additions & 0 deletions hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/ParserState.java
Expand Up @@ -841,6 +841,25 @@ public void enteringNewElement(String theNamespaceUri, String theLocalPart) thro
}
}

@Override
public void enteringNewElementExtension(StartElement theElem, String theUrlAttr, boolean theIsModifier, final String baseServerUrl) {
ResourceMetadataKeyEnum.ExtensionResourceMetadataKey resourceMetadataKeyEnum = new ResourceMetadataKeyEnum.ExtensionResourceMetadataKey(theUrlAttr);
Object metadataValue = myMap.get(resourceMetadataKeyEnum);
ExtensionDt newExtension;
if (metadataValue == null) {
newExtension = new ExtensionDt(theIsModifier);
} else if (metadataValue instanceof ExtensionDt) {
newExtension = (ExtensionDt) metadataValue;
} else {
throw new IllegalStateException("Expected ExtensionDt as custom resource metadata type, got: " + metadataValue.getClass().getSimpleName());
}
newExtension.setUrl(theUrlAttr);
myMap.put(resourceMetadataKeyEnum, newExtension);

ExtensionState newState = new ExtensionState(getPreResourceState(), newExtension);
push(newState);
}

}

private class MetaVersionElementState extends BaseState {
Expand Down
@@ -1,9 +1,11 @@
package ca.uhn.fhir.parser;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.stringContainsInOrder;
import static org.hamcrest.core.IsInstanceOf.instanceOf;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
Expand Down Expand Up @@ -1688,19 +1690,65 @@ public void testParseWithExtensions() throws Exception {
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

verify(peh, Mockito.never()).unknownElement(Mockito.isNull(IParseLocation.class), capt.capture());
assertEquals("Smith", p.getName().get(0).getGiven().get(0).getValue());
assertExtensionMetadata(p, "fhir-request-method", false, StringDt.class, "POST");
assertExtensionMetadata(p, "fhir-request-uri", false, UriDt.class, "Patient");
assertExtensionMetadata(p, "modified-fhir-request-method", true, StringDt.class, "POST");
assertExtensionMetadata(p, "modified-fhir-request-uri", true, UriDt.class, "Patient");
}

private void assertExtensionMetadata(
BaseResource resource,
String url,
boolean isModifier,
Class<?> expectedType,
String expectedValue) {
ExtensionDt extension = (ExtensionDt) resource.getResourceMetadata().get(new ResourceMetadataKeyEnum.ExtensionResourceMetadataKey(url));
assertThat(extension.getValue(), instanceOf(expectedType));
assertThat(extension.isModifier(), equalTo(isModifier));
assertThat(extension.getValueAsPrimitive().getValueAsString(), equalTo(expectedValue));
}

@Test
public void testEncodeResourceWithExtensionMetadata() throws Exception {
ProcedureRequest procedureRequest = new ProcedureRequest();
procedureRequest.setStatus(ProcedureRequestStatusEnum.ACCEPTED);
addExtensionResourceMetadataKeyToResource(procedureRequest, false, "http://someurl.com", "SomeValue");
addExtensionResourceMetadataKeyToResource(procedureRequest, false, "http://someurl2.com", "SomeValue2");
addExtensionResourceMetadataKeyToResource(procedureRequest, true, "http://someurl.com/modifier", "SomeValue");
addExtensionResourceMetadataKeyToResource(procedureRequest, true, "http://someurl.com/modifier2", "SomeValue2");

String json = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(procedureRequest);

// @formatter:off
assertThat(json, stringContainsInOrder("\"meta\": {",
"\"extension\": [", "{",
"\"url\": \"http://someurl.com\",",
"\"valueString\": \"SomeValue\"",
"},",
"{",
"\"url\": \"http://someurl2.com\",",
"\"valueString\": \"SomeValue2\"",
"}",
"],",
"\"modifierExtension\": [",
"{",
"\"url\": \"http://someurl.com\",",
"\"valueString\": \"SomeValue\"",
"},",
"{",
"\"url\": \"http://someurl2.com\",",
"\"valueString\": \"SomeValue2\"",
"}",
"]"));
// @formatter:on
}

private void addExtensionResourceMetadataKeyToResource(BaseResource resource, boolean isModifier, String url, String value) {
ExtensionDt extensionDt = new ExtensionDt(isModifier, url, new StringDt(value));
resource.getResourceMetadata()
.put(new ResourceMetadataKeyEnum.ExtensionResourceMetadataKey(extensionDt.getUrl()), extensionDt);
}

@Test
Expand Down
70 changes: 35 additions & 35 deletions hapi-fhir-structures-dstu2/src/test/resources/patient1.json
@@ -1,35 +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"
}
{
"id": "73b551fb-46f5-4fb8-b735-2399344e9717",
"meta": {
"extension": [
{
"url": "fhir-request-method",
"valueString": "POST"
},
{
"url": "fhir-request-uri",
"valueUri": "Patient"
}
],
"modifierExtension": [
{
"url": "modified-fhir-request-method",
"valueString": "POST"
},
{
"url": "modified-fhir-request-uri",
"valueUri": "Patient"
}
],
"versionId": "01e5253d-d258-494c-8d8e-f22ad6d8f19b",
"lastUpdated": "2016-02-20T11:01:56.155Z"
},
"name": [
{
"given": [
"Smith"
]
}
],
"resourceType": "Patient"
}

0 comments on commit 9ef3f6a

Please sign in to comment.