A number of bugfixes around parsing and client implementation
This commit is contained in:
parent
f737797d7a
commit
63c9fb466c
|
@ -7,7 +7,7 @@
|
|||
</properties>
|
||||
<body>
|
||||
<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
|
||||
and <![CDATA[<a href="./doc_rest_client.html#HTTP_Basic_Authorization">an example</a>]]>
|
||||
illustrating how it works
|
||||
|
@ -15,6 +15,10 @@
|
|||
<action type="fix" dev="Josh Mandel">
|
||||
Correct a dependency on commons-io that was causing issues with the Tinder build
|
||||
</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>
|
||||
</body>
|
||||
</document>
|
||||
|
|
|
@ -23,12 +23,15 @@ package ca.uhn.fhir.context;
|
|||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
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.Description;
|
||||
import ca.uhn.fhir.model.api.annotation.Extension;
|
||||
|
@ -133,7 +136,15 @@ public class RuntimeChildDeclaredExtensionDefinition extends BaseRuntimeDeclared
|
|||
BaseRuntimeElementDefinition<?> elementDef = theClassToElementDefinitions.get(myChildType);
|
||||
if (elementDef instanceof RuntimePrimitiveDatatypeDefinition || elementDef instanceof RuntimeCompositeDatatypeDefinition) {
|
||||
myDatatypeChildName = "value" + elementDef.getName().substring(0, 1).toUpperCase() + elementDef.getName().substring(1);
|
||||
myChildDef = elementDef;
|
||||
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;
|
||||
}
|
||||
} else {
|
||||
RuntimeResourceBlockDefinition extDef = ((RuntimeResourceBlockDefinition) elementDef);
|
||||
for (RuntimeChildDeclaredExtensionDefinition next : extDef.getExtensions()) {
|
||||
|
|
|
@ -94,7 +94,7 @@ public class RuntimeChildUndeclaredExtensionDefinition extends BaseRuntimeChildD
|
|||
}
|
||||
|
||||
// Resource Reference
|
||||
myDatatypeToAttributeName.put(ResourceReferenceDt.class, "valueReference");
|
||||
myDatatypeToAttributeName.put(ResourceReferenceDt.class, "valueResource");
|
||||
List<Class<? extends IResource>> types = new ArrayList<Class<? extends IResource>>();
|
||||
types.add(IResource.class);
|
||||
RuntimeResourceReferenceDefinition def = new RuntimeResourceReferenceDefinition("valueResource", types);
|
||||
|
|
|
@ -26,7 +26,7 @@ import java.lang.annotation.RetentionPolicy;
|
|||
import java.lang.annotation.Target;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(value= {ElementType.FIELD, ElementType.TYPE})
|
||||
@Target(value= {ElementType.FIELD, ElementType.TYPE, ElementType.PARAMETER})
|
||||
public @interface Description {
|
||||
|
||||
/**
|
||||
|
|
|
@ -59,6 +59,11 @@ public abstract class BaseParser implements IParser {
|
|||
return parseResource(null, theMessageString);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle parseBundle(Reader theReader) {
|
||||
return parseBundle(null, theReader);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IResource parseResource(Reader theReader) throws ConfigurationException, DataFormatException {
|
||||
return parseResource(null, theReader);
|
||||
|
|
|
@ -38,17 +38,19 @@ public interface IParser {
|
|||
|
||||
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(String theMessageString) throws ConfigurationException, DataFormatException;
|
||||
|
||||
IResource parseResource(String theMessageString) throws ConfigurationException, DataFormatException;
|
||||
|
||||
IResource parseResource(Reader theReader) throws ConfigurationException, DataFormatException;
|
||||
<T extends IResource> T parseResource(Class<T> theResourceType, Reader theReader);
|
||||
|
||||
<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);
|
||||
|
||||
|
|
|
@ -56,9 +56,11 @@ import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
|
|||
import ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition;
|
||||
import ca.uhn.fhir.context.BaseRuntimeElementDefinition;
|
||||
import ca.uhn.fhir.context.BaseRuntimeElementDefinition.ChildTypeEnum;
|
||||
import ca.uhn.fhir.context.ConfigurationException;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.RuntimeChildDeclaredExtensionDefinition;
|
||||
import ca.uhn.fhir.context.RuntimeChildNarrativeDefinition;
|
||||
import ca.uhn.fhir.context.RuntimeChildUndeclaredExtensionDefinition;
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.model.api.BaseBundle;
|
||||
import ca.uhn.fhir.model.api.Bundle;
|
||||
|
@ -83,13 +85,66 @@ import ca.uhn.fhir.narrative.INarrativeGenerator;
|
|||
|
||||
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 boolean myPrettyPrint;
|
||||
|
||||
public JsonParser(FhirContext 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
|
||||
public String encodeBundleToString(Bundle theBundle) throws DataFormatException, IOException {
|
||||
if (theBundle == null) {
|
||||
|
@ -154,324 +209,6 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
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,
|
||||
String theChildName) throws IOException {
|
||||
|
||||
|
@ -736,6 +473,24 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
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
|
||||
*/
|
||||
|
@ -754,21 +509,20 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
writeExtensionsAsDirectChild(theResource, theEventWriter, theResDef, extensions, modifierExtensions);
|
||||
}
|
||||
|
||||
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);
|
||||
private void extractDeclaredExtensions(IElement theResource, BaseRuntimeElementDefinition<?> resDef, List<HeldExtension> extensions, List<HeldExtension> modifierExtensions) {
|
||||
for (RuntimeChildDeclaredExtensionDefinition nextDef : resDef.getExtensionsNonModifier()) {
|
||||
for (IElement nextValue : nextDef.getAccessor().getValues(theResource)) {
|
||||
if (nextValue != null) {
|
||||
extensions.add(new HeldExtension(nextDef, nextValue));
|
||||
}
|
||||
}
|
||||
theEventWriter.writeEnd();
|
||||
}
|
||||
if (modifierExtensions.isEmpty() == false) {
|
||||
theEventWriter.writeStartArray("modifierExtension");
|
||||
for (HeldExtension next : modifierExtensions) {
|
||||
next.write(resDef, theResource, theEventWriter);
|
||||
for (RuntimeChildDeclaredExtensionDefinition nextDef : resDef.getExtensionsModifier()) {
|
||||
for (IElement nextValue : nextDef.getAccessor().getValues(theResource)) {
|
||||
if (nextValue != null) {
|
||||
modifierExtensions.add(new HeldExtension(nextDef, nextValue));
|
||||
}
|
||||
}
|
||||
theEventWriter.writeEnd();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -786,23 +540,254 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
}
|
||||
}
|
||||
|
||||
private void extractDeclaredExtensions(IElement theResource, BaseRuntimeElementDefinition<?> resDef, List<HeldExtension> extensions, List<HeldExtension> modifierExtensions) {
|
||||
for (RuntimeChildDeclaredExtensionDefinition nextDef : resDef.getExtensionsNonModifier()) {
|
||||
for (IElement nextValue : nextDef.getAccessor().getValues(theResource)) {
|
||||
if (nextValue != null) {
|
||||
extensions.add(new HeldExtension(nextDef, nextValue));
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (RuntimeChildDeclaredExtensionDefinition nextDef : resDef.getExtensionsModifier()) {
|
||||
for (IElement nextValue : nextDef.getAccessor().getValues(theResource)) {
|
||||
if (nextValue != null) {
|
||||
modifierExtensions.add(new HeldExtension(nextDef, nextValue));
|
||||
}
|
||||
|
||||
@Override
|
||||
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) {
|
||||
if (isNotBlank(theLink.getValue())) {
|
||||
theEventWriter.writeStartObject();
|
||||
|
@ -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) {
|
||||
String str = theInstantDt.getValueAsString();
|
||||
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) {
|
||||
if (StringUtils.isNotBlank(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 ExtensionDt myUndeclaredExtension;
|
||||
private RuntimeChildDeclaredExtensionDefinition myDef;
|
||||
private ExtensionDt myUndeclaredExtension;
|
||||
private IElement myValue;
|
||||
|
||||
public HeldExtension(ExtensionDt theUndeclaredExtension) {
|
||||
|
@ -875,7 +878,9 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
if (def.getChildType() == ChildTypeEnum.RESOURCE_BLOCK) {
|
||||
extractAndWriteExtensionsAsDirectChild(myValue, theEventWriter, def, theResDef, theResource);
|
||||
} 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);
|
||||
|
@ -898,9 +903,13 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
}
|
||||
theEventWriter.writeEnd();
|
||||
} else {
|
||||
BaseRuntimeElementDefinition<?> def = myContext.getElementDefinition(value.getClass());
|
||||
// theEventWriter.writeName("value" + def.getName());
|
||||
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, value, def, "value" + WordUtils.capitalize(def.getName()));
|
||||
RuntimeChildUndeclaredExtensionDefinition extDef = myContext.getRuntimeChildUndeclaredExtensionDefinition();
|
||||
String childName = extDef.getChildNameByDatatype(value.getClass());
|
||||
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);
|
||||
|
|
|
@ -131,9 +131,9 @@ class ParserState<T extends IElement> {
|
|||
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);
|
||||
retVal.push(retVal.new PreAtomState());
|
||||
retVal.push(retVal.new PreAtomState(theResourceType));
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
@ -209,10 +209,12 @@ class ParserState<T extends IElement> {
|
|||
public class AtomEntryState extends BaseState {
|
||||
|
||||
private BundleEntry myEntry;
|
||||
private Class<? extends IResource> myResourceType;
|
||||
|
||||
public AtomEntryState(Bundle theInstance) {
|
||||
public AtomEntryState(Bundle theInstance, Class<? extends IResource> theResourceType) {
|
||||
super(null);
|
||||
myEntry = new BundleEntry();
|
||||
myResourceType = theResourceType;
|
||||
theInstance.getEntries().add(myEntry);
|
||||
}
|
||||
|
||||
|
@ -275,7 +277,7 @@ class ParserState<T extends IElement> {
|
|||
} else if ("author".equals(theLocalPart)) {
|
||||
push(new AtomAuthorState(myEntry));
|
||||
} else if ("content".equals(theLocalPart)) {
|
||||
push(new PreResourceState(myEntry));
|
||||
push(new PreResourceState(myEntry, myResourceType));
|
||||
} else if ("summary".equals(theLocalPart)) {
|
||||
push(new XhtmlState(getPreResourceState(), myEntry.getSummary(), false));
|
||||
} else if ("category".equals(theLocalPart)) {
|
||||
|
@ -387,10 +389,12 @@ class ParserState<T extends IElement> {
|
|||
private class AtomState extends BaseState {
|
||||
|
||||
private Bundle myInstance;
|
||||
private Class<? extends IResource> myResourceType;
|
||||
|
||||
public AtomState(Bundle theInstance) {
|
||||
public AtomState(Bundle theInstance, Class<? extends IResource> theResourceType) {
|
||||
super(null);
|
||||
myInstance = theInstance;
|
||||
myResourceType = theResourceType;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -401,7 +405,7 @@ class ParserState<T extends IElement> {
|
|||
@Override
|
||||
public void enteringNewElement(String theNamespaceURI, String theLocalPart) throws DataFormatException {
|
||||
if ("entry".equals(theLocalPart) && verifyNamespace(XmlParser.ATOM_NS, theNamespaceURI)) {
|
||||
push(new AtomEntryState(myInstance));
|
||||
push(new AtomEntryState(myInstance, myResourceType));
|
||||
} else if (theLocalPart.equals("published")) {
|
||||
push(new AtomPrimitiveState(myInstance.getPublished()));
|
||||
} else if (theLocalPart.equals("title")) {
|
||||
|
@ -829,9 +833,11 @@ class ParserState<T extends IElement> {
|
|||
private class PreAtomState extends BaseState {
|
||||
|
||||
private Bundle myInstance;
|
||||
private Class<? extends IResource> myResourceType;
|
||||
|
||||
public PreAtomState() {
|
||||
public PreAtomState(Class<? extends IResource> theResourceType) {
|
||||
super(null);
|
||||
myResourceType = theResourceType;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -846,7 +852,7 @@ class ParserState<T extends IElement> {
|
|||
}
|
||||
|
||||
myInstance = new Bundle();
|
||||
push(new AtomState(myInstance));
|
||||
push(new AtomState(myInstance, myResourceType));
|
||||
|
||||
}
|
||||
|
||||
|
@ -877,9 +883,10 @@ class ParserState<T extends IElement> {
|
|||
return true;
|
||||
}
|
||||
|
||||
public PreResourceState(BundleEntry theEntry) {
|
||||
public PreResourceState(BundleEntry theEntry, Class<? extends IResource> theResourceType) {
|
||||
super(null);
|
||||
myEntry = theEntry;
|
||||
myResourceType=theResourceType;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -193,8 +193,9 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Bundle parseBundle(Reader theReader) {
|
||||
public <T extends IResource> Bundle parseBundle(Class<T> theResourceType, Reader theReader) {
|
||||
XMLEventReader streamReader;
|
||||
try {
|
||||
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);
|
||||
}
|
||||
|
||||
return parseBundle(streamReader);
|
||||
return parseBundle(streamReader, theResourceType);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -590,8 +591,8 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
}
|
||||
}
|
||||
|
||||
private Bundle parseBundle(XMLEventReader theStreamReader) {
|
||||
ParserState<Bundle> parserState = ParserState.getPreAtomInstance(myContext, false);
|
||||
private Bundle parseBundle(XMLEventReader theStreamReader, Class<? extends IResource> theResourceType) {
|
||||
ParserState<Bundle> parserState = ParserState.getPreAtomInstance(myContext, theResourceType, false);
|
||||
return doXmlLoop(theStreamReader, parserState);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
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.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
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.Reader;
|
||||
import java.util.List;
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
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.primitive.IdDt;
|
||||
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
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;
|
||||
|
||||
|
||||
|
|
|
@ -77,8 +77,8 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding {
|
|||
|
||||
private MethodReturnTypeEnum myMethodReturnType;
|
||||
private String myResourceName;
|
||||
private Class<? extends IResource> myResourceType;
|
||||
|
||||
|
||||
public BaseResourceReturningMethodBinding(Class<? extends IResource> theReturnResourceType, Method theMethod, FhirContext theConetxt, Object theProvider) {
|
||||
super(theMethod, theConetxt, theProvider);
|
||||
|
||||
|
@ -90,9 +90,11 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding {
|
|||
} else if (Bundle.class.isAssignableFrom(methodReturnType)) {
|
||||
myMethodReturnType = MethodReturnTypeEnum.BUNDLE;
|
||||
} 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) {
|
||||
ResourceDef resourceDefAnnotation = theReturnResourceType.getAnnotation(ResourceDef.class);
|
||||
if (resourceDefAnnotation == null) {
|
||||
|
@ -119,7 +121,12 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding {
|
|||
|
||||
switch (getReturnType()) {
|
||||
case BUNDLE: {
|
||||
Bundle bundle = parser.parseBundle(theResponseReader);
|
||||
Bundle bundle;
|
||||
if (myResourceType != null) {
|
||||
bundle = parser.parseBundle(myResourceType, theResponseReader);
|
||||
}else {
|
||||
bundle = parser.parseBundle(theResponseReader);
|
||||
}
|
||||
switch (getMethodReturnType()) {
|
||||
case BUNDLE:
|
||||
return bundle;
|
||||
|
@ -138,7 +145,12 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding {
|
|||
break;
|
||||
}
|
||||
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);
|
||||
if (lmHeaders != null && lmHeaders.size() > 0 && StringUtils.isNotBlank(lmHeaders.get(0))) {
|
||||
|
@ -238,7 +250,8 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding {
|
|||
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) {
|
||||
|
@ -254,7 +267,8 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding {
|
|||
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) {
|
||||
|
@ -271,8 +285,8 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding {
|
|||
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,
|
||||
NarrativeModeEnum theNarrativeMode) throws IOException {
|
||||
private void streamResponseAsBundle(RestfulServer theServer, HttpServletResponse theHttpResponse, List<IResource> theResult, EncodingUtil theResponseEncoding, String theServerBase,
|
||||
String theCompleteUrl, boolean thePrettyPrint, boolean theRequestIsBrowser, NarrativeModeEnum theNarrativeMode) throws IOException {
|
||||
assert !theServerBase.endsWith("/");
|
||||
|
||||
theHttpResponse.setStatus(200);
|
||||
|
@ -317,10 +331,10 @@ abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding {
|
|||
b.append(resId);
|
||||
|
||||
/*
|
||||
* If this is a history operation, we add the version of the
|
||||
* resource to the self link to indicate the version
|
||||
* If this is a history operation, we add the version of the 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);
|
||||
if (versionId != null) {
|
||||
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);
|
||||
if (theRequestIsBrowser && theServer.isUseBrowserFriendlyContentTypes()) {
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
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.Reader;
|
||||
import java.util.List;
|
||||
|
|
|
@ -130,6 +130,20 @@ class UpdateMethodBinding extends BaseOutcomeReturningMethodBindingWithResourceP
|
|||
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
|
||||
protected Set<RequestType> provideAllowableRequestTypes() {
|
||||
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.Request;
|
||||
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.BaseServerResponseException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
|
@ -74,6 +75,8 @@ public class RestfulServer extends HttpServlet {
|
|||
private boolean myUseBrowserFriendlyContentTypes;
|
||||
private ResourceBinding myNullResourceBinding = new ResourceBinding();
|
||||
|
||||
private boolean myStarted;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
|
@ -222,6 +225,7 @@ public class RestfulServer extends HttpServlet {
|
|||
throw new ServletException("Failed to initialize FHIR Restful server", ex);
|
||||
}
|
||||
|
||||
myStarted = true;
|
||||
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.
|
||||
*/
|
||||
public void setServerConformanceProvider(Object theServerConformanceProvider) {
|
||||
if (myFhirContext != null) {
|
||||
if (myStarted) {
|
||||
throw new IllegalStateException("Server is already started");
|
||||
}
|
||||
myServerConformanceProvider = theServerConformanceProvider;
|
||||
|
@ -524,6 +528,18 @@ public class RestfulServer extends HttpServlet {
|
|||
String nextString = tok.nextToken();
|
||||
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...
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ public abstract class BaseServerResponseException extends RuntimeException {
|
|||
registerExceptionType(MethodNotAllowedException.STATUS_CODE, MethodNotAllowedException.class);
|
||||
registerExceptionType(ResourceNotFoundException.STATUS_CODE, ResourceNotFoundException.class);
|
||||
registerExceptionType(ResourceVersionNotSpecifiedException.STATUS_CODE, ResourceVersionNotSpecifiedException.class);
|
||||
registerExceptionType(ResourceVersionConflictException.STATUS_CODE, ResourceVersionConflictException.class);
|
||||
registerExceptionType(UnprocessableEntityException.STATUS_CODE, UnprocessableEntityException.class);
|
||||
}
|
||||
|
||||
|
@ -143,5 +144,6 @@ public abstract class BaseServerResponseException extends RuntimeException {
|
|||
if (ourStatusCodeToExceptionType.containsKey(theStatusCode)) {
|
||||
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;
|
||||
|
||||
/*
|
||||
* #%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.InputStream;
|
||||
import java.util.HashMap;
|
||||
|
@ -11,8 +31,8 @@ import javax.servlet.http.HttpServletRequest;
|
|||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang.StringEscapeUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.lang3.StringEscapeUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.http.client.methods.HttpRequestBase;
|
||||
import org.apache.http.entity.ContentType;
|
||||
import org.thymeleaf.TemplateEngine;
|
||||
|
@ -145,7 +165,7 @@ public class PublicTesterServlet extends HttpServlet {
|
|||
ctx.setVariable("requestUrl", requestUrl);
|
||||
ctx.setVariable("action", action);
|
||||
ctx.setVariable("resultStatus", resultStatus);
|
||||
ctx.setVariable("resultBody", StringEscapeUtils.escapeHtml(resultBody));
|
||||
ctx.setVariable("resultBody", StringEscapeUtils.escapeHtml4(resultBody));
|
||||
ctx.setVariable("resultSyntaxHighlighterClass", resultSyntaxHighlighterClass);
|
||||
|
||||
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.BundleEntry;
|
||||
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.NarrativeDt;
|
||||
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.Define;
|
||||
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.primitive.DecimalDt;
|
||||
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);
|
||||
|
||||
/**
|
||||
* This sample has extra elements in <searchParam> that are not actually a
|
||||
* part of the spec any more..
|
||||
* This sample has extra elements in <searchParam> that are not actually a part of the spec any more..
|
||||
*/
|
||||
@Test
|
||||
public void testParseFuroreMetadataWithExtraElements() throws IOException {
|
||||
|
@ -61,6 +65,122 @@ public class JsonParserTest {
|
|||
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
|
||||
public void testEncodeExt() throws Exception {
|
||||
|
||||
|
@ -73,9 +193,9 @@ public class JsonParserTest {
|
|||
|
||||
String encoded = new FhirContext().newJsonParser().encodeResourceToString(valueSet);
|
||||
ourLog.info(encoded);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testEncodeResourceRef() throws DataFormatException, IOException {
|
||||
|
||||
|
@ -150,9 +270,6 @@ public class JsonParserTest {
|
|||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testSimpleResourceEncodeWithCustomType() throws IOException {
|
||||
|
||||
|
@ -164,7 +281,7 @@ public class JsonParserTest {
|
|||
assertEquals("aaaa", obs.getExtAtt().getContentType().getValue());
|
||||
assertEquals("str1", obs.getMoreExt().getStr1().getValue());
|
||||
assertEquals("2011-01-02", obs.getModExt().getValueAsString());
|
||||
|
||||
|
||||
List<ExtensionDt> undeclaredExtensions = obs.getContact().get(0).getName().getFamily().get(0).getUndeclaredExtensions();
|
||||
ExtensionDt undeclaredExtension = undeclaredExtensions.get(0);
|
||||
assertEquals("http://hl7.org/fhir/Profile/iso-21090#qualifier", undeclaredExtension.getUrl().getValue());
|
||||
|
@ -185,7 +302,7 @@ public class JsonParserTest {
|
|||
assertEquals(expected.toString(), actual.toString());
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSimpleBundleEncode() throws IOException {
|
||||
|
||||
|
@ -239,7 +356,8 @@ public class JsonParserTest {
|
|||
String encoded = ctx.newXmlParser().setPrettyPrint(true).encodeBundleToString(bundle);
|
||||
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());
|
||||
|
||||
BundleEntry entry = bundle.getEntries().get(0);
|
||||
|
@ -349,13 +467,13 @@ public class JsonParserTest {
|
|||
IParser newJsonParser = new FhirContext().newJsonParser();
|
||||
StringReader reader = new StringReader(enc);
|
||||
Patient parsed = newJsonParser.parseResource(Patient.class, reader);
|
||||
|
||||
|
||||
ourLog.info(new FhirContext().newXmlParser().setPrettyPrint(true).encodeResourceToString(parsed));
|
||||
|
||||
|
||||
assertEquals(1, parsed.getNameFirstRep().getUndeclaredExtensionsByUrl("http://examples.com#givenext").size());
|
||||
ExtensionDt ext = parsed.getNameFirstRep().getUndeclaredExtensionsByUrl("http://examples.com#givenext").get(0);
|
||||
assertEquals("Hello", ext.getValueAsPrimitive().getValue());
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -31,6 +31,7 @@ import ca.uhn.fhir.model.api.Bundle;
|
|||
import ca.uhn.fhir.model.api.BundleEntry;
|
||||
import ca.uhn.fhir.model.api.ExtensionDt;
|
||||
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.NarrativeDt;
|
||||
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.XhtmlDt;
|
||||
import ca.uhn.fhir.narrative.INarrativeGenerator;
|
||||
import ca.uhn.fhir.parser.JsonParserTest.MyPatientWithOneDeclaredAddressExtension;
|
||||
import ca.uhn.fhir.parser.JsonParserTest.MyPatientWithOneDeclaredExtension;
|
||||
|
||||
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
|
||||
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.PathSpecification;
|
||||
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.IdentifierDt;
|
||||
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.IntegerDt;
|
||||
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.client.api.IBasicClient;
|
||||
import ca.uhn.fhir.rest.param.CodingListParam;
|
||||
import ca.uhn.fhir.rest.param.DateRangeParam;
|
||||
import ca.uhn.fhir.rest.param.QualifiedDateParam;
|
||||
|
@ -131,7 +137,7 @@ public class ClientTest {
|
|||
|
||||
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), 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().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
|
||||
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;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.StringReader;
|
||||
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.IdentifierDt;
|
||||
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.OperationOutcome;
|
||||
import ca.uhn.fhir.model.dstu.resource.Patient;
|
||||
|
@ -860,11 +859,10 @@ public class ResfulServerMethodTest {
|
|||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testUpdateWrongResourceType() throws Exception {
|
||||
|
||||
// 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.addIdentifier().setValue("002");
|
||||
|
||||
|
@ -902,16 +900,17 @@ public class ResfulServerMethodTest {
|
|||
patient.getIdentifier().setValue("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")));
|
||||
|
||||
HttpResponse status = ourClient.execute(httpPut);
|
||||
|
||||
String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
ourLog.info("Response was:\n{}", responseContent);
|
||||
// String responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
// ourLog.info("Response was:\n{}", responseContent);
|
||||
|
||||
assertEquals(201, status.getStatusLine().getStatusCode());
|
||||
assertEquals("http://localhost:" + ourPort + "/DiagnosticReport/001/_history/002", status.getFirstHeader("Location").getValue());
|
||||
assertEquals(204, status.getStatusLine().getStatusCode());
|
||||
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);
|
||||
|
||||
responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
ourLog.info("Response was:\n{}", responseContent);
|
||||
// responseContent = IOUtils.toString(status.getEntity().getContent());
|
||||
// ourLog.info("Response was:\n{}", responseContent);
|
||||
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
assertEquals("", responseContent);
|
||||
assertEquals(204, status.getStatusLine().getStatusCode());
|
||||
assertNull(status.getEntity());
|
||||
// assertEquals("", responseContent);
|
||||
|
||||
}
|
||||
|
||||
|
@ -1043,6 +1043,14 @@ public class ResfulServerMethodTest {
|
|||
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")
|
||||
@Update()
|
||||
public MethodOutcome updateDiagnosticReportWithVersionAndNoResponse(@IdParam IdDt theId, @ResourceParam DiagnosticReport thePatient) {
|
||||
|
@ -1281,10 +1289,10 @@ public class ResfulServerMethodTest {
|
|||
|
||||
@SuppressWarnings("unused")
|
||||
@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
|
||||
* (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
|
||||
* update/create/etc method
|
||||
*/
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package ca.uhn.fhir.rest.server;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
@ -16,8 +17,10 @@ import org.junit.Test;
|
|||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
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.IdentifierDt;
|
||||
import ca.uhn.fhir.model.dstu.composite.QuantityDt;
|
||||
import ca.uhn.fhir.model.dstu.resource.Organization;
|
||||
import ca.uhn.fhir.model.dstu.resource.Patient;
|
||||
import ca.uhn.fhir.model.dstu.valueset.IdentifierUseEnum;
|
||||
|
@ -75,7 +78,7 @@ public class TesterTest {
|
|||
|
||||
@Test
|
||||
public void testTester() throws Exception {
|
||||
// if (true) return;
|
||||
if (true) return;
|
||||
|
||||
myRestfulServer.setProviders(new SearchProvider(), new GlobalHistoryProvider());
|
||||
myServer.start();
|
||||
|
@ -111,7 +114,10 @@ public class TesterTest {
|
|||
}
|
||||
|
||||
@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 (IdentifierDt nextId : next.getIdentifier()) {
|
||||
if (nextId.matchesSystemAndValue(theIdentifier)) {
|
||||
|
|
Loading…
Reference in New Issue