A number of bugfixes around parsing and client implementation
This commit is contained in:
parent
f737797d7a
commit
63c9fb466c
|
@ -7,7 +7,7 @@
|
||||||
</properties>
|
</properties>
|
||||||
<body>
|
<body>
|
||||||
<release version="0.3" date="TBD">
|
<release version="0.3" date="TBD">
|
||||||
<action type="fix" dev="Josh Mandel">
|
<action type="add">
|
||||||
Make it easier to add HTTP Basic Authorization headers to RESTful client requests
|
Make it easier to add HTTP Basic Authorization headers to RESTful client requests
|
||||||
and <![CDATA[<a href="./doc_rest_client.html#HTTP_Basic_Authorization">an example</a>]]>
|
and <![CDATA[<a href="./doc_rest_client.html#HTTP_Basic_Authorization">an example</a>]]>
|
||||||
illustrating how it works
|
illustrating how it works
|
||||||
|
@ -15,6 +15,10 @@
|
||||||
<action type="fix" dev="Josh Mandel">
|
<action type="fix" dev="Josh Mandel">
|
||||||
Correct a dependency on commons-io that was causing issues with the Tinder build
|
Correct a dependency on commons-io that was causing issues with the Tinder build
|
||||||
</action>
|
</action>
|
||||||
|
<action type="fix">
|
||||||
|
Fix an issue where extensions with a resource reference as the value show up incorrectly
|
||||||
|
(wrong element name for undeclared extensions, and empty content for declared extensions)
|
||||||
|
</action>
|
||||||
</release>
|
</release>
|
||||||
</body>
|
</body>
|
||||||
</document>
|
</document>
|
||||||
|
|
|
@ -23,12 +23,15 @@ package ca.uhn.fhir.context;
|
||||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import ca.uhn.fhir.model.api.IElement;
|
import ca.uhn.fhir.model.api.IElement;
|
||||||
|
import ca.uhn.fhir.model.api.IResource;
|
||||||
import ca.uhn.fhir.model.api.annotation.Child;
|
import ca.uhn.fhir.model.api.annotation.Child;
|
||||||
import ca.uhn.fhir.model.api.annotation.Description;
|
import ca.uhn.fhir.model.api.annotation.Description;
|
||||||
import ca.uhn.fhir.model.api.annotation.Extension;
|
import ca.uhn.fhir.model.api.annotation.Extension;
|
||||||
|
@ -133,7 +136,15 @@ public class RuntimeChildDeclaredExtensionDefinition extends BaseRuntimeDeclared
|
||||||
BaseRuntimeElementDefinition<?> elementDef = theClassToElementDefinitions.get(myChildType);
|
BaseRuntimeElementDefinition<?> elementDef = theClassToElementDefinitions.get(myChildType);
|
||||||
if (elementDef instanceof RuntimePrimitiveDatatypeDefinition || elementDef instanceof RuntimeCompositeDatatypeDefinition) {
|
if (elementDef instanceof RuntimePrimitiveDatatypeDefinition || elementDef instanceof RuntimeCompositeDatatypeDefinition) {
|
||||||
myDatatypeChildName = "value" + elementDef.getName().substring(0, 1).toUpperCase() + elementDef.getName().substring(1);
|
myDatatypeChildName = "value" + elementDef.getName().substring(0, 1).toUpperCase() + elementDef.getName().substring(1);
|
||||||
|
if ("valueResourceReference".equals(myDatatypeChildName)) {
|
||||||
|
// Per one of the examples here: http://hl7.org/implement/standards/fhir/extensibility.html#extension
|
||||||
|
myDatatypeChildName = "valueResource";
|
||||||
|
List<Class<? extends IResource>> types = new ArrayList<Class<? extends IResource>>();
|
||||||
|
types.add(IResource.class);
|
||||||
|
myChildDef = new RuntimeResourceReferenceDefinition("valueResource", types);
|
||||||
|
}else {
|
||||||
myChildDef = elementDef;
|
myChildDef = elementDef;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
RuntimeResourceBlockDefinition extDef = ((RuntimeResourceBlockDefinition) elementDef);
|
RuntimeResourceBlockDefinition extDef = ((RuntimeResourceBlockDefinition) elementDef);
|
||||||
for (RuntimeChildDeclaredExtensionDefinition next : extDef.getExtensions()) {
|
for (RuntimeChildDeclaredExtensionDefinition next : extDef.getExtensions()) {
|
||||||
|
|
|
@ -94,7 +94,7 @@ public class RuntimeChildUndeclaredExtensionDefinition extends BaseRuntimeChildD
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resource Reference
|
// Resource Reference
|
||||||
myDatatypeToAttributeName.put(ResourceReferenceDt.class, "valueReference");
|
myDatatypeToAttributeName.put(ResourceReferenceDt.class, "valueResource");
|
||||||
List<Class<? extends IResource>> types = new ArrayList<Class<? extends IResource>>();
|
List<Class<? extends IResource>> types = new ArrayList<Class<? extends IResource>>();
|
||||||
types.add(IResource.class);
|
types.add(IResource.class);
|
||||||
RuntimeResourceReferenceDefinition def = new RuntimeResourceReferenceDefinition("valueResource", types);
|
RuntimeResourceReferenceDefinition def = new RuntimeResourceReferenceDefinition("valueResource", types);
|
||||||
|
|
|
@ -26,7 +26,7 @@ import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target(value= {ElementType.FIELD, ElementType.TYPE})
|
@Target(value= {ElementType.FIELD, ElementType.TYPE, ElementType.PARAMETER})
|
||||||
public @interface Description {
|
public @interface Description {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -59,6 +59,11 @@ public abstract class BaseParser implements IParser {
|
||||||
return parseResource(null, theMessageString);
|
return parseResource(null, theMessageString);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Bundle parseBundle(Reader theReader) {
|
||||||
|
return parseBundle(null, theReader);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IResource parseResource(Reader theReader) throws ConfigurationException, DataFormatException {
|
public IResource parseResource(Reader theReader) throws ConfigurationException, DataFormatException {
|
||||||
return parseResource(null, theReader);
|
return parseResource(null, theReader);
|
||||||
|
|
|
@ -38,17 +38,19 @@ public interface IParser {
|
||||||
|
|
||||||
void encodeResourceToWriter(IResource theResource, Writer stringWriter) throws IOException, DataFormatException;
|
void encodeResourceToWriter(IResource theResource, Writer stringWriter) throws IOException, DataFormatException;
|
||||||
|
|
||||||
|
<T extends IResource> Bundle parseBundle(Class<T> theResourceType, Reader theReader);
|
||||||
|
|
||||||
Bundle parseBundle(Reader theReader);
|
Bundle parseBundle(Reader theReader);
|
||||||
|
|
||||||
Bundle parseBundle(String theMessageString) throws ConfigurationException, DataFormatException;
|
Bundle parseBundle(String theMessageString) throws ConfigurationException, DataFormatException;
|
||||||
|
|
||||||
IResource parseResource(String theMessageString) throws ConfigurationException, DataFormatException;
|
<T extends IResource> T parseResource(Class<T> theResourceType, Reader theReader);
|
||||||
|
|
||||||
IResource parseResource(Reader theReader) throws ConfigurationException, DataFormatException;
|
|
||||||
|
|
||||||
<T extends IResource> T parseResource(Class<T> theResourceType, String theMessageString);
|
<T extends IResource> T parseResource(Class<T> theResourceType, String theMessageString);
|
||||||
|
|
||||||
<T extends IResource> T parseResource(Class<T> theResourceType, Reader theReader);
|
IResource parseResource(Reader theReader) throws ConfigurationException, DataFormatException;
|
||||||
|
|
||||||
|
IResource parseResource(String theMessageString) throws ConfigurationException, DataFormatException;
|
||||||
|
|
||||||
IParser setPrettyPrint(boolean thePrettyPrint);
|
IParser setPrettyPrint(boolean thePrettyPrint);
|
||||||
|
|
||||||
|
|
|
@ -56,9 +56,11 @@ import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
|
||||||
import ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition;
|
import ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition;
|
||||||
import ca.uhn.fhir.context.BaseRuntimeElementDefinition;
|
import ca.uhn.fhir.context.BaseRuntimeElementDefinition;
|
||||||
import ca.uhn.fhir.context.BaseRuntimeElementDefinition.ChildTypeEnum;
|
import ca.uhn.fhir.context.BaseRuntimeElementDefinition.ChildTypeEnum;
|
||||||
|
import ca.uhn.fhir.context.ConfigurationException;
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.context.RuntimeChildDeclaredExtensionDefinition;
|
import ca.uhn.fhir.context.RuntimeChildDeclaredExtensionDefinition;
|
||||||
import ca.uhn.fhir.context.RuntimeChildNarrativeDefinition;
|
import ca.uhn.fhir.context.RuntimeChildNarrativeDefinition;
|
||||||
|
import ca.uhn.fhir.context.RuntimeChildUndeclaredExtensionDefinition;
|
||||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||||
import ca.uhn.fhir.model.api.BaseBundle;
|
import ca.uhn.fhir.model.api.BaseBundle;
|
||||||
import ca.uhn.fhir.model.api.Bundle;
|
import ca.uhn.fhir.model.api.Bundle;
|
||||||
|
@ -83,13 +85,66 @@ import ca.uhn.fhir.narrative.INarrativeGenerator;
|
||||||
|
|
||||||
public class JsonParser extends BaseParser implements IParser {
|
public class JsonParser extends BaseParser implements IParser {
|
||||||
|
|
||||||
|
private static final Set<String> BUNDLE_TEXTNODE_CHILDREN;
|
||||||
|
static {
|
||||||
|
HashSet<String> hashSet = new HashSet<String>();
|
||||||
|
hashSet.add("title");
|
||||||
|
hashSet.add("id");
|
||||||
|
hashSet.add("updated");
|
||||||
|
hashSet.add("published");
|
||||||
|
BUNDLE_TEXTNODE_CHILDREN = Collections.unmodifiableSet(hashSet);
|
||||||
|
}
|
||||||
|
|
||||||
private FhirContext myContext;
|
private FhirContext myContext;
|
||||||
|
|
||||||
private boolean myPrettyPrint;
|
private boolean myPrettyPrint;
|
||||||
|
|
||||||
public JsonParser(FhirContext theContext) {
|
public JsonParser(FhirContext theContext) {
|
||||||
myContext = theContext;
|
myContext = theContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void addToHeldExtensions(int valueIdx, ArrayList<ArrayList<HeldExtension>> list, RuntimeChildDeclaredExtensionDefinition theDef, IElement theValue) {
|
||||||
|
list.ensureCapacity(valueIdx);
|
||||||
|
while (list.size() <= valueIdx) {
|
||||||
|
list.add(null);
|
||||||
|
}
|
||||||
|
if (list.get(valueIdx) == null) {
|
||||||
|
list.set(valueIdx, new ArrayList<JsonParser.HeldExtension>());
|
||||||
|
}
|
||||||
|
list.get(valueIdx).add(new HeldExtension(theDef, theValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addToHeldExtensions(int valueIdx, List<ExtensionDt> ext, ArrayList<ArrayList<HeldExtension>> list) {
|
||||||
|
if (ext.size() > 0) {
|
||||||
|
list.ensureCapacity(valueIdx);
|
||||||
|
while (list.size() <= valueIdx) {
|
||||||
|
list.add(null);
|
||||||
|
}
|
||||||
|
if (list.get(valueIdx) == null) {
|
||||||
|
list.set(valueIdx, new ArrayList<JsonParser.HeldExtension>());
|
||||||
|
}
|
||||||
|
for (ExtensionDt next : ext) {
|
||||||
|
list.get(valueIdx).add(new HeldExtension(next));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertObjectOfType(JsonValue theResourceTypeObj, ValueType theValueType, String thePosition) {
|
||||||
|
if (theResourceTypeObj.getValueType() != theValueType) {
|
||||||
|
throw new DataFormatException("Invalid content of element " + thePosition + ", expected " + theValueType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private JsonGenerator createJsonGenerator(Writer theWriter) {
|
||||||
|
Map<String, Object> properties = new HashMap<String, Object>(1);
|
||||||
|
if (myPrettyPrint) {
|
||||||
|
properties.put(JsonGenerator.PRETTY_PRINTING, myPrettyPrint);
|
||||||
|
}
|
||||||
|
JsonGeneratorFactory jgf = Json.createGeneratorFactory(properties);
|
||||||
|
JsonGenerator eventWriter = jgf.createGenerator(theWriter);
|
||||||
|
return eventWriter;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String encodeBundleToString(Bundle theBundle) throws DataFormatException, IOException {
|
public String encodeBundleToString(Bundle theBundle) throws DataFormatException, IOException {
|
||||||
if (theBundle == null) {
|
if (theBundle == null) {
|
||||||
|
@ -154,324 +209,6 @@ public class JsonParser extends BaseParser implements IParser {
|
||||||
eventWriter.close();
|
eventWriter.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String encodeResourceToString(IResource theResource) throws DataFormatException, IOException {
|
|
||||||
Writer stringWriter = new StringWriter();
|
|
||||||
encodeResourceToWriter(theResource, stringWriter);
|
|
||||||
return stringWriter.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void encodeResourceToWriter(IResource theResource, Writer theWriter) throws IOException {
|
|
||||||
Validate.notNull(theResource, "Resource can not be null");
|
|
||||||
|
|
||||||
JsonGenerator eventWriter = createJsonGenerator(theWriter);
|
|
||||||
|
|
||||||
RuntimeResourceDefinition resDef = myContext.getResourceDefinition(theResource);
|
|
||||||
encodeResourceToJsonStreamWriter(resDef, theResource, eventWriter, null);
|
|
||||||
eventWriter.flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Bundle parseBundle(Reader theReader) {
|
|
||||||
JsonReader reader = Json.createReader(theReader);
|
|
||||||
JsonObject object = reader.readObject();
|
|
||||||
|
|
||||||
JsonValue resourceTypeObj = object.get("resourceType");
|
|
||||||
assertObjectOfType(resourceTypeObj, JsonValue.ValueType.STRING, "resourceType");
|
|
||||||
String resourceType = ((JsonString) resourceTypeObj).getString();
|
|
||||||
if (!"Bundle".equals(resourceType)) {
|
|
||||||
throw new DataFormatException("Trying to parse bundle but found resourceType other than 'Bundle'. Found: '" + resourceType + "'");
|
|
||||||
}
|
|
||||||
|
|
||||||
ParserState<Bundle> state = ParserState.getPreAtomInstance(myContext, true);
|
|
||||||
state.enteringNewElement(null, "feed");
|
|
||||||
|
|
||||||
parseBundleChildren(object, state);
|
|
||||||
|
|
||||||
state.endingElement();
|
|
||||||
|
|
||||||
Bundle retVal = state.getObject();
|
|
||||||
|
|
||||||
return retVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T extends IResource> T parseResource(Class<T> theResourceType, String theMessageString) {
|
|
||||||
return parseResource(theResourceType, new StringReader(theMessageString));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T extends IResource> T parseResource(Class<T> theResourceType, Reader theReader) {
|
|
||||||
JsonReader reader = Json.createReader(theReader);
|
|
||||||
JsonObject object = reader.readObject();
|
|
||||||
|
|
||||||
JsonValue resourceTypeObj = object.get("resourceType");
|
|
||||||
assertObjectOfType(resourceTypeObj, JsonValue.ValueType.STRING, "resourceType");
|
|
||||||
String resourceType = ((JsonString) resourceTypeObj).getString();
|
|
||||||
|
|
||||||
RuntimeResourceDefinition def;
|
|
||||||
if (theResourceType != null) {
|
|
||||||
def = myContext.getResourceDefinition(theResourceType);
|
|
||||||
} else {
|
|
||||||
def = myContext.getResourceDefinition(resourceType);
|
|
||||||
}
|
|
||||||
|
|
||||||
ParserState<? extends IResource> state = ParserState.getPreResourceInstance(def.getImplementingClass(), myContext, true);
|
|
||||||
state.enteringNewElement(null, def.getName());
|
|
||||||
|
|
||||||
parseChildren(object, state);
|
|
||||||
|
|
||||||
state.endingElement();
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
T retVal = (T) state.getObject();
|
|
||||||
|
|
||||||
return retVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void parseChildren(JsonObject theObject, ParserState<?> theState) {
|
|
||||||
String elementId = null;
|
|
||||||
for (String nextName : theObject.keySet()) {
|
|
||||||
if ("resourceType".equals(nextName)) {
|
|
||||||
continue;
|
|
||||||
} else if ("id".equals(nextName)) {
|
|
||||||
elementId = theObject.getString(nextName);
|
|
||||||
continue;
|
|
||||||
} else if ("extension".equals(nextName)) {
|
|
||||||
JsonArray array = theObject.getJsonArray(nextName);
|
|
||||||
parseExtension(theState, array, false);
|
|
||||||
continue;
|
|
||||||
} else if ("modifierExtension".equals(nextName)) {
|
|
||||||
JsonArray array = theObject.getJsonArray(nextName);
|
|
||||||
parseExtension(theState, array, true);
|
|
||||||
continue;
|
|
||||||
} else if (nextName.charAt(0) == '_') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
JsonValue nextVal = theObject.get(nextName);
|
|
||||||
JsonValue alternateVal = theObject.get('_' + nextName);
|
|
||||||
|
|
||||||
parseChildren(theState, nextName, nextVal, alternateVal);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (elementId != null) {
|
|
||||||
IElement object = theState.getObject();
|
|
||||||
if (object instanceof IIdentifiableElement) {
|
|
||||||
((IIdentifiableElement) object).setId(new IdDt(elementId));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final Set<String> BUNDLE_TEXTNODE_CHILDREN;
|
|
||||||
|
|
||||||
static {
|
|
||||||
HashSet<String> hashSet = new HashSet<String>();
|
|
||||||
hashSet.add("title");
|
|
||||||
hashSet.add("id");
|
|
||||||
hashSet.add("updated");
|
|
||||||
hashSet.add("published");
|
|
||||||
BUNDLE_TEXTNODE_CHILDREN = Collections.unmodifiableSet(hashSet);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void parseBundleChildren(JsonObject theObject, ParserState<?> theState) {
|
|
||||||
for (String nextName : theObject.keySet()) {
|
|
||||||
if ("resourceType".equals(nextName)) {
|
|
||||||
continue;
|
|
||||||
} else if ("link".equals(nextName)) {
|
|
||||||
JsonArray entries = theObject.getJsonArray(nextName);
|
|
||||||
for (JsonValue jsonValue : entries) {
|
|
||||||
theState.enteringNewElement(null, "link");
|
|
||||||
JsonObject linkObj = (JsonObject) jsonValue;
|
|
||||||
String rel = linkObj.getString("rel", null);
|
|
||||||
String href = linkObj.getString("href", null);
|
|
||||||
theState.attributeValue("rel", rel);
|
|
||||||
theState.attributeValue("href", href);
|
|
||||||
theState.endingElement();
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
} else if ("entry".equals(nextName)) {
|
|
||||||
JsonArray entries = theObject.getJsonArray(nextName);
|
|
||||||
for (JsonValue jsonValue : entries) {
|
|
||||||
theState.enteringNewElement(null, "entry");
|
|
||||||
parseBundleChildren((JsonObject) jsonValue, theState);
|
|
||||||
theState.endingElement();
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
} else if (BUNDLE_TEXTNODE_CHILDREN.contains(nextName)) {
|
|
||||||
theState.enteringNewElement(null, nextName);
|
|
||||||
theState.string(theObject.getString(nextName, null));
|
|
||||||
theState.endingElement();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
JsonValue nextVal = theObject.get(nextName);
|
|
||||||
parseChildren(theState, nextName, nextVal, null);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void parseChildren(ParserState<?> theState, String theName, JsonValue theJsonVal, JsonValue theAlternateVal) {
|
|
||||||
switch (theJsonVal.getValueType()) {
|
|
||||||
case ARRAY: {
|
|
||||||
JsonArray nextArray = (JsonArray) theJsonVal;
|
|
||||||
JsonArray nextAlternateArray = (JsonArray) theAlternateVal;
|
|
||||||
for (int i = 0; i < nextArray.size(); i++) {
|
|
||||||
JsonValue nextObject = nextArray.get(i);
|
|
||||||
JsonValue nextAlternate = null;
|
|
||||||
if (nextAlternateArray != null) {
|
|
||||||
nextAlternate = nextAlternateArray.get(i);
|
|
||||||
}
|
|
||||||
parseChildren(theState, theName, nextObject, nextAlternate);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case OBJECT: {
|
|
||||||
theState.enteringNewElement(null, theName);
|
|
||||||
parseAlternates(theAlternateVal, theState);
|
|
||||||
JsonObject nextObject = (JsonObject) theJsonVal;
|
|
||||||
boolean preResource = false;
|
|
||||||
if (theState.isPreResource()) {
|
|
||||||
String resType = nextObject.getString("resourceType");
|
|
||||||
if (isBlank(resType)) {
|
|
||||||
throw new DataFormatException("Missing 'resourceType' from resource");
|
|
||||||
}
|
|
||||||
theState.enteringNewElement(null, resType);
|
|
||||||
preResource = true;
|
|
||||||
}
|
|
||||||
parseChildren(nextObject, theState);
|
|
||||||
if (preResource) {
|
|
||||||
theState.endingElement();
|
|
||||||
}
|
|
||||||
theState.endingElement();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case STRING: {
|
|
||||||
JsonString nextValStr = (JsonString) theJsonVal;
|
|
||||||
theState.enteringNewElement(null, theName);
|
|
||||||
theState.attributeValue("value", nextValStr.getString());
|
|
||||||
parseAlternates(theAlternateVal, theState);
|
|
||||||
theState.endingElement();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case NUMBER:
|
|
||||||
case FALSE:
|
|
||||||
case TRUE:
|
|
||||||
theState.enteringNewElement(null, theName);
|
|
||||||
theState.attributeValue("value", theJsonVal.toString());
|
|
||||||
parseAlternates(theAlternateVal, theState);
|
|
||||||
theState.endingElement();
|
|
||||||
break;
|
|
||||||
case NULL:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void parseAlternates(JsonValue theAlternateVal, ParserState<?> theState) {
|
|
||||||
if (theAlternateVal == null || theAlternateVal.getValueType() == ValueType.NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
JsonObject alternate = (JsonObject) theAlternateVal;
|
|
||||||
for (Entry<String, JsonValue> nextEntry : alternate.entrySet()) {
|
|
||||||
String nextKey = nextEntry.getKey();
|
|
||||||
JsonValue nextVal = nextEntry.getValue();
|
|
||||||
if ("extension".equals(nextKey)) {
|
|
||||||
boolean isModifier = false;
|
|
||||||
JsonArray array = (JsonArray) nextEntry.getValue();
|
|
||||||
parseExtension(theState, array, isModifier);
|
|
||||||
} else if ("modifierExtension".equals(nextKey)) {
|
|
||||||
boolean isModifier = true;
|
|
||||||
JsonArray array = (JsonArray) nextEntry.getValue();
|
|
||||||
parseExtension(theState, array, isModifier);
|
|
||||||
} else if ("id".equals(nextKey)) {
|
|
||||||
switch (nextVal.getValueType()) {
|
|
||||||
case STRING:
|
|
||||||
theState.attributeValue("id", ((JsonString) nextVal).getString());
|
|
||||||
break;
|
|
||||||
case NULL:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void parseExtension(ParserState<?> theState, JsonArray array, boolean theIsModifier) {
|
|
||||||
// TODO: use theIsModifier
|
|
||||||
for (int i = 0; i < array.size(); i++) {
|
|
||||||
JsonObject nextExtObj = array.getJsonObject(i);
|
|
||||||
String url = nextExtObj.getString("url");
|
|
||||||
theState.enteringNewElementExtension(null, url, theIsModifier);
|
|
||||||
for (Iterator<String> iter = nextExtObj.keySet().iterator(); iter.hasNext();) {
|
|
||||||
String next = iter.next();
|
|
||||||
if ("url".equals(next)) {
|
|
||||||
continue;
|
|
||||||
} else if ("extension".equals(next)) {
|
|
||||||
JsonArray jsonVal = (JsonArray) nextExtObj.get(next);
|
|
||||||
parseExtension(theState, jsonVal, false);
|
|
||||||
} else if ("modifierExtension".equals(next)) {
|
|
||||||
JsonArray jsonVal = (JsonArray) nextExtObj.get(next);
|
|
||||||
parseExtension(theState, jsonVal, true);
|
|
||||||
} else {
|
|
||||||
JsonValue jsonVal = nextExtObj.get(next);
|
|
||||||
parseChildren(theState, next, jsonVal, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
theState.endingElement();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IParser setPrettyPrint(boolean thePrettyPrint) {
|
|
||||||
myPrettyPrint = thePrettyPrint;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addToHeldExtensions(int valueIdx, List<ExtensionDt> ext, ArrayList<ArrayList<HeldExtension>> list) {
|
|
||||||
if (ext.size() > 0) {
|
|
||||||
list.ensureCapacity(valueIdx);
|
|
||||||
while (list.size() <= valueIdx) {
|
|
||||||
list.add(null);
|
|
||||||
}
|
|
||||||
if (list.get(valueIdx) == null) {
|
|
||||||
list.set(valueIdx, new ArrayList<JsonParser.HeldExtension>());
|
|
||||||
}
|
|
||||||
for (ExtensionDt next : ext) {
|
|
||||||
list.get(valueIdx).add(new HeldExtension(next));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addToHeldExtensions(int valueIdx, ArrayList<ArrayList<HeldExtension>> list, RuntimeChildDeclaredExtensionDefinition theDef, IElement theValue) {
|
|
||||||
list.ensureCapacity(valueIdx);
|
|
||||||
while (list.size() <= valueIdx) {
|
|
||||||
list.add(null);
|
|
||||||
}
|
|
||||||
if (list.get(valueIdx) == null) {
|
|
||||||
list.set(valueIdx, new ArrayList<JsonParser.HeldExtension>());
|
|
||||||
}
|
|
||||||
list.get(valueIdx).add(new HeldExtension(theDef, theValue));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void assertObjectOfType(JsonValue theResourceTypeObj, ValueType theValueType, String thePosition) {
|
|
||||||
if (theResourceTypeObj.getValueType() != theValueType) {
|
|
||||||
throw new DataFormatException("Invalid content of element " + thePosition + ", expected " + theValueType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private JsonGenerator createJsonGenerator(Writer theWriter) {
|
|
||||||
Map<String, Object> properties = new HashMap<String, Object>(1);
|
|
||||||
if (myPrettyPrint) {
|
|
||||||
properties.put(JsonGenerator.PRETTY_PRINTING, myPrettyPrint);
|
|
||||||
}
|
|
||||||
JsonGeneratorFactory jgf = Json.createGeneratorFactory(properties);
|
|
||||||
JsonGenerator eventWriter = jgf.createGenerator(theWriter);
|
|
||||||
return eventWriter;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void encodeChildElementToStreamWriter(RuntimeResourceDefinition theResDef, IResource theResource, JsonGenerator theWriter, IElement theValue, BaseRuntimeElementDefinition<?> theChildDef,
|
private void encodeChildElementToStreamWriter(RuntimeResourceDefinition theResDef, IResource theResource, JsonGenerator theWriter, IElement theValue, BaseRuntimeElementDefinition<?> theChildDef,
|
||||||
String theChildName) throws IOException {
|
String theChildName) throws IOException {
|
||||||
|
|
||||||
|
@ -736,6 +473,24 @@ public class JsonParser extends BaseParser implements IParser {
|
||||||
theEventWriter.writeEnd();
|
theEventWriter.writeEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String encodeResourceToString(IResource theResource) throws DataFormatException, IOException {
|
||||||
|
Writer stringWriter = new StringWriter();
|
||||||
|
encodeResourceToWriter(theResource, stringWriter);
|
||||||
|
return stringWriter.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void encodeResourceToWriter(IResource theResource, Writer theWriter) throws IOException {
|
||||||
|
Validate.notNull(theResource, "Resource can not be null");
|
||||||
|
|
||||||
|
JsonGenerator eventWriter = createJsonGenerator(theWriter);
|
||||||
|
|
||||||
|
RuntimeResourceDefinition resDef = myContext.getResourceDefinition(theResource);
|
||||||
|
encodeResourceToJsonStreamWriter(resDef, theResource, eventWriter, null);
|
||||||
|
eventWriter.flush();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
* 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
|
||||||
*/
|
*/
|
||||||
|
@ -754,21 +509,20 @@ public class JsonParser extends BaseParser implements IParser {
|
||||||
writeExtensionsAsDirectChild(theResource, theEventWriter, theResDef, extensions, modifierExtensions);
|
writeExtensionsAsDirectChild(theResource, theEventWriter, theResDef, extensions, modifierExtensions);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeExtensionsAsDirectChild(IResource theResource, JsonGenerator theEventWriter, RuntimeResourceDefinition resDef, List<HeldExtension> extensions,
|
private void extractDeclaredExtensions(IElement theResource, BaseRuntimeElementDefinition<?> resDef, List<HeldExtension> extensions, List<HeldExtension> modifierExtensions) {
|
||||||
List<HeldExtension> modifierExtensions) throws IOException {
|
for (RuntimeChildDeclaredExtensionDefinition nextDef : resDef.getExtensionsNonModifier()) {
|
||||||
if (extensions.isEmpty() == false) {
|
for (IElement nextValue : nextDef.getAccessor().getValues(theResource)) {
|
||||||
theEventWriter.writeStartArray("extension");
|
if (nextValue != null) {
|
||||||
for (HeldExtension next : extensions) {
|
extensions.add(new HeldExtension(nextDef, nextValue));
|
||||||
next.write(resDef, theResource, theEventWriter);
|
|
||||||
}
|
}
|
||||||
theEventWriter.writeEnd();
|
|
||||||
}
|
}
|
||||||
if (modifierExtensions.isEmpty() == false) {
|
|
||||||
theEventWriter.writeStartArray("modifierExtension");
|
|
||||||
for (HeldExtension next : modifierExtensions) {
|
|
||||||
next.write(resDef, theResource, theEventWriter);
|
|
||||||
}
|
}
|
||||||
theEventWriter.writeEnd();
|
for (RuntimeChildDeclaredExtensionDefinition nextDef : resDef.getExtensionsModifier()) {
|
||||||
|
for (IElement nextValue : nextDef.getAccessor().getValues(theResource)) {
|
||||||
|
if (nextValue != null) {
|
||||||
|
modifierExtensions.add(new HeldExtension(nextDef, nextValue));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -786,21 +540,252 @@ public class JsonParser extends BaseParser implements IParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void extractDeclaredExtensions(IElement theResource, BaseRuntimeElementDefinition<?> resDef, List<HeldExtension> extensions, List<HeldExtension> modifierExtensions) {
|
private void parseAlternates(JsonValue theAlternateVal, ParserState<?> theState) {
|
||||||
for (RuntimeChildDeclaredExtensionDefinition nextDef : resDef.getExtensionsNonModifier()) {
|
if (theAlternateVal == null || theAlternateVal.getValueType() == ValueType.NULL) {
|
||||||
for (IElement nextValue : nextDef.getAccessor().getValues(theResource)) {
|
return;
|
||||||
if (nextValue != null) {
|
}
|
||||||
extensions.add(new HeldExtension(nextDef, nextValue));
|
JsonObject alternate = (JsonObject) theAlternateVal;
|
||||||
|
for (Entry<String, JsonValue> nextEntry : alternate.entrySet()) {
|
||||||
|
String nextKey = nextEntry.getKey();
|
||||||
|
JsonValue nextVal = nextEntry.getValue();
|
||||||
|
if ("extension".equals(nextKey)) {
|
||||||
|
boolean isModifier = false;
|
||||||
|
JsonArray array = (JsonArray) nextEntry.getValue();
|
||||||
|
parseExtension(theState, array, isModifier);
|
||||||
|
} else if ("modifierExtension".equals(nextKey)) {
|
||||||
|
boolean isModifier = true;
|
||||||
|
JsonArray array = (JsonArray) nextEntry.getValue();
|
||||||
|
parseExtension(theState, array, isModifier);
|
||||||
|
} else if ("id".equals(nextKey)) {
|
||||||
|
switch (nextVal.getValueType()) {
|
||||||
|
case STRING:
|
||||||
|
theState.attributeValue("id", ((JsonString) nextVal).getString());
|
||||||
|
break;
|
||||||
|
case NULL:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (RuntimeChildDeclaredExtensionDefinition nextDef : resDef.getExtensionsModifier()) {
|
}
|
||||||
for (IElement nextValue : nextDef.getAccessor().getValues(theResource)) {
|
|
||||||
if (nextValue != null) {
|
@Override
|
||||||
modifierExtensions.add(new HeldExtension(nextDef, nextValue));
|
public <T extends IResource> Bundle parseBundle(Class<T> theResourceType, Reader theReader) {
|
||||||
|
JsonReader reader = Json.createReader(theReader);
|
||||||
|
JsonObject object = reader.readObject();
|
||||||
|
|
||||||
|
JsonValue resourceTypeObj = object.get("resourceType");
|
||||||
|
assertObjectOfType(resourceTypeObj, JsonValue.ValueType.STRING, "resourceType");
|
||||||
|
String resourceType = ((JsonString) resourceTypeObj).getString();
|
||||||
|
if (!"Bundle".equals(resourceType)) {
|
||||||
|
throw new DataFormatException("Trying to parse bundle but found resourceType other than 'Bundle'. Found: '" + resourceType + "'");
|
||||||
|
}
|
||||||
|
|
||||||
|
ParserState<Bundle> state = ParserState.getPreAtomInstance(myContext, theResourceType, true);
|
||||||
|
state.enteringNewElement(null, "feed");
|
||||||
|
|
||||||
|
parseBundleChildren(object, state);
|
||||||
|
|
||||||
|
state.endingElement();
|
||||||
|
|
||||||
|
Bundle retVal = state.getObject();
|
||||||
|
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void parseBundleChildren(JsonObject theObject, ParserState<?> theState) {
|
||||||
|
for (String nextName : theObject.keySet()) {
|
||||||
|
if ("resourceType".equals(nextName)) {
|
||||||
|
continue;
|
||||||
|
} else if ("link".equals(nextName)) {
|
||||||
|
JsonArray entries = theObject.getJsonArray(nextName);
|
||||||
|
for (JsonValue jsonValue : entries) {
|
||||||
|
theState.enteringNewElement(null, "link");
|
||||||
|
JsonObject linkObj = (JsonObject) jsonValue;
|
||||||
|
String rel = linkObj.getString("rel", null);
|
||||||
|
String href = linkObj.getString("href", null);
|
||||||
|
theState.attributeValue("rel", rel);
|
||||||
|
theState.attributeValue("href", href);
|
||||||
|
theState.endingElement();
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
} else if ("entry".equals(nextName)) {
|
||||||
|
JsonArray entries = theObject.getJsonArray(nextName);
|
||||||
|
for (JsonValue jsonValue : entries) {
|
||||||
|
theState.enteringNewElement(null, "entry");
|
||||||
|
parseBundleChildren((JsonObject) jsonValue, theState);
|
||||||
|
theState.endingElement();
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
} else if (BUNDLE_TEXTNODE_CHILDREN.contains(nextName)) {
|
||||||
|
theState.enteringNewElement(null, nextName);
|
||||||
|
theState.string(theObject.getString(nextName, null));
|
||||||
|
theState.endingElement();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonValue nextVal = theObject.get(nextName);
|
||||||
|
parseChildren(theState, nextName, nextVal, null);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parseChildren(JsonObject theObject, ParserState<?> theState) {
|
||||||
|
String elementId = null;
|
||||||
|
for (String nextName : theObject.keySet()) {
|
||||||
|
if ("resourceType".equals(nextName)) {
|
||||||
|
continue;
|
||||||
|
} else if ("id".equals(nextName)) {
|
||||||
|
elementId = theObject.getString(nextName);
|
||||||
|
continue;
|
||||||
|
} else if ("extension".equals(nextName)) {
|
||||||
|
JsonArray array = theObject.getJsonArray(nextName);
|
||||||
|
parseExtension(theState, array, false);
|
||||||
|
continue;
|
||||||
|
} else if ("modifierExtension".equals(nextName)) {
|
||||||
|
JsonArray array = theObject.getJsonArray(nextName);
|
||||||
|
parseExtension(theState, array, true);
|
||||||
|
continue;
|
||||||
|
} else if (nextName.charAt(0) == '_') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonValue nextVal = theObject.get(nextName);
|
||||||
|
JsonValue alternateVal = theObject.get('_' + nextName);
|
||||||
|
|
||||||
|
parseChildren(theState, nextName, nextVal, alternateVal);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (elementId != null) {
|
||||||
|
IElement object = theState.getObject();
|
||||||
|
if (object instanceof IIdentifiableElement) {
|
||||||
|
((IIdentifiableElement) object).setId(new IdDt(elementId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void parseChildren(ParserState<?> theState, String theName, JsonValue theJsonVal, JsonValue theAlternateVal) {
|
||||||
|
switch (theJsonVal.getValueType()) {
|
||||||
|
case ARRAY: {
|
||||||
|
JsonArray nextArray = (JsonArray) theJsonVal;
|
||||||
|
JsonArray nextAlternateArray = (JsonArray) theAlternateVal;
|
||||||
|
for (int i = 0; i < nextArray.size(); i++) {
|
||||||
|
JsonValue nextObject = nextArray.get(i);
|
||||||
|
JsonValue nextAlternate = null;
|
||||||
|
if (nextAlternateArray != null) {
|
||||||
|
nextAlternate = nextAlternateArray.get(i);
|
||||||
|
}
|
||||||
|
parseChildren(theState, theName, nextObject, nextAlternate);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OBJECT: {
|
||||||
|
theState.enteringNewElement(null, theName);
|
||||||
|
parseAlternates(theAlternateVal, theState);
|
||||||
|
JsonObject nextObject = (JsonObject) theJsonVal;
|
||||||
|
boolean preResource = false;
|
||||||
|
if (theState.isPreResource()) {
|
||||||
|
String resType = nextObject.getString("resourceType");
|
||||||
|
if (isBlank(resType)) {
|
||||||
|
throw new DataFormatException("Missing 'resourceType' from resource");
|
||||||
|
}
|
||||||
|
theState.enteringNewElement(null, resType);
|
||||||
|
preResource = true;
|
||||||
|
}
|
||||||
|
parseChildren(nextObject, theState);
|
||||||
|
if (preResource) {
|
||||||
|
theState.endingElement();
|
||||||
|
}
|
||||||
|
theState.endingElement();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case STRING: {
|
||||||
|
JsonString nextValStr = (JsonString) theJsonVal;
|
||||||
|
theState.enteringNewElement(null, theName);
|
||||||
|
theState.attributeValue("value", nextValStr.getString());
|
||||||
|
parseAlternates(theAlternateVal, theState);
|
||||||
|
theState.endingElement();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case NUMBER:
|
||||||
|
case FALSE:
|
||||||
|
case TRUE:
|
||||||
|
theState.enteringNewElement(null, theName);
|
||||||
|
theState.attributeValue("value", theJsonVal.toString());
|
||||||
|
parseAlternates(theAlternateVal, theState);
|
||||||
|
theState.endingElement();
|
||||||
|
break;
|
||||||
|
case NULL:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parseExtension(ParserState<?> theState, JsonArray array, boolean theIsModifier) {
|
||||||
|
// TODO: use theIsModifier
|
||||||
|
for (int i = 0; i < array.size(); i++) {
|
||||||
|
JsonObject nextExtObj = array.getJsonObject(i);
|
||||||
|
String url = nextExtObj.getString("url");
|
||||||
|
theState.enteringNewElementExtension(null, url, theIsModifier);
|
||||||
|
for (Iterator<String> iter = nextExtObj.keySet().iterator(); iter.hasNext();) {
|
||||||
|
String next = iter.next();
|
||||||
|
if ("url".equals(next)) {
|
||||||
|
continue;
|
||||||
|
} else if ("extension".equals(next)) {
|
||||||
|
JsonArray jsonVal = (JsonArray) nextExtObj.get(next);
|
||||||
|
parseExtension(theState, jsonVal, false);
|
||||||
|
} else if ("modifierExtension".equals(next)) {
|
||||||
|
JsonArray jsonVal = (JsonArray) nextExtObj.get(next);
|
||||||
|
parseExtension(theState, jsonVal, true);
|
||||||
|
} else {
|
||||||
|
JsonValue jsonVal = nextExtObj.get(next);
|
||||||
|
parseChildren(theState, next, jsonVal, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
theState.endingElement();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T extends IResource> T parseResource(Class<T> theResourceType, Reader theReader) {
|
||||||
|
JsonReader reader = Json.createReader(theReader);
|
||||||
|
JsonObject object = reader.readObject();
|
||||||
|
|
||||||
|
JsonValue resourceTypeObj = object.get("resourceType");
|
||||||
|
assertObjectOfType(resourceTypeObj, JsonValue.ValueType.STRING, "resourceType");
|
||||||
|
String resourceType = ((JsonString) resourceTypeObj).getString();
|
||||||
|
|
||||||
|
RuntimeResourceDefinition def;
|
||||||
|
if (theResourceType != null) {
|
||||||
|
def = myContext.getResourceDefinition(theResourceType);
|
||||||
|
} else {
|
||||||
|
def = myContext.getResourceDefinition(resourceType);
|
||||||
|
}
|
||||||
|
|
||||||
|
ParserState<? extends IResource> state = ParserState.getPreResourceInstance(def.getImplementingClass(), myContext, true);
|
||||||
|
state.enteringNewElement(null, def.getName());
|
||||||
|
|
||||||
|
parseChildren(object, state);
|
||||||
|
|
||||||
|
state.endingElement();
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
T retVal = (T) state.getObject();
|
||||||
|
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T extends IResource> T parseResource(Class<T> theResourceType, String theMessageString) {
|
||||||
|
return parseResource(theResourceType, new StringReader(theMessageString));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IParser setPrettyPrint(boolean thePrettyPrint) {
|
||||||
|
myPrettyPrint = thePrettyPrint;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeAtomLink(JsonGenerator theEventWriter, String theRel, StringDt theLink) {
|
private void writeAtomLink(JsonGenerator theEventWriter, String theRel, StringDt theLink) {
|
||||||
|
@ -823,6 +808,24 @@ public class JsonParser extends BaseParser implements IParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void writeExtensionsAsDirectChild(IResource theResource, JsonGenerator theEventWriter, RuntimeResourceDefinition resDef, List<HeldExtension> extensions,
|
||||||
|
List<HeldExtension> modifierExtensions) throws IOException {
|
||||||
|
if (extensions.isEmpty() == false) {
|
||||||
|
theEventWriter.writeStartArray("extension");
|
||||||
|
for (HeldExtension next : extensions) {
|
||||||
|
next.write(resDef, theResource, theEventWriter);
|
||||||
|
}
|
||||||
|
theEventWriter.writeEnd();
|
||||||
|
}
|
||||||
|
if (modifierExtensions.isEmpty() == false) {
|
||||||
|
theEventWriter.writeStartArray("modifierExtension");
|
||||||
|
for (HeldExtension next : modifierExtensions) {
|
||||||
|
next.write(resDef, theResource, theEventWriter);
|
||||||
|
}
|
||||||
|
theEventWriter.writeEnd();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void writeOptionalTagWithTextNode(JsonGenerator theEventWriter, String theElementName, IPrimitiveDatatype<?> theInstantDt) {
|
private void writeOptionalTagWithTextNode(JsonGenerator theEventWriter, String theElementName, IPrimitiveDatatype<?> theInstantDt) {
|
||||||
String str = theInstantDt.getValueAsString();
|
String str = theInstantDt.getValueAsString();
|
||||||
if (StringUtils.isNotBlank(str)) {
|
if (StringUtils.isNotBlank(str)) {
|
||||||
|
@ -830,14 +833,6 @@ public class JsonParser extends BaseParser implements IParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeTagWithTextNode(JsonGenerator theEventWriter, String theElementName, StringDt theStringDt) {
|
|
||||||
if (StringUtils.isNotBlank(theStringDt.getValue())) {
|
|
||||||
theEventWriter.write(theElementName, theStringDt.getValue());
|
|
||||||
} else {
|
|
||||||
theEventWriter.writeNull(theElementName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void writeTagWithTextNode(JsonGenerator theEventWriter, String theElementName, IdDt theIdDt) {
|
private void writeTagWithTextNode(JsonGenerator theEventWriter, String theElementName, IdDt theIdDt) {
|
||||||
if (StringUtils.isNotBlank(theIdDt.getValue())) {
|
if (StringUtils.isNotBlank(theIdDt.getValue())) {
|
||||||
theEventWriter.write(theElementName, theIdDt.getValue());
|
theEventWriter.write(theElementName, theIdDt.getValue());
|
||||||
|
@ -846,10 +841,18 @@ public class JsonParser extends BaseParser implements IParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void writeTagWithTextNode(JsonGenerator theEventWriter, String theElementName, StringDt theStringDt) {
|
||||||
|
if (StringUtils.isNotBlank(theStringDt.getValue())) {
|
||||||
|
theEventWriter.write(theElementName, theStringDt.getValue());
|
||||||
|
} else {
|
||||||
|
theEventWriter.writeNull(theElementName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private class HeldExtension {
|
private class HeldExtension {
|
||||||
|
|
||||||
private ExtensionDt myUndeclaredExtension;
|
|
||||||
private RuntimeChildDeclaredExtensionDefinition myDef;
|
private RuntimeChildDeclaredExtensionDefinition myDef;
|
||||||
|
private ExtensionDt myUndeclaredExtension;
|
||||||
private IElement myValue;
|
private IElement myValue;
|
||||||
|
|
||||||
public HeldExtension(ExtensionDt theUndeclaredExtension) {
|
public HeldExtension(ExtensionDt theUndeclaredExtension) {
|
||||||
|
@ -875,7 +878,9 @@ public class JsonParser extends BaseParser implements IParser {
|
||||||
if (def.getChildType() == ChildTypeEnum.RESOURCE_BLOCK) {
|
if (def.getChildType() == ChildTypeEnum.RESOURCE_BLOCK) {
|
||||||
extractAndWriteExtensionsAsDirectChild(myValue, theEventWriter, def, theResDef, theResource);
|
extractAndWriteExtensionsAsDirectChild(myValue, theEventWriter, def, theResDef, theResource);
|
||||||
} else {
|
} else {
|
||||||
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, myValue, def, "value" + WordUtils.capitalize(def.getName()));
|
// encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, myValue, def, "value" + WordUtils.capitalize(def.getName()));
|
||||||
|
String childName = myDef.getChildNameByDatatype(myValue.getClass());
|
||||||
|
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, myValue, def, childName);
|
||||||
}
|
}
|
||||||
|
|
||||||
// theEventWriter.name(myUndeclaredExtension.get);
|
// theEventWriter.name(myUndeclaredExtension.get);
|
||||||
|
@ -898,9 +903,13 @@ public class JsonParser extends BaseParser implements IParser {
|
||||||
}
|
}
|
||||||
theEventWriter.writeEnd();
|
theEventWriter.writeEnd();
|
||||||
} else {
|
} else {
|
||||||
BaseRuntimeElementDefinition<?> def = myContext.getElementDefinition(value.getClass());
|
RuntimeChildUndeclaredExtensionDefinition extDef = myContext.getRuntimeChildUndeclaredExtensionDefinition();
|
||||||
// theEventWriter.writeName("value" + def.getName());
|
String childName = extDef.getChildNameByDatatype(value.getClass());
|
||||||
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, value, def, "value" + WordUtils.capitalize(def.getName()));
|
if (childName == null) {
|
||||||
|
throw new ConfigurationException("Unable to encode extension, unregognized child element type: " + value.getClass().getCanonicalName());
|
||||||
|
}
|
||||||
|
BaseRuntimeElementDefinition<?> childDef = extDef.getChildElementDefinitionByDatatype(value.getClass());
|
||||||
|
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, value, childDef, childName);
|
||||||
}
|
}
|
||||||
|
|
||||||
// theEventWriter.name(myUndeclaredExtension.get);
|
// theEventWriter.name(myUndeclaredExtension.get);
|
||||||
|
|
|
@ -131,9 +131,9 @@ class ParserState<T extends IElement> {
|
||||||
myState = theState;
|
myState = theState;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ParserState<Bundle> getPreAtomInstance(FhirContext theContext, boolean theJsonMode) throws DataFormatException {
|
public static ParserState<Bundle> getPreAtomInstance(FhirContext theContext, Class<? extends IResource> theResourceType, boolean theJsonMode) throws DataFormatException {
|
||||||
ParserState<Bundle> retVal = new ParserState<Bundle>(theContext, theJsonMode);
|
ParserState<Bundle> retVal = new ParserState<Bundle>(theContext, theJsonMode);
|
||||||
retVal.push(retVal.new PreAtomState());
|
retVal.push(retVal.new PreAtomState(theResourceType));
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,10 +209,12 @@ class ParserState<T extends IElement> {
|
||||||
public class AtomEntryState extends BaseState {
|
public class AtomEntryState extends BaseState {
|
||||||
|
|
||||||
private BundleEntry myEntry;
|
private BundleEntry myEntry;
|
||||||
|
private Class<? extends IResource> myResourceType;
|
||||||
|
|
||||||
public AtomEntryState(Bundle theInstance) {
|
public AtomEntryState(Bundle theInstance, Class<? extends IResource> theResourceType) {
|
||||||
super(null);
|
super(null);
|
||||||
myEntry = new BundleEntry();
|
myEntry = new BundleEntry();
|
||||||
|
myResourceType = theResourceType;
|
||||||
theInstance.getEntries().add(myEntry);
|
theInstance.getEntries().add(myEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,7 +277,7 @@ class ParserState<T extends IElement> {
|
||||||
} else if ("author".equals(theLocalPart)) {
|
} else if ("author".equals(theLocalPart)) {
|
||||||
push(new AtomAuthorState(myEntry));
|
push(new AtomAuthorState(myEntry));
|
||||||
} else if ("content".equals(theLocalPart)) {
|
} else if ("content".equals(theLocalPart)) {
|
||||||
push(new PreResourceState(myEntry));
|
push(new PreResourceState(myEntry, myResourceType));
|
||||||
} else if ("summary".equals(theLocalPart)) {
|
} else if ("summary".equals(theLocalPart)) {
|
||||||
push(new XhtmlState(getPreResourceState(), myEntry.getSummary(), false));
|
push(new XhtmlState(getPreResourceState(), myEntry.getSummary(), false));
|
||||||
} else if ("category".equals(theLocalPart)) {
|
} else if ("category".equals(theLocalPart)) {
|
||||||
|
@ -387,10 +389,12 @@ class ParserState<T extends IElement> {
|
||||||
private class AtomState extends BaseState {
|
private class AtomState extends BaseState {
|
||||||
|
|
||||||
private Bundle myInstance;
|
private Bundle myInstance;
|
||||||
|
private Class<? extends IResource> myResourceType;
|
||||||
|
|
||||||
public AtomState(Bundle theInstance) {
|
public AtomState(Bundle theInstance, Class<? extends IResource> theResourceType) {
|
||||||
super(null);
|
super(null);
|
||||||
myInstance = theInstance;
|
myInstance = theInstance;
|
||||||
|
myResourceType = theResourceType;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -401,7 +405,7 @@ class ParserState<T extends IElement> {
|
||||||
@Override
|
@Override
|
||||||
public void enteringNewElement(String theNamespaceURI, String theLocalPart) throws DataFormatException {
|
public void enteringNewElement(String theNamespaceURI, String theLocalPart) throws DataFormatException {
|
||||||
if ("entry".equals(theLocalPart) && verifyNamespace(XmlParser.ATOM_NS, theNamespaceURI)) {
|
if ("entry".equals(theLocalPart) && verifyNamespace(XmlParser.ATOM_NS, theNamespaceURI)) {
|
||||||
push(new AtomEntryState(myInstance));
|
push(new AtomEntryState(myInstance, myResourceType));
|
||||||
} else if (theLocalPart.equals("published")) {
|
} else if (theLocalPart.equals("published")) {
|
||||||
push(new AtomPrimitiveState(myInstance.getPublished()));
|
push(new AtomPrimitiveState(myInstance.getPublished()));
|
||||||
} else if (theLocalPart.equals("title")) {
|
} else if (theLocalPart.equals("title")) {
|
||||||
|
@ -829,9 +833,11 @@ class ParserState<T extends IElement> {
|
||||||
private class PreAtomState extends BaseState {
|
private class PreAtomState extends BaseState {
|
||||||
|
|
||||||
private Bundle myInstance;
|
private Bundle myInstance;
|
||||||
|
private Class<? extends IResource> myResourceType;
|
||||||
|
|
||||||
public PreAtomState() {
|
public PreAtomState(Class<? extends IResource> theResourceType) {
|
||||||
super(null);
|
super(null);
|
||||||
|
myResourceType = theResourceType;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -846,7 +852,7 @@ class ParserState<T extends IElement> {
|
||||||
}
|
}
|
||||||
|
|
||||||
myInstance = new Bundle();
|
myInstance = new Bundle();
|
||||||
push(new AtomState(myInstance));
|
push(new AtomState(myInstance, myResourceType));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -877,9 +883,10 @@ class ParserState<T extends IElement> {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PreResourceState(BundleEntry theEntry) {
|
public PreResourceState(BundleEntry theEntry, Class<? extends IResource> theResourceType) {
|
||||||
super(null);
|
super(null);
|
||||||
myEntry = theEntry;
|
myEntry = theEntry;
|
||||||
|
myResourceType=theResourceType;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -193,8 +193,9 @@ public class XmlParser extends BaseParser implements IParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Bundle parseBundle(Reader theReader) {
|
public <T extends IResource> Bundle parseBundle(Class<T> theResourceType, Reader theReader) {
|
||||||
XMLEventReader streamReader;
|
XMLEventReader streamReader;
|
||||||
try {
|
try {
|
||||||
streamReader = myXmlInputFactory.createXMLEventReader(theReader);
|
streamReader = myXmlInputFactory.createXMLEventReader(theReader);
|
||||||
|
@ -204,7 +205,7 @@ public class XmlParser extends BaseParser implements IParser {
|
||||||
throw new ConfigurationException("Failed to initialize STaX event factory", e);
|
throw new ConfigurationException("Failed to initialize STaX event factory", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
return parseBundle(streamReader);
|
return parseBundle(streamReader, theResourceType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -590,8 +591,8 @@ public class XmlParser extends BaseParser implements IParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Bundle parseBundle(XMLEventReader theStreamReader) {
|
private Bundle parseBundle(XMLEventReader theStreamReader, Class<? extends IResource> theResourceType) {
|
||||||
ParserState<Bundle> parserState = ParserState.getPreAtomInstance(myContext, false);
|
ParserState<Bundle> parserState = ParserState.getPreAtomInstance(myContext, theResourceType, false);
|
||||||
return doXmlLoop(theStreamReader, parserState);
|
return doXmlLoop(theStreamReader, parserState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,25 @@
|
||||||
package ca.uhn.fhir.rest.client;
|
package ca.uhn.fhir.rest.client;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* HAPI FHIR Library
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2014 University Health Network
|
||||||
|
* %%
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
|
|
|
@ -1,5 +1,25 @@
|
||||||
package ca.uhn.fhir.rest.client;
|
package ca.uhn.fhir.rest.client;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* HAPI FHIR Library
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2014 University Health Network
|
||||||
|
* %%
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
|
@ -1,5 +1,25 @@
|
||||||
package ca.uhn.fhir.rest.client;
|
package ca.uhn.fhir.rest.client;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* HAPI FHIR Library
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2014 University Health Network
|
||||||
|
* %%
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
|
||||||
import ca.uhn.fhir.model.api.IResource;
|
import ca.uhn.fhir.model.api.IResource;
|
||||||
import ca.uhn.fhir.model.primitive.IdDt;
|
import ca.uhn.fhir.model.primitive.IdDt;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,25 @@
|
||||||
package ca.uhn.fhir.rest.client.exceptions;
|
package ca.uhn.fhir.rest.client.exceptions;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* HAPI FHIR Library
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2014 University Health Network
|
||||||
|
* %%
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
|
||||||
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -77,7 +77,7 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding {
|
||||||
|
|
||||||
private MethodReturnTypeEnum myMethodReturnType;
|
private MethodReturnTypeEnum myMethodReturnType;
|
||||||
private String myResourceName;
|
private String myResourceName;
|
||||||
|
private Class<? extends IResource> myResourceType;
|
||||||
|
|
||||||
public BaseResourceReturningMethodBinding(Class<? extends IResource> theReturnResourceType, Method theMethod, FhirContext theConetxt, Object theProvider) {
|
public BaseResourceReturningMethodBinding(Class<? extends IResource> theReturnResourceType, Method theMethod, FhirContext theConetxt, Object theProvider) {
|
||||||
super(theMethod, theConetxt, theProvider);
|
super(theMethod, theConetxt, theProvider);
|
||||||
|
@ -90,9 +90,11 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding {
|
||||||
} else if (Bundle.class.isAssignableFrom(methodReturnType)) {
|
} else if (Bundle.class.isAssignableFrom(methodReturnType)) {
|
||||||
myMethodReturnType = MethodReturnTypeEnum.BUNDLE;
|
myMethodReturnType = MethodReturnTypeEnum.BUNDLE;
|
||||||
} else {
|
} else {
|
||||||
throw new ConfigurationException("Invalid return type '" + methodReturnType.getCanonicalName() + "' on method '" + theMethod.getName() + "' on type: " + theMethod.getDeclaringClass().getCanonicalName());
|
throw new ConfigurationException("Invalid return type '" + methodReturnType.getCanonicalName() + "' on method '" + theMethod.getName() + "' on type: "
|
||||||
|
+ theMethod.getDeclaringClass().getCanonicalName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
myResourceType = theReturnResourceType;
|
||||||
if (theReturnResourceType != null) {
|
if (theReturnResourceType != null) {
|
||||||
ResourceDef resourceDefAnnotation = theReturnResourceType.getAnnotation(ResourceDef.class);
|
ResourceDef resourceDefAnnotation = theReturnResourceType.getAnnotation(ResourceDef.class);
|
||||||
if (resourceDefAnnotation == null) {
|
if (resourceDefAnnotation == null) {
|
||||||
|
@ -119,7 +121,12 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding {
|
||||||
|
|
||||||
switch (getReturnType()) {
|
switch (getReturnType()) {
|
||||||
case BUNDLE: {
|
case BUNDLE: {
|
||||||
Bundle bundle = parser.parseBundle(theResponseReader);
|
Bundle bundle;
|
||||||
|
if (myResourceType != null) {
|
||||||
|
bundle = parser.parseBundle(myResourceType, theResponseReader);
|
||||||
|
}else {
|
||||||
|
bundle = parser.parseBundle(theResponseReader);
|
||||||
|
}
|
||||||
switch (getMethodReturnType()) {
|
switch (getMethodReturnType()) {
|
||||||
case BUNDLE:
|
case BUNDLE:
|
||||||
return bundle;
|
return bundle;
|
||||||
|
@ -138,7 +145,12 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case RESOURCE: {
|
case RESOURCE: {
|
||||||
IResource resource = parser.parseResource(theResponseReader);
|
IResource resource;
|
||||||
|
if (myResourceType != null) {
|
||||||
|
resource = parser.parseResource(myResourceType, theResponseReader);
|
||||||
|
} else {
|
||||||
|
resource = parser.parseResource(theResponseReader);
|
||||||
|
}
|
||||||
|
|
||||||
List<String> lmHeaders = theHeaders.get(Constants.HEADER_LAST_MODIFIED_LOWERCASE);
|
List<String> lmHeaders = theHeaders.get(Constants.HEADER_LAST_MODIFIED_LOWERCASE);
|
||||||
if (lmHeaders != null && lmHeaders.size() > 0 && StringUtils.isNotBlank(lmHeaders.get(0))) {
|
if (lmHeaders != null && lmHeaders.size() > 0 && StringUtils.isNotBlank(lmHeaders.get(0))) {
|
||||||
|
@ -238,7 +250,8 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding {
|
||||||
return (IdDt) retValObj;
|
return (IdDt) retValObj;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new InternalErrorException("Found an object of type '" + retValObj.getClass().getCanonicalName() + "' in resource metadata for key " + theKey.name() + " - Expected " + IdDt.class.getCanonicalName());
|
throw new InternalErrorException("Found an object of type '" + retValObj.getClass().getCanonicalName() + "' in resource metadata for key " + theKey.name() + " - Expected "
|
||||||
|
+ IdDt.class.getCanonicalName());
|
||||||
}
|
}
|
||||||
|
|
||||||
private InstantDt getInstantFromMetadataOrNullIfNone(Map<ResourceMetadataKeyEnum, Object> theResourceMetadata, ResourceMetadataKeyEnum theKey) {
|
private InstantDt getInstantFromMetadataOrNullIfNone(Map<ResourceMetadataKeyEnum, Object> theResourceMetadata, ResourceMetadataKeyEnum theKey) {
|
||||||
|
@ -254,7 +267,8 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding {
|
||||||
return (InstantDt) retValObj;
|
return (InstantDt) retValObj;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new InternalErrorException("Found an object of type '" + retValObj.getClass().getCanonicalName() + "' in resource metadata for key " + theKey.name() + " - Expected " + InstantDt.class.getCanonicalName());
|
throw new InternalErrorException("Found an object of type '" + retValObj.getClass().getCanonicalName() + "' in resource metadata for key " + theKey.name() + " - Expected "
|
||||||
|
+ InstantDt.class.getCanonicalName());
|
||||||
}
|
}
|
||||||
|
|
||||||
private IParser getNewParser(EncodingUtil theResponseEncoding, boolean thePrettyPrint, NarrativeModeEnum theNarrativeMode) {
|
private IParser getNewParser(EncodingUtil theResponseEncoding, boolean thePrettyPrint, NarrativeModeEnum theNarrativeMode) {
|
||||||
|
@ -271,8 +285,8 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding {
|
||||||
return parser.setPrettyPrint(thePrettyPrint).setSuppressNarratives(theNarrativeMode == NarrativeModeEnum.SUPPRESS);
|
return parser.setPrettyPrint(thePrettyPrint).setSuppressNarratives(theNarrativeMode == NarrativeModeEnum.SUPPRESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void streamResponseAsBundle(RestfulServer theServer, HttpServletResponse theHttpResponse, List<IResource> theResult, EncodingUtil theResponseEncoding, String theServerBase, String theCompleteUrl, boolean thePrettyPrint, boolean theRequestIsBrowser,
|
private void streamResponseAsBundle(RestfulServer theServer, HttpServletResponse theHttpResponse, List<IResource> theResult, EncodingUtil theResponseEncoding, String theServerBase,
|
||||||
NarrativeModeEnum theNarrativeMode) throws IOException {
|
String theCompleteUrl, boolean thePrettyPrint, boolean theRequestIsBrowser, NarrativeModeEnum theNarrativeMode) throws IOException {
|
||||||
assert !theServerBase.endsWith("/");
|
assert !theServerBase.endsWith("/");
|
||||||
|
|
||||||
theHttpResponse.setStatus(200);
|
theHttpResponse.setStatus(200);
|
||||||
|
@ -317,10 +331,10 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding {
|
||||||
b.append(resId);
|
b.append(resId);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If this is a history operation, we add the version of the
|
* If this is a history operation, we add the version of the resource to the self link to indicate the version
|
||||||
* resource to the self link to indicate the version
|
|
||||||
*/
|
*/
|
||||||
if (getResourceOperationType() == RestfulOperationTypeEnum.HISTORY_INSTANCE || getResourceOperationType() == RestfulOperationTypeEnum.HISTORY_TYPE || getSystemOperationType() == RestfulOperationSystemEnum.HISTORY_SYSTEM) {
|
if (getResourceOperationType() == RestfulOperationTypeEnum.HISTORY_INSTANCE || getResourceOperationType() == RestfulOperationTypeEnum.HISTORY_TYPE
|
||||||
|
|| getSystemOperationType() == RestfulOperationSystemEnum.HISTORY_SYSTEM) {
|
||||||
IdDt versionId = getIdFromMetadataOrNullIfNone(next.getResourceMetadata(), ResourceMetadataKeyEnum.VERSION_ID);
|
IdDt versionId = getIdFromMetadataOrNullIfNone(next.getResourceMetadata(), ResourceMetadataKeyEnum.VERSION_ID);
|
||||||
if (versionId != null) {
|
if (versionId != null) {
|
||||||
b.append('/');
|
b.append('/');
|
||||||
|
@ -382,7 +396,8 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void streamResponseAsResource(RestfulServer theServer, HttpServletResponse theHttpResponse, IResource theResource, EncodingUtil theResponseEncoding, boolean thePrettyPrint, boolean theRequestIsBrowser, NarrativeModeEnum theNarrativeMode) throws IOException {
|
private void streamResponseAsResource(RestfulServer theServer, HttpServletResponse theHttpResponse, IResource theResource, EncodingUtil theResponseEncoding, boolean thePrettyPrint,
|
||||||
|
boolean theRequestIsBrowser, NarrativeModeEnum theNarrativeMode) throws IOException {
|
||||||
|
|
||||||
theHttpResponse.setStatus(200);
|
theHttpResponse.setStatus(200);
|
||||||
if (theRequestIsBrowser && theServer.isUseBrowserFriendlyContentTypes()) {
|
if (theRequestIsBrowser && theServer.isUseBrowserFriendlyContentTypes()) {
|
||||||
|
|
|
@ -1,5 +1,25 @@
|
||||||
package ca.uhn.fhir.rest.method;
|
package ca.uhn.fhir.rest.method;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* HAPI FHIR Library
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2014 University Health Network
|
||||||
|
* %%
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
|
@ -130,6 +130,20 @@ class UpdateMethodBinding extends BaseOutcomeReturningMethodBindingWithResourceP
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean matches(Request theRequest) {
|
||||||
|
if (super.matches(theRequest)) {
|
||||||
|
if (myVersionIdParameterIndex != null) {
|
||||||
|
if (theRequest.getVersion() == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Set<RequestType> provideAllowableRequestTypes() {
|
protected Set<RequestType> provideAllowableRequestTypes() {
|
||||||
return Collections.singleton(RequestType.PUT);
|
return Collections.singleton(RequestType.PUT);
|
||||||
|
|
|
@ -46,6 +46,7 @@ import ca.uhn.fhir.rest.method.BaseMethodBinding;
|
||||||
import ca.uhn.fhir.rest.method.ConformanceMethodBinding;
|
import ca.uhn.fhir.rest.method.ConformanceMethodBinding;
|
||||||
import ca.uhn.fhir.rest.method.Request;
|
import ca.uhn.fhir.rest.method.Request;
|
||||||
import ca.uhn.fhir.rest.method.SearchMethodBinding;
|
import ca.uhn.fhir.rest.method.SearchMethodBinding;
|
||||||
|
import ca.uhn.fhir.rest.method.SearchMethodBinding.RequestType;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
|
import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||||
|
@ -74,6 +75,8 @@ public class RestfulServer extends HttpServlet {
|
||||||
private boolean myUseBrowserFriendlyContentTypes;
|
private boolean myUseBrowserFriendlyContentTypes;
|
||||||
private ResourceBinding myNullResourceBinding = new ResourceBinding();
|
private ResourceBinding myNullResourceBinding = new ResourceBinding();
|
||||||
|
|
||||||
|
private boolean myStarted;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*/
|
*/
|
||||||
|
@ -222,6 +225,7 @@ public class RestfulServer extends HttpServlet {
|
||||||
throw new ServletException("Failed to initialize FHIR Restful server", ex);
|
throw new ServletException("Failed to initialize FHIR Restful server", ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
myStarted = true;
|
||||||
ourLog.info("A FHIR has been lit on this server");
|
ourLog.info("A FHIR has been lit on this server");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -293,7 +297,7 @@ public class RestfulServer extends HttpServlet {
|
||||||
* {@link IllegalStateException} if called after that.
|
* {@link IllegalStateException} if called after that.
|
||||||
*/
|
*/
|
||||||
public void setServerConformanceProvider(Object theServerConformanceProvider) {
|
public void setServerConformanceProvider(Object theServerConformanceProvider) {
|
||||||
if (myFhirContext != null) {
|
if (myStarted) {
|
||||||
throw new IllegalStateException("Server is already started");
|
throw new IllegalStateException("Server is already started");
|
||||||
}
|
}
|
||||||
myServerConformanceProvider = theServerConformanceProvider;
|
myServerConformanceProvider = theServerConformanceProvider;
|
||||||
|
@ -525,6 +529,18 @@ public class RestfulServer extends HttpServlet {
|
||||||
versionId = new IdDt(nextString);
|
versionId = new IdDt(nextString);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (theRequestType==RequestType.PUT && versionId==null) {
|
||||||
|
String contentLocation = theRequest.getHeader("Content-Location");
|
||||||
|
if (contentLocation!=null) {
|
||||||
|
int idx = contentLocation.indexOf("/_history/");
|
||||||
|
if (idx != -1) {
|
||||||
|
String versionIdString = contentLocation.substring(idx + "/_history/".length());
|
||||||
|
versionId = new IdDt(versionIdString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// TODO: look for more tokens for version, compartments, etc...
|
// TODO: look for more tokens for version, compartments, etc...
|
||||||
|
|
||||||
Request r = new Request();
|
Request r = new Request();
|
||||||
|
|
|
@ -38,6 +38,7 @@ public abstract class BaseServerResponseException extends RuntimeException {
|
||||||
registerExceptionType(MethodNotAllowedException.STATUS_CODE, MethodNotAllowedException.class);
|
registerExceptionType(MethodNotAllowedException.STATUS_CODE, MethodNotAllowedException.class);
|
||||||
registerExceptionType(ResourceNotFoundException.STATUS_CODE, ResourceNotFoundException.class);
|
registerExceptionType(ResourceNotFoundException.STATUS_CODE, ResourceNotFoundException.class);
|
||||||
registerExceptionType(ResourceVersionNotSpecifiedException.STATUS_CODE, ResourceVersionNotSpecifiedException.class);
|
registerExceptionType(ResourceVersionNotSpecifiedException.STATUS_CODE, ResourceVersionNotSpecifiedException.class);
|
||||||
|
registerExceptionType(ResourceVersionConflictException.STATUS_CODE, ResourceVersionConflictException.class);
|
||||||
registerExceptionType(UnprocessableEntityException.STATUS_CODE, UnprocessableEntityException.class);
|
registerExceptionType(UnprocessableEntityException.STATUS_CODE, UnprocessableEntityException.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,5 +144,6 @@ public abstract class BaseServerResponseException extends RuntimeException {
|
||||||
if (ourStatusCodeToExceptionType.containsKey(theStatusCode)) {
|
if (ourStatusCodeToExceptionType.containsKey(theStatusCode)) {
|
||||||
throw new Error("Can not register " + theType + " to status code " + theStatusCode + " because " + ourStatusCodeToExceptionType.get(theStatusCode) + " already registers that code");
|
throw new Error("Can not register " + theType + " to status code " + theStatusCode + " because " + ourStatusCodeToExceptionType.get(theStatusCode) + " already registers that code");
|
||||||
}
|
}
|
||||||
|
ourStatusCodeToExceptionType.put(theStatusCode, theType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,25 @@
|
||||||
package ca.uhn.fhir.rest.server.tester;
|
package ca.uhn.fhir.rest.server.tester;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* HAPI FHIR Library
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2014 University Health Network
|
||||||
|
* %%
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
@ -11,8 +31,8 @@ import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.apache.commons.lang.StringEscapeUtils;
|
import org.apache.commons.lang3.StringEscapeUtils;
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.http.client.methods.HttpRequestBase;
|
import org.apache.http.client.methods.HttpRequestBase;
|
||||||
import org.apache.http.entity.ContentType;
|
import org.apache.http.entity.ContentType;
|
||||||
import org.thymeleaf.TemplateEngine;
|
import org.thymeleaf.TemplateEngine;
|
||||||
|
@ -145,7 +165,7 @@ public class PublicTesterServlet extends HttpServlet {
|
||||||
ctx.setVariable("requestUrl", requestUrl);
|
ctx.setVariable("requestUrl", requestUrl);
|
||||||
ctx.setVariable("action", action);
|
ctx.setVariable("action", action);
|
||||||
ctx.setVariable("resultStatus", resultStatus);
|
ctx.setVariable("resultStatus", resultStatus);
|
||||||
ctx.setVariable("resultBody", StringEscapeUtils.escapeHtml(resultBody));
|
ctx.setVariable("resultBody", StringEscapeUtils.escapeHtml4(resultBody));
|
||||||
ctx.setVariable("resultSyntaxHighlighterClass", resultSyntaxHighlighterClass);
|
ctx.setVariable("resultSyntaxHighlighterClass", resultSyntaxHighlighterClass);
|
||||||
|
|
||||||
myTemplateEngine.process(PUBLIC_TESTER_RESULT_HTML, ctx, theResp.getWriter());
|
myTemplateEngine.process(PUBLIC_TESTER_RESULT_HTML, ctx, theResp.getWriter());
|
||||||
|
|
|
@ -25,6 +25,10 @@ import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.model.api.Bundle;
|
import ca.uhn.fhir.model.api.Bundle;
|
||||||
import ca.uhn.fhir.model.api.BundleEntry;
|
import ca.uhn.fhir.model.api.BundleEntry;
|
||||||
import ca.uhn.fhir.model.api.ExtensionDt;
|
import ca.uhn.fhir.model.api.ExtensionDt;
|
||||||
|
import ca.uhn.fhir.model.api.annotation.Child;
|
||||||
|
import ca.uhn.fhir.model.api.annotation.Extension;
|
||||||
|
import ca.uhn.fhir.model.api.annotation.ResourceDef;
|
||||||
|
import ca.uhn.fhir.model.dstu.composite.AddressDt;
|
||||||
import ca.uhn.fhir.model.dstu.composite.HumanNameDt;
|
import ca.uhn.fhir.model.dstu.composite.HumanNameDt;
|
||||||
import ca.uhn.fhir.model.dstu.composite.NarrativeDt;
|
import ca.uhn.fhir.model.dstu.composite.NarrativeDt;
|
||||||
import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt;
|
import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt;
|
||||||
|
@ -38,6 +42,7 @@ import ca.uhn.fhir.model.dstu.resource.Specimen;
|
||||||
import ca.uhn.fhir.model.dstu.resource.ValueSet;
|
import ca.uhn.fhir.model.dstu.resource.ValueSet;
|
||||||
import ca.uhn.fhir.model.dstu.resource.ValueSet.Define;
|
import ca.uhn.fhir.model.dstu.resource.ValueSet.Define;
|
||||||
import ca.uhn.fhir.model.dstu.resource.ValueSet.DefineConcept;
|
import ca.uhn.fhir.model.dstu.resource.ValueSet.DefineConcept;
|
||||||
|
import ca.uhn.fhir.model.dstu.valueset.AddressUseEnum;
|
||||||
import ca.uhn.fhir.model.dstu.valueset.NarrativeStatusEnum;
|
import ca.uhn.fhir.model.dstu.valueset.NarrativeStatusEnum;
|
||||||
import ca.uhn.fhir.model.primitive.DecimalDt;
|
import ca.uhn.fhir.model.primitive.DecimalDt;
|
||||||
import ca.uhn.fhir.model.primitive.StringDt;
|
import ca.uhn.fhir.model.primitive.StringDt;
|
||||||
|
@ -48,8 +53,7 @@ public class JsonParserTest {
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(JsonParserTest.class);
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(JsonParserTest.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This sample has extra elements in <searchParam> that are not actually a
|
* This sample has extra elements in <searchParam> that are not actually a part of the spec any more..
|
||||||
* part of the spec any more..
|
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testParseFuroreMetadataWithExtraElements() throws IOException {
|
public void testParseFuroreMetadataWithExtraElements() throws IOException {
|
||||||
|
@ -61,6 +65,122 @@ public class JsonParserTest {
|
||||||
assertEquals("_id", res.getSearchParam().get(1).getName().getValue());
|
assertEquals("_id", res.getSearchParam().get(1).getName().getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEncodeExtensionWithResourceContent() throws IOException {
|
||||||
|
IParser parser = new FhirContext().newJsonParser();
|
||||||
|
|
||||||
|
Patient patient = new Patient();
|
||||||
|
patient.addAddress().setUse(AddressUseEnum.HOME);
|
||||||
|
patient.addUndeclaredExtension(false, "urn:foo", new ResourceReferenceDt(Organization.class, "123"));
|
||||||
|
|
||||||
|
String val = parser.encodeResourceToString(patient);
|
||||||
|
ourLog.info(val);
|
||||||
|
assertThat(val, StringContains.containsString("\"extension\":[{\"url\":\"urn:foo\",\"valueResource\":{\"resource\":\"Organization/123\"}}]"));
|
||||||
|
|
||||||
|
Patient actual = parser.parseResource(Patient.class, val);
|
||||||
|
assertEquals(AddressUseEnum.HOME, patient.getAddressFirstRep().getUse().getValueAsEnum());
|
||||||
|
List<ExtensionDt> ext = actual.getUndeclaredExtensionsByUrl("urn:foo");
|
||||||
|
assertEquals(1, ext.size());
|
||||||
|
ResourceReferenceDt ref = (ResourceReferenceDt) ext.get(0).getValue();
|
||||||
|
assertEquals("Organization/123", ref.getResourceUrl());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEncodeDeclaredExtensionWithResourceContent() throws IOException {
|
||||||
|
IParser parser = new FhirContext().newJsonParser();
|
||||||
|
|
||||||
|
MyPatientWithOneDeclaredExtension patient = new MyPatientWithOneDeclaredExtension();
|
||||||
|
patient.addAddress().setUse(AddressUseEnum.HOME);
|
||||||
|
patient.setFoo(new ResourceReferenceDt(Organization.class, "123"));
|
||||||
|
|
||||||
|
String val = parser.encodeResourceToString(patient);
|
||||||
|
ourLog.info(val);
|
||||||
|
assertThat(val, StringContains.containsString("\"extension\":[{\"url\":\"urn:foo\",\"valueResource\":{\"resource\":\"Organization/123\"}}]"));
|
||||||
|
|
||||||
|
MyPatientWithOneDeclaredExtension actual = parser.parseResource(MyPatientWithOneDeclaredExtension.class, val);
|
||||||
|
assertEquals(AddressUseEnum.HOME, patient.getAddressFirstRep().getUse().getValueAsEnum());
|
||||||
|
ResourceReferenceDt ref = actual.getFoo();
|
||||||
|
assertEquals("Organization/123", ref.getResourceUrl());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEncodeDeclaredExtensionWithAddressContent() throws IOException {
|
||||||
|
IParser parser = new FhirContext().newJsonParser();
|
||||||
|
|
||||||
|
MyPatientWithOneDeclaredAddressExtension patient = new MyPatientWithOneDeclaredAddressExtension();
|
||||||
|
patient.addAddress().setUse(AddressUseEnum.HOME);
|
||||||
|
patient.setFoo(new AddressDt().addLine("line1"));
|
||||||
|
|
||||||
|
String val = parser.encodeResourceToString(patient);
|
||||||
|
ourLog.info(val);
|
||||||
|
assertThat(val, StringContains.containsString("\"extension\":[{\"url\":\"urn:foo\",\"valueAddress\":{\"line\":[\"line1\"]}}]"));
|
||||||
|
|
||||||
|
MyPatientWithOneDeclaredAddressExtension actual = parser.parseResource(MyPatientWithOneDeclaredAddressExtension.class, val);
|
||||||
|
assertEquals(AddressUseEnum.HOME, patient.getAddressFirstRep().getUse().getValueAsEnum());
|
||||||
|
AddressDt ref = actual.getFoo();
|
||||||
|
assertEquals("line1", ref.getLineFirstRep().getValue());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEncodeUndeclaredExtensionWithAddressContent() throws IOException {
|
||||||
|
IParser parser = new FhirContext().newJsonParser();
|
||||||
|
|
||||||
|
Patient patient = new Patient();
|
||||||
|
patient.addAddress().setUse(AddressUseEnum.HOME);
|
||||||
|
patient.addUndeclaredExtension(false, "urn:foo", new AddressDt().addLine("line1"));
|
||||||
|
|
||||||
|
String val = parser.encodeResourceToString(patient);
|
||||||
|
ourLog.info(val);
|
||||||
|
assertThat(val, StringContains.containsString("\"extension\":[{\"url\":\"urn:foo\",\"valueAddress\":{\"line\":[\"line1\"]}}]"));
|
||||||
|
|
||||||
|
MyPatientWithOneDeclaredAddressExtension actual = parser.parseResource(MyPatientWithOneDeclaredAddressExtension.class, val);
|
||||||
|
assertEquals(AddressUseEnum.HOME, patient.getAddressFirstRep().getUse().getValueAsEnum());
|
||||||
|
AddressDt ref = actual.getFoo();
|
||||||
|
assertEquals("line1", ref.getLineFirstRep().getValue());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ResourceDef(name = "Patient")
|
||||||
|
public static class MyPatientWithOneDeclaredExtension extends Patient {
|
||||||
|
|
||||||
|
@Child(order = 0, name = "foo")
|
||||||
|
@Extension(url = "urn:foo", definedLocally = true, isModifier = false)
|
||||||
|
private ResourceReferenceDt myFoo;
|
||||||
|
|
||||||
|
public ResourceReferenceDt getFoo() {
|
||||||
|
return myFoo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFoo(ResourceReferenceDt theFoo) {
|
||||||
|
myFoo = theFoo;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ResourceDef(name = "Patient")
|
||||||
|
public static class MyPatientWithOneDeclaredAddressExtension extends Patient {
|
||||||
|
|
||||||
|
@Child(order = 0, name = "foo")
|
||||||
|
@Extension(url = "urn:foo", definedLocally = true, isModifier = false)
|
||||||
|
private AddressDt myFoo;
|
||||||
|
|
||||||
|
public AddressDt getFoo() {
|
||||||
|
return myFoo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFoo(AddressDt theFoo) {
|
||||||
|
myFoo = theFoo;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEncodeExt() throws Exception {
|
public void testEncodeExt() throws Exception {
|
||||||
|
|
||||||
|
@ -150,9 +270,6 @@ public class JsonParserTest {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSimpleResourceEncodeWithCustomType() throws IOException {
|
public void testSimpleResourceEncodeWithCustomType() throws IOException {
|
||||||
|
|
||||||
|
@ -239,7 +356,8 @@ public class JsonParserTest {
|
||||||
String encoded = ctx.newXmlParser().setPrettyPrint(true).encodeBundleToString(bundle);
|
String encoded = ctx.newXmlParser().setPrettyPrint(true).encodeBundleToString(bundle);
|
||||||
ourLog.info(encoded);
|
ourLog.info(encoded);
|
||||||
|
|
||||||
assertEquals("http://fhir.healthintersections.com.au/open/DiagnosticReport/_search?_format=application/json+fhir&search-id=46d5f0e7-9240-4d4f-9f51-f8ac975c65&search-sort=_id", bundle.getLinkSelf().getValue());
|
assertEquals("http://fhir.healthintersections.com.au/open/DiagnosticReport/_search?_format=application/json+fhir&search-id=46d5f0e7-9240-4d4f-9f51-f8ac975c65&search-sort=_id", bundle
|
||||||
|
.getLinkSelf().getValue());
|
||||||
assertEquals("urn:uuid:0b754ff9-03cf-4322-a119-15019af8a3", bundle.getBundleId().getValue());
|
assertEquals("urn:uuid:0b754ff9-03cf-4322-a119-15019af8a3", bundle.getBundleId().getValue());
|
||||||
|
|
||||||
BundleEntry entry = bundle.getEntries().get(0);
|
BundleEntry entry = bundle.getEntries().get(0);
|
||||||
|
|
|
@ -31,6 +31,7 @@ import ca.uhn.fhir.model.api.Bundle;
|
||||||
import ca.uhn.fhir.model.api.BundleEntry;
|
import ca.uhn.fhir.model.api.BundleEntry;
|
||||||
import ca.uhn.fhir.model.api.ExtensionDt;
|
import ca.uhn.fhir.model.api.ExtensionDt;
|
||||||
import ca.uhn.fhir.model.api.IResource;
|
import ca.uhn.fhir.model.api.IResource;
|
||||||
|
import ca.uhn.fhir.model.dstu.composite.AddressDt;
|
||||||
import ca.uhn.fhir.model.dstu.composite.HumanNameDt;
|
import ca.uhn.fhir.model.dstu.composite.HumanNameDt;
|
||||||
import ca.uhn.fhir.model.dstu.composite.NarrativeDt;
|
import ca.uhn.fhir.model.dstu.composite.NarrativeDt;
|
||||||
import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt;
|
import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt;
|
||||||
|
@ -51,6 +52,8 @@ import ca.uhn.fhir.model.primitive.DecimalDt;
|
||||||
import ca.uhn.fhir.model.primitive.StringDt;
|
import ca.uhn.fhir.model.primitive.StringDt;
|
||||||
import ca.uhn.fhir.model.primitive.XhtmlDt;
|
import ca.uhn.fhir.model.primitive.XhtmlDt;
|
||||||
import ca.uhn.fhir.narrative.INarrativeGenerator;
|
import ca.uhn.fhir.narrative.INarrativeGenerator;
|
||||||
|
import ca.uhn.fhir.parser.JsonParserTest.MyPatientWithOneDeclaredAddressExtension;
|
||||||
|
import ca.uhn.fhir.parser.JsonParserTest.MyPatientWithOneDeclaredExtension;
|
||||||
|
|
||||||
public class XmlParserTest {
|
public class XmlParserTest {
|
||||||
|
|
||||||
|
@ -69,7 +72,83 @@ public class XmlParserTest {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEncodeExtensionWithResourceContent() throws IOException {
|
||||||
|
IParser parser = new FhirContext().newXmlParser();
|
||||||
|
|
||||||
|
Patient patient = new Patient();
|
||||||
|
patient.addAddress().setUse(AddressUseEnum.HOME);
|
||||||
|
patient.addUndeclaredExtension(false, "urn:foo", new ResourceReferenceDt(Organization.class, "123"));
|
||||||
|
|
||||||
|
String val = parser.encodeResourceToString(patient);
|
||||||
|
ourLog.info(val);
|
||||||
|
assertThat(val, StringContains.containsString("<extension url=\"urn:foo\"><valueResource><reference value=\"Organization/123\"/></valueResource></extension>"));
|
||||||
|
|
||||||
|
Patient actual = parser.parseResource(Patient.class, val);
|
||||||
|
assertEquals(AddressUseEnum.HOME, patient.getAddressFirstRep().getUse().getValueAsEnum());
|
||||||
|
List<ExtensionDt> ext = actual.getUndeclaredExtensionsByUrl("urn:foo");
|
||||||
|
assertEquals(1, ext.size());
|
||||||
|
ResourceReferenceDt ref = (ResourceReferenceDt) ext.get(0).getValue();
|
||||||
|
assertEquals("Organization/123", ref.getResourceUrl());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEncodeDeclaredExtensionWithResourceContent() throws IOException {
|
||||||
|
IParser parser = new FhirContext().newXmlParser();
|
||||||
|
|
||||||
|
MyPatientWithOneDeclaredExtension patient = new MyPatientWithOneDeclaredExtension();
|
||||||
|
patient.addAddress().setUse(AddressUseEnum.HOME);
|
||||||
|
patient.setFoo(new ResourceReferenceDt(Organization.class, "123"));
|
||||||
|
|
||||||
|
String val = parser.encodeResourceToString(patient);
|
||||||
|
ourLog.info(val);
|
||||||
|
assertThat(val, StringContains.containsString("<extension url=\"urn:foo\"><valueResource><reference value=\"Organization/123\"/></valueResource></extension>"));
|
||||||
|
|
||||||
|
MyPatientWithOneDeclaredExtension actual = parser.parseResource(MyPatientWithOneDeclaredExtension.class, val);
|
||||||
|
assertEquals(AddressUseEnum.HOME, patient.getAddressFirstRep().getUse().getValueAsEnum());
|
||||||
|
ResourceReferenceDt ref = actual.getFoo();
|
||||||
|
assertEquals("Organization/123", ref.getResourceUrl());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEncodeDeclaredExtensionWithAddressContent() throws IOException {
|
||||||
|
IParser parser = new FhirContext().newXmlParser();
|
||||||
|
|
||||||
|
MyPatientWithOneDeclaredAddressExtension patient = new MyPatientWithOneDeclaredAddressExtension();
|
||||||
|
patient.addAddress().setUse(AddressUseEnum.HOME);
|
||||||
|
patient.setFoo(new AddressDt().addLine("line1"));
|
||||||
|
|
||||||
|
String val = parser.encodeResourceToString(patient);
|
||||||
|
ourLog.info(val);
|
||||||
|
assertThat(val, StringContains.containsString("<extension url=\"urn:foo\"><valueAddress><line value=\"line1\"/></valueAddress></extension>"));
|
||||||
|
|
||||||
|
MyPatientWithOneDeclaredAddressExtension actual = parser.parseResource(MyPatientWithOneDeclaredAddressExtension.class, val);
|
||||||
|
assertEquals(AddressUseEnum.HOME, patient.getAddressFirstRep().getUse().getValueAsEnum());
|
||||||
|
AddressDt ref = actual.getFoo();
|
||||||
|
assertEquals("line1", ref.getLineFirstRep().getValue());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEncodeUndeclaredExtensionWithAddressContent() throws IOException {
|
||||||
|
IParser parser = new FhirContext().newXmlParser();
|
||||||
|
|
||||||
|
Patient patient = new Patient();
|
||||||
|
patient.addAddress().setUse(AddressUseEnum.HOME);
|
||||||
|
patient.addUndeclaredExtension(false, "urn:foo", new AddressDt().addLine("line1"));
|
||||||
|
|
||||||
|
String val = parser.encodeResourceToString(patient);
|
||||||
|
ourLog.info(val);
|
||||||
|
assertThat(val, StringContains.containsString("<extension url=\"urn:foo\"><valueAddress><line value=\"line1\"/></valueAddress></extension>"));
|
||||||
|
|
||||||
|
MyPatientWithOneDeclaredAddressExtension actual = parser.parseResource(MyPatientWithOneDeclaredAddressExtension.class, val);
|
||||||
|
assertEquals(AddressUseEnum.HOME, patient.getAddressFirstRep().getUse().getValueAsEnum());
|
||||||
|
AddressDt ref = actual.getFoo();
|
||||||
|
assertEquals("line1", ref.getLineFirstRep().getValue());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEncodeBundleResultCount() throws IOException {
|
public void testEncodeBundleResultCount() throws IOException {
|
||||||
|
|
|
@ -36,6 +36,7 @@ import ca.uhn.fhir.model.api.Bundle;
|
||||||
import ca.uhn.fhir.model.api.BundleEntry;
|
import ca.uhn.fhir.model.api.BundleEntry;
|
||||||
import ca.uhn.fhir.model.api.PathSpecification;
|
import ca.uhn.fhir.model.api.PathSpecification;
|
||||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||||
|
import ca.uhn.fhir.model.api.annotation.ResourceDef;
|
||||||
import ca.uhn.fhir.model.dstu.composite.CodingDt;
|
import ca.uhn.fhir.model.dstu.composite.CodingDt;
|
||||||
import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
|
import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
|
||||||
import ca.uhn.fhir.model.dstu.resource.Conformance;
|
import ca.uhn.fhir.model.dstu.resource.Conformance;
|
||||||
|
@ -46,7 +47,12 @@ 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.IntegerDt;
|
import ca.uhn.fhir.model.primitive.IntegerDt;
|
||||||
import ca.uhn.fhir.model.primitive.StringDt;
|
import ca.uhn.fhir.model.primitive.StringDt;
|
||||||
|
import ca.uhn.fhir.rest.annotation.Create;
|
||||||
|
import ca.uhn.fhir.rest.annotation.RequiredParam;
|
||||||
|
import ca.uhn.fhir.rest.annotation.ResourceParam;
|
||||||
|
import ca.uhn.fhir.rest.annotation.Search;
|
||||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||||
|
import ca.uhn.fhir.rest.client.api.IBasicClient;
|
||||||
import ca.uhn.fhir.rest.param.CodingListParam;
|
import ca.uhn.fhir.rest.param.CodingListParam;
|
||||||
import ca.uhn.fhir.rest.param.DateRangeParam;
|
import ca.uhn.fhir.rest.param.DateRangeParam;
|
||||||
import ca.uhn.fhir.rest.param.QualifiedDateParam;
|
import ca.uhn.fhir.rest.param.QualifiedDateParam;
|
||||||
|
@ -131,7 +137,7 @@ public class ClientTest {
|
||||||
|
|
||||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||||
when(httpClient.execute(capt.capture())).thenReturn(httpResponse);
|
when(httpClient.execute(capt.capture())).thenReturn(httpResponse);
|
||||||
when(httpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 400, "OK"));
|
when(httpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 400, "foobar"));
|
||||||
when(httpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_TEXT + "; charset=UTF-8"));
|
when(httpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_TEXT + "; charset=UTF-8"));
|
||||||
when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader("foobar"), Charset.forName("UTF-8")));
|
when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader("foobar"), Charset.forName("UTF-8")));
|
||||||
|
|
||||||
|
@ -481,6 +487,62 @@ public class ClientTest {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSearchWithCustomType() throws Exception {
|
||||||
|
|
||||||
|
String msg = getPatientFeedWithOneResult();
|
||||||
|
|
||||||
|
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||||
|
when(httpClient.execute(capt.capture())).thenReturn(httpResponse);
|
||||||
|
when(httpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||||
|
when(httpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
||||||
|
when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
|
||||||
|
|
||||||
|
ITestClientWithCustomType client = ctx.newRestfulClient(ITestClientWithCustomType.class, "http://foo");
|
||||||
|
CustomPatient response = client.getPatientByDob(new QualifiedDateParam(QuantityCompararatorEnum.GREATERTHAN_OR_EQUALS, "2011-01-02"));
|
||||||
|
|
||||||
|
assertEquals("http://foo/Patient?birthdate=%3E%3D2011-01-02", capt.getValue().getURI().toString());
|
||||||
|
assertEquals("PRP1660", response.getIdentifier().get(0).getValue().getValue());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface ITestClientWithCustomType extends IBasicClient {
|
||||||
|
@Search()
|
||||||
|
public CustomPatient getPatientByDob(@RequiredParam(name=Patient.SP_BIRTHDATE) QualifiedDateParam theBirthDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSearchWithCustomTypeList() throws Exception {
|
||||||
|
|
||||||
|
String msg = getPatientFeedWithOneResult();
|
||||||
|
|
||||||
|
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||||
|
when(httpClient.execute(capt.capture())).thenReturn(httpResponse);
|
||||||
|
when(httpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||||
|
when(httpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
||||||
|
when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
|
||||||
|
|
||||||
|
ITestClientWithCustomTypeList client = ctx.newRestfulClient(ITestClientWithCustomTypeList.class, "http://foo");
|
||||||
|
List<CustomPatient> response = client.getPatientByDob(new QualifiedDateParam(QuantityCompararatorEnum.GREATERTHAN_OR_EQUALS, "2011-01-02"));
|
||||||
|
|
||||||
|
assertEquals("http://foo/Patient?birthdate=%3E%3D2011-01-02", capt.getValue().getURI().toString());
|
||||||
|
assertEquals("PRP1660", response.get(0).getIdentifier().get(0).getValue().getValue());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface ITestClientWithCustomTypeList extends IBasicClient {
|
||||||
|
@Search()
|
||||||
|
public List<CustomPatient> getPatientByDob(@RequiredParam(name=Patient.SP_BIRTHDATE) QualifiedDateParam theBirthDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ResourceDef(name="Patient")
|
||||||
|
public static class CustomPatient extends Patient
|
||||||
|
{
|
||||||
|
// nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSearchByToken() throws Exception {
|
public void testSearchByToken() throws Exception {
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
package ca.uhn.fhir.rest.client;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.model.dstu.resource.Patient;
|
||||||
|
import ca.uhn.fhir.rest.annotation.RequiredParam;
|
||||||
|
import ca.uhn.fhir.rest.annotation.Search;
|
||||||
|
import ca.uhn.fhir.rest.client.ClientTest.CustomPatient;
|
||||||
|
import ca.uhn.fhir.rest.client.api.IBasicClient;
|
||||||
|
import ca.uhn.fhir.rest.param.QualifiedDateParam;
|
||||||
|
|
||||||
|
public class InvalidClientDefinitionTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAnnotationTypeIsNotAssignableToMethodReturnType() {
|
||||||
|
// TODO: this should fail
|
||||||
|
new FhirContext().newRestfulClient(ITestClientWithCustomType.class, "http://example.com");
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface ITestClientWithCustomType extends IBasicClient {
|
||||||
|
@Search(type=Patient.class)
|
||||||
|
public CustomPatient getPatientByDob(@RequiredParam(name=Patient.SP_BIRTHDATE) QualifiedDateParam theBirthDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
package ca.uhn.fhir.rest.server;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
import ca.uhn.fhir.model.api.annotation.Description;
|
||||||
|
import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
|
||||||
|
import ca.uhn.fhir.model.dstu.resource.Conformance;
|
||||||
|
import ca.uhn.fhir.model.dstu.resource.Patient;
|
||||||
|
import ca.uhn.fhir.parser.DataFormatException;
|
||||||
|
import ca.uhn.fhir.rest.annotation.RequiredParam;
|
||||||
|
import ca.uhn.fhir.rest.annotation.Search;
|
||||||
|
import ca.uhn.fhir.rest.server.provider.ServerConformanceProvider;
|
||||||
|
|
||||||
|
public class DocumentationTest {
|
||||||
|
|
||||||
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(DocumentationTest.class);
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSearchParameterDocumentation() throws Exception {
|
||||||
|
|
||||||
|
RestfulServer rs = new RestfulServer();
|
||||||
|
rs.setProviders(new SearchProvider());
|
||||||
|
|
||||||
|
ServerConformanceProvider sc = new ServerConformanceProvider(rs);
|
||||||
|
rs.setServerConformanceProvider(sc);
|
||||||
|
|
||||||
|
rs.init(null);
|
||||||
|
|
||||||
|
Conformance conformance = sc.getServerConformance();
|
||||||
|
String conf = new FhirContext().newXmlParser().setPrettyPrint(true).encodeResourceToString(conformance);
|
||||||
|
ourLog.info(conf);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by dsotnikov on 2/25/2014.
|
||||||
|
*/
|
||||||
|
public static class SearchProvider {
|
||||||
|
|
||||||
|
@Search(type = Patient.class)
|
||||||
|
public Patient findPatient(@Description(shortDefinition = "The patient's identifier (MRN or other card number)") @RequiredParam(name = Patient.SP_IDENTIFIER) IdentifierDt theIdentifier) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,8 +1,6 @@
|
||||||
package ca.uhn.fhir.rest.server;
|
package ca.uhn.fhir.rest.server;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.*;
|
||||||
import static org.junit.Assert.assertThat;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -49,6 +47,7 @@ import ca.uhn.fhir.model.dstu.composite.CodingDt;
|
||||||
import ca.uhn.fhir.model.dstu.composite.HumanNameDt;
|
import ca.uhn.fhir.model.dstu.composite.HumanNameDt;
|
||||||
import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
|
import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
|
||||||
import ca.uhn.fhir.model.dstu.resource.Conformance;
|
import ca.uhn.fhir.model.dstu.resource.Conformance;
|
||||||
|
import ca.uhn.fhir.model.dstu.resource.DiagnosticOrder;
|
||||||
import ca.uhn.fhir.model.dstu.resource.DiagnosticReport;
|
import ca.uhn.fhir.model.dstu.resource.DiagnosticReport;
|
||||||
import ca.uhn.fhir.model.dstu.resource.OperationOutcome;
|
import ca.uhn.fhir.model.dstu.resource.OperationOutcome;
|
||||||
import ca.uhn.fhir.model.dstu.resource.Patient;
|
import ca.uhn.fhir.model.dstu.resource.Patient;
|
||||||
|
@ -860,11 +859,10 @@ public class ResfulServerMethodTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testUpdateWrongResourceType() throws Exception {
|
public void testUpdateWrongResourceType() throws Exception {
|
||||||
|
|
||||||
// TODO: this method sends in the wrong resource type vs. the URL so it should
|
// TODO: this method sends in the wrong resource type vs. the URL so it should
|
||||||
// give a useful error message
|
// give a useful error message (and then make this unit test actually run)
|
||||||
Patient patient = new Patient();
|
Patient patient = new Patient();
|
||||||
patient.addIdentifier().setValue("002");
|
patient.addIdentifier().setValue("002");
|
||||||
|
|
||||||
|
@ -902,16 +900,17 @@ public class ResfulServerMethodTest {
|
||||||
patient.getIdentifier().setValue("001");
|
patient.getIdentifier().setValue("001");
|
||||||
|
|
||||||
HttpPut httpPut = new HttpPut("http://localhost:" + ourPort + "/DiagnosticReport/001");
|
HttpPut httpPut = new HttpPut("http://localhost:" + ourPort + "/DiagnosticReport/001");
|
||||||
httpPut.addHeader("Content-Location", "/DiagnosticReport/001/_history/002");
|
httpPut.addHeader("Content-Location", "/DiagnosticReport/001/_history/004");
|
||||||
httpPut.setEntity(new StringEntity(new FhirContext().newXmlParser().encodeResourceToString(patient), ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
httpPut.setEntity(new StringEntity(new FhirContext().newXmlParser().encodeResourceToString(patient), ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
|
||||||
|
|
||||||
HttpResponse status = ourClient.execute(httpPut);
|
HttpResponse status = ourClient.execute(httpPut);
|
||||||
|
|
||||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
// String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||||
ourLog.info("Response was:\n{}", responseContent);
|
// ourLog.info("Response was:\n{}", responseContent);
|
||||||
|
|
||||||
assertEquals(201, status.getStatusLine().getStatusCode());
|
assertEquals(204, status.getStatusLine().getStatusCode());
|
||||||
assertEquals("http://localhost:" + ourPort + "/DiagnosticReport/001/_history/002", status.getFirstHeader("Location").getValue());
|
assertNull(status.getEntity());
|
||||||
|
assertEquals("http://localhost:" + ourPort + "/DiagnosticReport/001/_history/004", status.getFirstHeader("Location").getValue());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -977,11 +976,12 @@ public class ResfulServerMethodTest {
|
||||||
|
|
||||||
status = ourClient.execute(httpPost);
|
status = ourClient.execute(httpPost);
|
||||||
|
|
||||||
responseContent = IOUtils.toString(status.getEntity().getContent());
|
// responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||||
ourLog.info("Response was:\n{}", responseContent);
|
// ourLog.info("Response was:\n{}", responseContent);
|
||||||
|
|
||||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
assertEquals(204, status.getStatusLine().getStatusCode());
|
||||||
assertEquals("", responseContent);
|
assertNull(status.getEntity());
|
||||||
|
// assertEquals("", responseContent);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1043,6 +1043,14 @@ public class ResfulServerMethodTest {
|
||||||
return DiagnosticReport.class;
|
return DiagnosticReport.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
@Update()
|
||||||
|
public MethodOutcome updateDiagnosticReportWithNoResponse(@IdParam IdDt theId, @VersionIdParam IdDt theVersionId, @ResourceParam DiagnosticReport thePatient) {
|
||||||
|
IdDt id = theId;
|
||||||
|
IdDt version = theVersionId;
|
||||||
|
return new MethodOutcome(id, version);
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
@Update()
|
@Update()
|
||||||
public MethodOutcome updateDiagnosticReportWithVersionAndNoResponse(@IdParam IdDt theId, @ResourceParam DiagnosticReport thePatient) {
|
public MethodOutcome updateDiagnosticReportWithVersionAndNoResponse(@IdParam IdDt theId, @ResourceParam DiagnosticReport thePatient) {
|
||||||
|
@ -1281,10 +1289,10 @@ public class ResfulServerMethodTest {
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
@Update()
|
@Update()
|
||||||
public MethodOutcome updateDiagnosticReportWithVersion(@IdParam IdDt theId, @VersionIdParam IdDt theVersionId, @ResourceParam DiagnosticReport thePatient) {
|
public MethodOutcome updateDiagnosticReportWithVersion(@IdParam IdDt theId, @VersionIdParam IdDt theVersionId, @ResourceParam DiagnosticOrder thePatient) {
|
||||||
/*
|
/*
|
||||||
* TODO: THIS METHOD IS NOT USED. It's the wrong type
|
* TODO: THIS METHOD IS NOT USED. It's the wrong type
|
||||||
* (DiagnosticReport), so it should cause an exception on startup.
|
* (DiagnosticOrder), so it should cause an exception on startup.
|
||||||
* Also we should detect if there are multiple resource params on an
|
* Also we should detect if there are multiple resource params on an
|
||||||
* update/create/etc method
|
* update/create/etc method
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package ca.uhn.fhir.rest.server;
|
package ca.uhn.fhir.rest.server;
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -16,8 +17,10 @@ import org.junit.Test;
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.model.api.IResource;
|
import ca.uhn.fhir.model.api.IResource;
|
||||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||||
|
import ca.uhn.fhir.model.api.annotation.Description;
|
||||||
import ca.uhn.fhir.model.dstu.composite.HumanNameDt;
|
import ca.uhn.fhir.model.dstu.composite.HumanNameDt;
|
||||||
import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
|
import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
|
||||||
|
import ca.uhn.fhir.model.dstu.composite.QuantityDt;
|
||||||
import ca.uhn.fhir.model.dstu.resource.Organization;
|
import ca.uhn.fhir.model.dstu.resource.Organization;
|
||||||
import ca.uhn.fhir.model.dstu.resource.Patient;
|
import ca.uhn.fhir.model.dstu.resource.Patient;
|
||||||
import ca.uhn.fhir.model.dstu.valueset.IdentifierUseEnum;
|
import ca.uhn.fhir.model.dstu.valueset.IdentifierUseEnum;
|
||||||
|
@ -75,7 +78,7 @@ public class TesterTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTester() throws Exception {
|
public void testTester() throws Exception {
|
||||||
// if (true) return;
|
if (true) return;
|
||||||
|
|
||||||
myRestfulServer.setProviders(new SearchProvider(), new GlobalHistoryProvider());
|
myRestfulServer.setProviders(new SearchProvider(), new GlobalHistoryProvider());
|
||||||
myServer.start();
|
myServer.start();
|
||||||
|
@ -111,7 +114,10 @@ public class TesterTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Search(type = Patient.class)
|
@Search(type = Patient.class)
|
||||||
public Patient findPatient(@RequiredParam(name = Patient.SP_IDENTIFIER) IdentifierDt theIdentifier) {
|
public Patient findPatient(
|
||||||
|
@Description(shortDefinition="The patient's identifier (MRN or other card number)")
|
||||||
|
@RequiredParam(name = Patient.SP_IDENTIFIER) IdentifierDt theIdentifier
|
||||||
|
) {
|
||||||
for (Patient next : getIdToPatient().values()) {
|
for (Patient next : getIdToPatient().values()) {
|
||||||
for (IdentifierDt nextId : next.getIdentifier()) {
|
for (IdentifierDt nextId : next.getIdentifier()) {
|
||||||
if (nextId.matchesSystemAndValue(theIdentifier)) {
|
if (nextId.matchesSystemAndValue(theIdentifier)) {
|
||||||
|
|
Loading…
Reference in New Issue