Fix some bugs on the generic client
This commit is contained in:
parent
b937d5c2dc
commit
fb998a6a32
|
@ -20,7 +20,9 @@ package ca.uhn.fhir.parser;
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import static org.apache.commons.lang3.StringUtils.*;
|
import static org.apache.commons.lang3.StringUtils.defaultString;
|
||||||
|
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||||
|
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
|
@ -45,13 +47,10 @@ import javax.json.JsonValue;
|
||||||
import javax.json.JsonValue.ValueType;
|
import javax.json.JsonValue.ValueType;
|
||||||
import javax.json.stream.JsonGenerator;
|
import javax.json.stream.JsonGenerator;
|
||||||
import javax.json.stream.JsonGeneratorFactory;
|
import javax.json.stream.JsonGeneratorFactory;
|
||||||
import javax.xml.stream.XMLStreamException;
|
|
||||||
import javax.xml.stream.XMLStreamWriter;
|
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.commons.lang3.Validate;
|
import org.apache.commons.lang3.Validate;
|
||||||
|
|
||||||
import ch.qos.logback.core.boolex.EventEvaluator;
|
|
||||||
import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
|
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;
|
||||||
|
@ -64,7 +63,6 @@ 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;
|
||||||
import ca.uhn.fhir.model.api.Tag;
|
|
||||||
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.IElement;
|
import ca.uhn.fhir.model.api.IElement;
|
||||||
|
@ -72,6 +70,7 @@ import ca.uhn.fhir.model.api.IIdentifiableElement;
|
||||||
import ca.uhn.fhir.model.api.IPrimitiveDatatype;
|
import ca.uhn.fhir.model.api.IPrimitiveDatatype;
|
||||||
import ca.uhn.fhir.model.api.IResource;
|
import ca.uhn.fhir.model.api.IResource;
|
||||||
import ca.uhn.fhir.model.api.ISupportsUndeclaredExtensions;
|
import ca.uhn.fhir.model.api.ISupportsUndeclaredExtensions;
|
||||||
|
import ca.uhn.fhir.model.api.Tag;
|
||||||
import ca.uhn.fhir.model.api.TagList;
|
import ca.uhn.fhir.model.api.TagList;
|
||||||
import ca.uhn.fhir.model.api.annotation.Child;
|
import ca.uhn.fhir.model.api.annotation.Child;
|
||||||
import ca.uhn.fhir.model.dstu.composite.ContainedDt;
|
import ca.uhn.fhir.model.dstu.composite.ContainedDt;
|
||||||
|
@ -88,6 +87,8 @@ 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;
|
private static final Set<String> BUNDLE_TEXTNODE_CHILDREN;
|
||||||
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(JsonParser.HeldExtension.class);
|
||||||
|
|
||||||
static {
|
static {
|
||||||
HashSet<String> hashSet = new HashSet<String>();
|
HashSet<String> hashSet = new HashSet<String>();
|
||||||
hashSet.add("title");
|
hashSet.add("title");
|
||||||
|
@ -105,6 +106,48 @@ public class JsonParser extends BaseParser implements IParser {
|
||||||
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 void encodeBundleToWriter(Bundle theBundle, Writer theWriter) throws IOException {
|
public void encodeBundleToWriter(Bundle theBundle, Writer theWriter) throws IOException {
|
||||||
JsonGenerator eventWriter = createJsonGenerator(theWriter);
|
JsonGenerator eventWriter = createJsonGenerator(theWriter);
|
||||||
|
@ -170,173 +213,8 @@ public class JsonParser extends BaseParser implements IParser {
|
||||||
eventWriter.close();
|
eventWriter.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private void encodeChildElementToStreamWriter(RuntimeResourceDefinition theResDef, IResource theResource, JsonGenerator theWriter, IElement theValue, BaseRuntimeElementDefinition<?> theChildDef,
|
||||||
public void encodeResourceToWriter(IResource theResource, Writer theWriter) throws IOException {
|
String theChildName) 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 void encodeTagListToWriter(TagList theTagList, Writer theWriter) throws IOException {
|
|
||||||
JsonGenerator eventWriter = createJsonGenerator(theWriter);
|
|
||||||
|
|
||||||
eventWriter.writeStartObject();
|
|
||||||
|
|
||||||
eventWriter.write("resourceType", TagList.ELEMENT_NAME);
|
|
||||||
|
|
||||||
eventWriter.writeStartArray(TagList.ATTR_CATEGORY);
|
|
||||||
for (Tag next : theTagList) {
|
|
||||||
eventWriter.writeStartObject();
|
|
||||||
|
|
||||||
if (isNotBlank(next.getTerm())) {
|
|
||||||
eventWriter.write(Tag.ATTR_TERM, next.getTerm());
|
|
||||||
}
|
|
||||||
if (isNotBlank(next.getLabel())) {
|
|
||||||
eventWriter.write(Tag.ATTR_LABEL, next.getLabel());
|
|
||||||
}
|
|
||||||
if (isNotBlank(next.getScheme())) {
|
|
||||||
eventWriter.write(Tag.ATTR_SCHEME, next.getScheme());
|
|
||||||
}
|
|
||||||
|
|
||||||
eventWriter.writeEnd();
|
|
||||||
}
|
|
||||||
eventWriter.writeEnd();
|
|
||||||
|
|
||||||
eventWriter.writeEnd();
|
|
||||||
eventWriter.flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
@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;
|
|
||||||
}
|
|
||||||
|
|
||||||
@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 TagList parseTagList(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();
|
|
||||||
|
|
||||||
ParserState<TagList> state = ParserState.getPreTagListInstance(myContext, true);
|
|
||||||
state.enteringNewElement(null, resourceType);
|
|
||||||
|
|
||||||
parseChildren(object, state);
|
|
||||||
|
|
||||||
state.endingElement();
|
|
||||||
|
|
||||||
return state.getObject();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IParser setPrettyPrint(boolean thePrettyPrint) {
|
|
||||||
myPrettyPrint = thePrettyPrint;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void encodeChildElementToStreamWriter(RuntimeResourceDefinition theResDef, IResource theResource, JsonGenerator theWriter, IElement theValue, BaseRuntimeElementDefinition<?> theChildDef, String theChildName) throws IOException {
|
|
||||||
|
|
||||||
switch (theChildDef.getChildType()) {
|
switch (theChildDef.getChildType()) {
|
||||||
case PRIMITIVE_DATATYPE: {
|
case PRIMITIVE_DATATYPE: {
|
||||||
|
@ -438,7 +316,8 @@ public class JsonParser extends BaseParser implements IParser {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void encodeCompositeElementChildrenToStreamWriter(RuntimeResourceDefinition theResDef, IResource theResource, IElement theElement, JsonGenerator theEventWriter, List<? extends BaseRuntimeChildDefinition> theChildren) throws IOException {
|
private void encodeCompositeElementChildrenToStreamWriter(RuntimeResourceDefinition theResDef, IResource theResource, IElement theElement, JsonGenerator theEventWriter,
|
||||||
|
List<? extends BaseRuntimeChildDefinition> theChildren) throws IOException {
|
||||||
for (BaseRuntimeChildDefinition nextChild : theChildren) {
|
for (BaseRuntimeChildDefinition nextChild : theChildren) {
|
||||||
if (nextChild instanceof RuntimeChildNarrativeDefinition) {
|
if (nextChild instanceof RuntimeChildNarrativeDefinition) {
|
||||||
INarrativeGenerator gen = myContext.getNarrativeGenerator();
|
INarrativeGenerator gen = myContext.getNarrativeGenerator();
|
||||||
|
@ -570,7 +449,8 @@ public class JsonParser extends BaseParser implements IParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void encodeCompositeElementToStreamWriter(RuntimeResourceDefinition theResDef, IResource theResource, IElement theElement, JsonGenerator theEventWriter, BaseRuntimeElementCompositeDefinition<?> resDef) throws IOException, DataFormatException {
|
private void encodeCompositeElementToStreamWriter(RuntimeResourceDefinition theResDef, IResource theResource, IElement theElement, JsonGenerator theEventWriter,
|
||||||
|
BaseRuntimeElementCompositeDefinition<?> resDef) throws IOException, DataFormatException {
|
||||||
encodeCompositeElementChildrenToStreamWriter(theResDef, theResource, theElement, theEventWriter, resDef.getExtensions());
|
encodeCompositeElementChildrenToStreamWriter(theResDef, theResource, theElement, theEventWriter, resDef.getExtensions());
|
||||||
encodeCompositeElementChildrenToStreamWriter(theResDef, theResource, theElement, theEventWriter, resDef.getChildren());
|
encodeCompositeElementChildrenToStreamWriter(theResDef, theResource, theElement, theEventWriter, resDef.getChildren());
|
||||||
}
|
}
|
||||||
|
@ -598,12 +478,52 @@ public class JsonParser extends BaseParser implements IParser {
|
||||||
theEventWriter.writeEnd();
|
theEventWriter.writeEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@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 void encodeTagListToWriter(TagList theTagList, Writer theWriter) throws IOException {
|
||||||
|
JsonGenerator eventWriter = createJsonGenerator(theWriter);
|
||||||
|
|
||||||
|
eventWriter.writeStartObject();
|
||||||
|
|
||||||
|
eventWriter.write("resourceType", TagList.ELEMENT_NAME);
|
||||||
|
|
||||||
|
eventWriter.writeStartArray(TagList.ATTR_CATEGORY);
|
||||||
|
for (Tag next : theTagList) {
|
||||||
|
eventWriter.writeStartObject();
|
||||||
|
|
||||||
|
if (isNotBlank(next.getTerm())) {
|
||||||
|
eventWriter.write(Tag.ATTR_TERM, next.getTerm());
|
||||||
|
}
|
||||||
|
if (isNotBlank(next.getLabel())) {
|
||||||
|
eventWriter.write(Tag.ATTR_LABEL, next.getLabel());
|
||||||
|
}
|
||||||
|
if (isNotBlank(next.getScheme())) {
|
||||||
|
eventWriter.write(Tag.ATTR_SCHEME, next.getScheme());
|
||||||
|
}
|
||||||
|
|
||||||
|
eventWriter.writeEnd();
|
||||||
|
}
|
||||||
|
eventWriter.writeEnd();
|
||||||
|
|
||||||
|
eventWriter.writeEnd();
|
||||||
|
eventWriter.flush();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is useful only for the two cases where extensions are encoded as
|
* 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
|
||||||
* direct children (e.g. not in some object called _name): resource
|
|
||||||
* extensions, and extension extensions
|
|
||||||
*/
|
*/
|
||||||
private void extractAndWriteExtensionsAsDirectChild(IElement theElement, JsonGenerator theEventWriter, BaseRuntimeElementDefinition<?> theElementDef, RuntimeResourceDefinition theResDef, IResource theResource) throws IOException {
|
private void extractAndWriteExtensionsAsDirectChild(IElement theElement, JsonGenerator theEventWriter, BaseRuntimeElementDefinition<?> theElementDef, RuntimeResourceDefinition theResDef,
|
||||||
|
IResource theResource) throws IOException {
|
||||||
List<HeldExtension> extensions = new ArrayList<HeldExtension>(0);
|
List<HeldExtension> extensions = new ArrayList<HeldExtension>(0);
|
||||||
List<HeldExtension> modifierExtensions = new ArrayList<HeldExtension>(0);
|
List<HeldExtension> modifierExtensions = new ArrayList<HeldExtension>(0);
|
||||||
|
|
||||||
|
@ -678,6 +598,30 @@ public class JsonParser extends BaseParser implements IParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@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) {
|
private void parseBundleChildren(JsonObject theObject, ParserState<?> theState) {
|
||||||
for (String nextName : theObject.keySet()) {
|
for (String nextName : theObject.keySet()) {
|
||||||
if ("resourceType".equals(nextName)) {
|
if ("resourceType".equals(nextName)) {
|
||||||
|
@ -830,6 +774,65 @@ public class JsonParser extends BaseParser implements IParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@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 TagList parseTagList(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();
|
||||||
|
|
||||||
|
ParserState<TagList> state = ParserState.getPreTagListInstance(myContext, true);
|
||||||
|
state.enteringNewElement(null, resourceType);
|
||||||
|
|
||||||
|
parseChildren(object, state);
|
||||||
|
|
||||||
|
state.endingElement();
|
||||||
|
|
||||||
|
return state.getObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
@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) {
|
||||||
if (isNotBlank(theLink.getValue())) {
|
if (isNotBlank(theLink.getValue())) {
|
||||||
theEventWriter.writeStartObject();
|
theEventWriter.writeStartObject();
|
||||||
|
@ -850,7 +853,8 @@ public class JsonParser extends BaseParser implements IParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeExtensionsAsDirectChild(IResource theResource, JsonGenerator theEventWriter, RuntimeResourceDefinition resDef, List<HeldExtension> extensions, List<HeldExtension> modifierExtensions) throws IOException {
|
private void writeExtensionsAsDirectChild(IResource theResource, JsonGenerator theEventWriter, RuntimeResourceDefinition resDef, List<HeldExtension> extensions,
|
||||||
|
List<HeldExtension> modifierExtensions) throws IOException {
|
||||||
if (extensions.isEmpty() == false) {
|
if (extensions.isEmpty() == false) {
|
||||||
theEventWriter.writeStartArray("extension");
|
theEventWriter.writeStartArray("extension");
|
||||||
for (HeldExtension next : extensions) {
|
for (HeldExtension next : extensions) {
|
||||||
|
@ -933,12 +937,13 @@ public class JsonParser extends BaseParser implements IParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeUndeclaredExt(RuntimeResourceDefinition theResDef, IResource theResource, JsonGenerator theEventWriter, ExtensionDt ext) throws IOException {
|
private void writeUndeclaredExt(RuntimeResourceDefinition theResDef, IResource theResource, JsonGenerator theEventWriter, ExtensionDt ext) throws IOException {
|
||||||
|
IElement value = ext.getValue();
|
||||||
|
|
||||||
theEventWriter.writeStartObject();
|
theEventWriter.writeStartObject();
|
||||||
theEventWriter.write("url", ext.getUrl().getValue());
|
theEventWriter.write("url", ext.getUrl().getValue());
|
||||||
|
|
||||||
IElement value = ext.getValue();
|
|
||||||
if (value == null && ext.getAllUndeclaredExtensions().isEmpty()) {
|
if (value == null && ext.getAllUndeclaredExtensions().isEmpty()) {
|
||||||
theEventWriter.writeNull();
|
ourLog.debug("Extension with URL[{}] has no value", ext.getUrl().getValue());
|
||||||
} else if (value == null) {
|
} else if (value == null) {
|
||||||
theEventWriter.writeStartArray("extension");
|
theEventWriter.writeStartArray("extension");
|
||||||
for (ExtensionDt next : ext.getUndeclaredExtensions()) {
|
for (ExtensionDt next : ext.getUndeclaredExtensions()) {
|
||||||
|
@ -961,5 +966,4 @@ public class JsonParser extends BaseParser implements IParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,19 +60,15 @@ public abstract class BaseClient {
|
||||||
private boolean myPrettyPrint = false;
|
private boolean myPrettyPrint = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the encoding that will be used on requests. Default is
|
* Returns the encoding that will be used on requests. Default is <code>null</code>, which means the client will not explicitly request an encoding. (This is standard behaviour according to the
|
||||||
* <code>null</code>, which means the client will not explicitly request an
|
* FHIR specification)
|
||||||
* encoding. (This is standard behaviour according to the FHIR
|
|
||||||
* specification)
|
|
||||||
*/
|
*/
|
||||||
public EncodingEnum getEncoding() {
|
public EncodingEnum getEncoding() {
|
||||||
return myEncoding;
|
return myEncoding;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the encoding that will be used on requests. Default is
|
* Sets the encoding that will be used on requests. Default is <code>null</code>, which means the client will not explicitly request an encoding. (This is standard behaviour according to the FHIR
|
||||||
* <code>null</code>, which means the client will not explicitly request an
|
|
||||||
* encoding. (This is standard behaviour according to the FHIR
|
|
||||||
* specification)
|
* specification)
|
||||||
*/
|
*/
|
||||||
public BaseClient setEncoding(EncodingEnum theEncoding) {
|
public BaseClient setEncoding(EncodingEnum theEncoding) {
|
||||||
|
@ -87,16 +83,14 @@ public abstract class BaseClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For now, this is a part of the internal API of HAPI - Use with caution as
|
* For now, this is a part of the internal API of HAPI - Use with caution as this method may change!
|
||||||
* this method may change!
|
|
||||||
*/
|
*/
|
||||||
public HttpResponse getLastResponse() {
|
public HttpResponse getLastResponse() {
|
||||||
return myLastResponse;
|
return myLastResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For now, this is a part of the internal API of HAPI - Use with caution as
|
* For now, this is a part of the internal API of HAPI - Use with caution as this method may change!
|
||||||
* this method may change!
|
|
||||||
*/
|
*/
|
||||||
public String getLastResponseBody() {
|
public String getLastResponseBody() {
|
||||||
return myLastResponseBody;
|
return myLastResponseBody;
|
||||||
|
@ -106,11 +100,11 @@ public abstract class BaseClient {
|
||||||
return myUrlBase;
|
return myUrlBase;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object invokeClient(IClientResponseHandler binding, BaseClientInvocation clientInvocation) {
|
<T> T invokeClient(IClientResponseHandler<T> binding, BaseClientInvocation clientInvocation) {
|
||||||
return invokeClient(binding, clientInvocation, false);
|
return invokeClient(binding, clientInvocation, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
Object invokeClient(IClientResponseHandler binding, BaseClientInvocation clientInvocation, boolean theLogRequestAndResponse) {
|
<T> T invokeClient(IClientResponseHandler<T> binding, BaseClientInvocation clientInvocation, boolean theLogRequestAndResponse) {
|
||||||
// TODO: handle non 2xx status codes by throwing the correct exception,
|
// TODO: handle non 2xx status codes by throwing the correct exception,
|
||||||
// and ensure it's passed upwards
|
// and ensure it's passed upwards
|
||||||
HttpRequestBase httpRequest;
|
HttpRequestBase httpRequest;
|
||||||
|
@ -160,13 +154,24 @@ public abstract class BaseClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (response.getStatusLine().getStatusCode() < 200 || response.getStatusLine().getStatusCode() > 299) {
|
if (response.getStatusLine().getStatusCode() < 200 || response.getStatusLine().getStatusCode() > 299) {
|
||||||
throw BaseServerResponseException.newInstance(response.getStatusLine().getStatusCode(), response.getStatusLine().getReasonPhrase());
|
BaseServerResponseException exception = BaseServerResponseException.newInstance(response.getStatusLine().getStatusCode(), response.getStatusLine().getReasonPhrase());
|
||||||
|
|
||||||
|
try {
|
||||||
|
String body = IOUtils.toString(reader);
|
||||||
|
exception.setResponseBody(body);
|
||||||
|
} catch (Exception e) {
|
||||||
|
ourLog.debug("Failed to read input stream", e);
|
||||||
|
} finally {
|
||||||
|
IOUtils.closeQuietly(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw exception;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return binding.invokeClient(mimeType, reader, response.getStatusLine().getStatusCode(), headers);
|
return binding.invokeClient(mimeType, reader, response.getStatusLine().getStatusCode(), headers);
|
||||||
} finally {
|
} finally {
|
||||||
reader.close();
|
IOUtils.closeQuietly(reader);
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (IllegalStateException e) {
|
} catch (IllegalStateException e) {
|
||||||
|
@ -201,32 +206,28 @@ public abstract class BaseClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For now, this is a part of the internal API of HAPI - Use with caution as
|
* For now, this is a part of the internal API of HAPI - Use with caution as this method may change!
|
||||||
* this method may change!
|
|
||||||
*/
|
*/
|
||||||
public boolean isKeepResponses() {
|
public boolean isKeepResponses() {
|
||||||
return myKeepResponses;
|
return myKeepResponses;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For now, this is a part of the internal API of HAPI - Use with caution as
|
* For now, this is a part of the internal API of HAPI - Use with caution as this method may change!
|
||||||
* this method may change!
|
|
||||||
*/
|
*/
|
||||||
public void setKeepResponses(boolean theKeepResponses) {
|
public void setKeepResponses(boolean theKeepResponses) {
|
||||||
myKeepResponses = theKeepResponses;
|
myKeepResponses = theKeepResponses;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For now, this is a part of the internal API of HAPI - Use with caution as
|
* For now, this is a part of the internal API of HAPI - Use with caution as this method may change!
|
||||||
* this method may change!
|
|
||||||
*/
|
*/
|
||||||
public void setLastResponse(HttpResponse theLastResponse) {
|
public void setLastResponse(HttpResponse theLastResponse) {
|
||||||
myLastResponse = theLastResponse;
|
myLastResponse = theLastResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For now, this is a part of the internal API of HAPI - Use with caution as
|
* For now, this is a part of the internal API of HAPI - Use with caution as this method may change!
|
||||||
* this method may change!
|
|
||||||
*/
|
*/
|
||||||
public void setLastResponseBody(String theLastResponseBody) {
|
public void setLastResponseBody(String theLastResponseBody) {
|
||||||
myLastResponseBody = theLastResponseBody;
|
myLastResponseBody = theLastResponseBody;
|
||||||
|
@ -252,20 +253,16 @@ public abstract class BaseClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the pretty print flag, which is a request to the server for it to
|
* Returns the pretty print flag, which is a request to the server for it to return "pretty printed" responses. Note that this is currently a non-standard flag (_pretty) which is supported only by
|
||||||
* return "pretty printed" responses. Note that this is currently a
|
* HAPI based servers (and any other servers which might implement it).
|
||||||
* non-standard flag (_pretty) which is supported only by HAPI based servers
|
|
||||||
* (and any other servers which might implement it).
|
|
||||||
*/
|
*/
|
||||||
public boolean isPrettyPrint() {
|
public boolean isPrettyPrint() {
|
||||||
return myPrettyPrint;
|
return myPrettyPrint;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the pretty print flag, which is a request to the server for it to
|
* Sets the pretty print flag, which is a request to the server for it to return "pretty printed" responses. Note that this is currently a non-standard flag (_pretty) which is supported only by
|
||||||
* return "pretty printed" responses. Note that this is currently a
|
* HAPI based servers (and any other servers which might implement it).
|
||||||
* non-standard flag (_pretty) which is supported only by HAPI based servers
|
|
||||||
* (and any other servers which might implement it).
|
|
||||||
*/
|
*/
|
||||||
public BaseClient setPrettyPrint(boolean thePrettyPrint) {
|
public BaseClient setPrettyPrint(boolean thePrettyPrint) {
|
||||||
myPrettyPrint = thePrettyPrint;
|
myPrettyPrint = thePrettyPrint;
|
||||||
|
|
|
@ -35,7 +35,7 @@ import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||||
|
|
||||||
public class ClientInvocationHandler extends BaseClient implements InvocationHandler {
|
public class ClientInvocationHandler extends BaseClient implements InvocationHandler {
|
||||||
|
|
||||||
private final Map<Method, BaseMethodBinding> myBindings = new HashMap<Method, BaseMethodBinding>();
|
private final Map<Method, BaseMethodBinding<?>> myBindings = new HashMap<Method, BaseMethodBinding<?>>();
|
||||||
|
|
||||||
private final Map<Method, ILambda> myMethodToLambda = new HashMap<Method, ILambda>();
|
private final Map<Method, ILambda> myMethodToLambda = new HashMap<Method, ILambda>();
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ public class ClientInvocationHandler extends BaseClient implements InvocationHan
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addBinding(Method theMethod, BaseMethodBinding theBinding) {
|
public void addBinding(Method theMethod, BaseMethodBinding<?> theBinding) {
|
||||||
myBindings.put(theMethod, theBinding);
|
myBindings.put(theMethod, theBinding);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ public class ClientInvocationHandler extends BaseClient implements InvocationHan
|
||||||
return directRetVal;
|
return directRetVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseMethodBinding binding = myBindings.get(theMethod);
|
BaseMethodBinding<?> binding = myBindings.get(theMethod);
|
||||||
if (binding != null) {
|
if (binding != null) {
|
||||||
BaseClientInvocation clientInvocation = binding.invokeClient(theArgs);
|
BaseClientInvocation clientInvocation = binding.invokeClient(theArgs);
|
||||||
return invokeClient(binding, clientInvocation);
|
return invokeClient(binding, clientInvocation);
|
||||||
|
|
|
@ -40,6 +40,7 @@ import ca.uhn.fhir.model.dstu.resource.Conformance;
|
||||||
import ca.uhn.fhir.model.primitive.IdDt;
|
import ca.uhn.fhir.model.primitive.IdDt;
|
||||||
import ca.uhn.fhir.parser.IParser;
|
import ca.uhn.fhir.parser.IParser;
|
||||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||||
|
import ca.uhn.fhir.rest.client.exceptions.NonFhirResponseException;
|
||||||
import ca.uhn.fhir.rest.gclient.ICriterion;
|
import ca.uhn.fhir.rest.gclient.ICriterion;
|
||||||
import ca.uhn.fhir.rest.gclient.ICriterionInternal;
|
import ca.uhn.fhir.rest.gclient.ICriterionInternal;
|
||||||
import ca.uhn.fhir.rest.gclient.IQuery;
|
import ca.uhn.fhir.rest.gclient.IQuery;
|
||||||
|
@ -68,8 +69,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
||||||
private HttpRequestBase myLastRequest;
|
private HttpRequestBase myLastRequest;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For now, this is a part of the internal API of HAPI - Use with caution as
|
* For now, this is a part of the internal API of HAPI - Use with caution as this method may change!
|
||||||
* this method may change!
|
|
||||||
*/
|
*/
|
||||||
public GenericClient(FhirContext theContext, HttpClient theHttpClient, String theServerBase) {
|
public GenericClient(FhirContext theContext, HttpClient theHttpClient, String theServerBase) {
|
||||||
super(theHttpClient, theServerBase);
|
super(theHttpClient, theServerBase);
|
||||||
|
@ -83,16 +83,8 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
||||||
myLastRequest = invocation.asHttpRequest(getServerBase(), createExtraParams(), getEncoding());
|
myLastRequest = invocation.asHttpRequest(getServerBase(), createExtraParams(), getEncoding());
|
||||||
}
|
}
|
||||||
|
|
||||||
IClientResponseHandler binding = new IClientResponseHandler() {
|
ResourceResponseHandler<Conformance> binding = new ResourceResponseHandler<Conformance>(Conformance.class);
|
||||||
@Override
|
Conformance resp = invokeClient(binding, invocation);
|
||||||
public Object invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) throws IOException, BaseServerResponseException {
|
|
||||||
EncodingEnum respType = EncodingEnum.forContentType(theResponseMimeType);
|
|
||||||
IParser parser = respType.newParser(myContext);
|
|
||||||
return parser.parseResource(Conformance.class, theResponseReader);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Conformance resp = (Conformance) invokeClient(binding, invocation);
|
|
||||||
return resp;
|
return resp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,15 +98,9 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
||||||
RuntimeResourceDefinition def = myContext.getResourceDefinition(theResource);
|
RuntimeResourceDefinition def = myContext.getResourceDefinition(theResource);
|
||||||
final String resourceName = def.getName();
|
final String resourceName = def.getName();
|
||||||
|
|
||||||
IClientResponseHandler binding = new IClientResponseHandler() {
|
OutcomeResponseHandler binding = new OutcomeResponseHandler(resourceName);
|
||||||
@Override
|
|
||||||
public Object invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) throws IOException, BaseServerResponseException {
|
|
||||||
MethodOutcome response = BaseOutcomeReturningMethodBinding.process2xxResponse(myContext, resourceName, theResponseStatusCode, theResponseMimeType, theResponseReader, theHeaders);
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
MethodOutcome resp = (MethodOutcome) invokeClient(binding, invocation);
|
MethodOutcome resp = invokeClient(binding, invocation);
|
||||||
return resp;
|
return resp;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -127,15 +113,8 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
final String resourceName = myContext.getResourceDefinition(theType).getName();
|
final String resourceName = myContext.getResourceDefinition(theType).getName();
|
||||||
IClientResponseHandler binding = new IClientResponseHandler() {
|
OutcomeResponseHandler binding = new OutcomeResponseHandler(resourceName);
|
||||||
@Override
|
MethodOutcome resp = invokeClient(binding, invocation);
|
||||||
public Object invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) throws IOException, BaseServerResponseException {
|
|
||||||
MethodOutcome response = BaseOutcomeReturningMethodBinding.process2xxResponse(myContext, resourceName, theResponseStatusCode, theResponseMimeType, theResponseReader, theHeaders);
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
MethodOutcome resp = (MethodOutcome) invokeClient(binding, invocation);
|
|
||||||
return resp;
|
return resp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,16 +134,8 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
||||||
myLastRequest = invocation.asHttpRequest(getServerBase(), createExtraParams(), getEncoding());
|
myLastRequest = invocation.asHttpRequest(getServerBase(), createExtraParams(), getEncoding());
|
||||||
}
|
}
|
||||||
|
|
||||||
IClientResponseHandler binding = new IClientResponseHandler() {
|
BundleResponseHandler binding = new BundleResponseHandler(theType);
|
||||||
@Override
|
Bundle resp = invokeClient(binding, invocation);
|
||||||
public Object invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) throws IOException, BaseServerResponseException {
|
|
||||||
EncodingEnum respType = EncodingEnum.forContentType(theResponseMimeType);
|
|
||||||
IParser parser = respType.newParser(myContext);
|
|
||||||
return parser.parseBundle(theType, theResponseReader);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Bundle resp = (Bundle) invokeClient(binding, invocation);
|
|
||||||
return resp;
|
return resp;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -181,17 +152,8 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
||||||
myLastRequest = invocation.asHttpRequest(getServerBase(), createExtraParams(), getEncoding());
|
myLastRequest = invocation.asHttpRequest(getServerBase(), createExtraParams(), getEncoding());
|
||||||
}
|
}
|
||||||
|
|
||||||
IClientResponseHandler binding = new IClientResponseHandler() {
|
ResourceResponseHandler<T> binding = new ResourceResponseHandler<T>(theType);
|
||||||
@Override
|
T resp = invokeClient(binding, invocation);
|
||||||
public Object invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) throws IOException, BaseServerResponseException {
|
|
||||||
EncodingEnum respType = EncodingEnum.forContentType(theResponseMimeType);
|
|
||||||
IParser parser = respType.newParser(myContext);
|
|
||||||
return parser.parseResource(theType, theResponseReader);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
T resp = (T) invokeClient(binding, invocation);
|
|
||||||
return resp;
|
return resp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -221,22 +183,13 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
||||||
myLastRequest = invocation.asHttpRequest(getServerBase(), createExtraParams(), getEncoding());
|
myLastRequest = invocation.asHttpRequest(getServerBase(), createExtraParams(), getEncoding());
|
||||||
}
|
}
|
||||||
|
|
||||||
IClientResponseHandler binding = new IClientResponseHandler() {
|
BundleResponseHandler binding = new BundleResponseHandler(theType);
|
||||||
@Override
|
Bundle resp = invokeClient(binding, invocation);
|
||||||
public Object invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) throws IOException, BaseServerResponseException {
|
|
||||||
EncodingEnum respType = EncodingEnum.forContentType(theResponseMimeType);
|
|
||||||
IParser parser = respType.newParser(myContext);
|
|
||||||
return parser.parseBundle(theType, theResponseReader);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Bundle resp = (Bundle) invokeClient(binding, invocation);
|
|
||||||
return resp;
|
return resp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For now, this is a part of the internal API of HAPI - Use with caution as
|
* For now, this is a part of the internal API of HAPI - Use with caution as this method may change!
|
||||||
* this method may change!
|
|
||||||
*/
|
*/
|
||||||
public void setLastRequest(HttpRequestBase theLastRequest) {
|
public void setLastRequest(HttpRequestBase theLastRequest) {
|
||||||
myLastRequest = theLastRequest;
|
myLastRequest = theLastRequest;
|
||||||
|
@ -252,15 +205,8 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
||||||
RuntimeResourceDefinition def = myContext.getResourceDefinition(theResource);
|
RuntimeResourceDefinition def = myContext.getResourceDefinition(theResource);
|
||||||
final String resourceName = def.getName();
|
final String resourceName = def.getName();
|
||||||
|
|
||||||
IClientResponseHandler binding = new IClientResponseHandler() {
|
OutcomeResponseHandler binding = new OutcomeResponseHandler(resourceName);
|
||||||
@Override
|
MethodOutcome resp = invokeClient(binding, invocation);
|
||||||
public Object invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) throws IOException, BaseServerResponseException {
|
|
||||||
MethodOutcome response = BaseOutcomeReturningMethodBinding.process2xxResponse(myContext, resourceName, theResponseStatusCode, theResponseMimeType, theResponseReader, theHeaders);
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
MethodOutcome resp = (MethodOutcome) invokeClient(binding, invocation);
|
|
||||||
return resp;
|
return resp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,15 +225,8 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
||||||
RuntimeResourceDefinition def = myContext.getResourceDefinition(theResource);
|
RuntimeResourceDefinition def = myContext.getResourceDefinition(theResource);
|
||||||
final String resourceName = def.getName();
|
final String resourceName = def.getName();
|
||||||
|
|
||||||
IClientResponseHandler binding = new IClientResponseHandler() {
|
OutcomeResponseHandler binding = new OutcomeResponseHandler(resourceName);
|
||||||
@Override
|
MethodOutcome resp = invokeClient(binding, invocation);
|
||||||
public Object invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) throws IOException, BaseServerResponseException {
|
|
||||||
MethodOutcome response = BaseOutcomeReturningMethodBinding.process2xxResponse(myContext, resourceName, theResponseStatusCode, theResponseMimeType, theResponseReader, theHeaders);
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
MethodOutcome resp = (MethodOutcome) invokeClient(binding, invocation);
|
|
||||||
return resp;
|
return resp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -298,17 +237,8 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
||||||
myLastRequest = invocation.asHttpRequest(getServerBase(), createExtraParams(), getEncoding());
|
myLastRequest = invocation.asHttpRequest(getServerBase(), createExtraParams(), getEncoding());
|
||||||
}
|
}
|
||||||
|
|
||||||
IClientResponseHandler binding = new IClientResponseHandler() {
|
ResourceResponseHandler<T> binding = new ResourceResponseHandler<T>(theType);
|
||||||
@Override
|
T resp = invokeClient(binding, invocation);
|
||||||
public Object invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) throws IOException, BaseServerResponseException {
|
|
||||||
EncodingEnum respType = EncodingEnum.forContentType(theResponseMimeType);
|
|
||||||
IParser parser = respType.newParser(myContext);
|
|
||||||
return parser.parseResource(theType, theResponseReader);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
T resp = (T) invokeClient(binding, invocation);
|
|
||||||
return resp;
|
return resp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -321,6 +251,57 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
||||||
return myContext.getResourceDefinition(theType).getName();
|
return myContext.getResourceDefinition(theType).getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final class OutcomeResponseHandler implements IClientResponseHandler<MethodOutcome> {
|
||||||
|
private final String myResourceName;
|
||||||
|
|
||||||
|
private OutcomeResponseHandler(String theResourceName) {
|
||||||
|
myResourceName = theResourceName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MethodOutcome invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) throws IOException,
|
||||||
|
BaseServerResponseException {
|
||||||
|
MethodOutcome response = BaseOutcomeReturningMethodBinding.process2xxResponse(myContext, myResourceName, theResponseStatusCode, theResponseMimeType, theResponseReader, theHeaders);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final class ResourceResponseHandler<T extends IResource> implements IClientResponseHandler<T> {
|
||||||
|
|
||||||
|
private Class<T> myType;
|
||||||
|
|
||||||
|
public ResourceResponseHandler(Class<T> theType) {
|
||||||
|
myType = theType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) throws IOException, BaseServerResponseException {
|
||||||
|
EncodingEnum respType = EncodingEnum.forContentType(theResponseMimeType);
|
||||||
|
IParser parser = respType.newParser(myContext);
|
||||||
|
return parser.parseResource(myType, theResponseReader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final class BundleResponseHandler implements IClientResponseHandler<Bundle> {
|
||||||
|
|
||||||
|
private Class<? extends IResource> myType;
|
||||||
|
|
||||||
|
public BundleResponseHandler(Class<? extends IResource> theType) {
|
||||||
|
myType = theType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Bundle invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) throws IOException,
|
||||||
|
BaseServerResponseException {
|
||||||
|
EncodingEnum respType = EncodingEnum.forContentType(theResponseMimeType);
|
||||||
|
if (respType == null) {
|
||||||
|
throw new NonFhirResponseException(theResponseStatusCode, "");
|
||||||
|
}
|
||||||
|
IParser parser = respType.newParser(myContext);
|
||||||
|
return parser.parseBundle(myType, theResponseReader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private class ForInternal implements IQuery {
|
private class ForInternal implements IQuery {
|
||||||
|
|
||||||
private List<ICriterionInternal> myCriterion = new ArrayList<ICriterionInternal>();
|
private List<ICriterionInternal> myCriterion = new ArrayList<ICriterionInternal>();
|
||||||
|
@ -403,16 +384,9 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
||||||
myLastRequest = invocation.asHttpRequest(getServerBase(), createExtraParams(), getEncoding());
|
myLastRequest = invocation.asHttpRequest(getServerBase(), createExtraParams(), getEncoding());
|
||||||
}
|
}
|
||||||
|
|
||||||
IClientResponseHandler binding = new IClientResponseHandler() {
|
BundleResponseHandler binding = new BundleResponseHandler(myResourceType);
|
||||||
@Override
|
|
||||||
public Object invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) throws IOException, BaseServerResponseException {
|
|
||||||
EncodingEnum respType = EncodingEnum.forContentType(theResponseMimeType);
|
|
||||||
IParser parser = respType.newParser(myContext);
|
|
||||||
return parser.parseBundle(myResourceType, theResponseReader);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Bundle resp = (Bundle) invokeClient(binding, invocation, myLogRequestAndResponse);
|
Bundle resp = invokeClient(binding, invocation, myLogRequestAndResponse);
|
||||||
return resp;
|
return resp;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,8 @@ import org.apache.http.protocol.HttpContext;
|
||||||
* HTTP interceptor to be used for adding HTTP basic auth username/password tokens
|
* HTTP interceptor to be used for adding HTTP basic auth username/password tokens
|
||||||
* to requests
|
* to requests
|
||||||
* <p>
|
* <p>
|
||||||
* See the
|
* See the <a href="http://hl7api.sourceforge.net/hapi-fhir/doc_rest_client.html#HTTP_Basic_Authorization">HAPI Documentation</a>
|
||||||
|
* for information on how to use this class.
|
||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
public class HttpBasicAuthInterceptor implements HttpRequestInterceptor {
|
public class HttpBasicAuthInterceptor implements HttpRequestInterceptor {
|
||||||
|
|
|
@ -52,7 +52,7 @@ import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
|
|
||||||
public abstract class BaseAddOrDeleteTagsMethodBinding extends BaseMethodBinding {
|
public abstract class BaseAddOrDeleteTagsMethodBinding extends BaseMethodBinding<Void> {
|
||||||
|
|
||||||
private Class<? extends IResource> myType;
|
private Class<? extends IResource> myType;
|
||||||
private Integer myIdParamIndex;
|
private Integer myIdParamIndex;
|
||||||
|
@ -89,7 +89,7 @@ public abstract class BaseAddOrDeleteTagsMethodBinding extends BaseMethodBinding
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) throws IOException, BaseServerResponseException {
|
public Void invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) throws IOException, BaseServerResponseException {
|
||||||
switch (theResponseStatusCode) {
|
switch (theResponseStatusCode) {
|
||||||
case Constants.STATUS_HTTP_200_OK:
|
case Constants.STATUS_HTTP_200_OK:
|
||||||
case Constants.STATUS_HTTP_201_CREATED:
|
case Constants.STATUS_HTTP_201_CREATED:
|
||||||
|
|
|
@ -78,7 +78,7 @@ import ca.uhn.fhir.rest.server.exceptions.UnclassifiedServerFailureException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||||
import ca.uhn.fhir.util.ReflectionUtil;
|
import ca.uhn.fhir.util.ReflectionUtil;
|
||||||
|
|
||||||
public abstract class BaseMethodBinding implements IClientResponseHandler {
|
public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T> {
|
||||||
|
|
||||||
private FhirContext myContext;
|
private FhirContext myContext;
|
||||||
private Method myMethod;
|
private Method myMethod;
|
||||||
|
@ -160,7 +160,7 @@ public abstract class BaseMethodBinding implements IClientResponseHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static BaseMethodBinding bindMethod(Method theMethod, FhirContext theContext, Object theProvider) {
|
public static BaseMethodBinding<?> bindMethod(Method theMethod, FhirContext theContext, Object theProvider) {
|
||||||
Read read = theMethod.getAnnotation(Read.class);
|
Read read = theMethod.getAnnotation(Read.class);
|
||||||
Search search = theMethod.getAnnotation(Search.class);
|
Search search = theMethod.getAnnotation(Search.class);
|
||||||
Metadata conformance = theMethod.getAnnotation(Metadata.class);
|
Metadata conformance = theMethod.getAnnotation(Metadata.class);
|
||||||
|
|
|
@ -55,7 +55,7 @@ import ca.uhn.fhir.rest.server.RestfulServer;
|
||||||
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;
|
||||||
|
|
||||||
public abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding {
|
public abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<MethodOutcome> {
|
||||||
private static final String LABEL = "label=\"";
|
private static final String LABEL = "label=\"";
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseOutcomeReturningMethodBinding.class);
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseOutcomeReturningMethodBinding.class);
|
||||||
private static final String SCHEME = "scheme=\"";
|
private static final String SCHEME = "scheme=\"";
|
||||||
|
@ -94,7 +94,7 @@ public abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBindin
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) throws IOException, BaseServerResponseException {
|
public MethodOutcome invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) throws IOException, BaseServerResponseException {
|
||||||
switch (theResponseStatusCode) {
|
switch (theResponseStatusCode) {
|
||||||
case Constants.STATUS_HTTP_200_OK:
|
case Constants.STATUS_HTTP_200_OK:
|
||||||
case Constants.STATUS_HTTP_201_CREATED:
|
case Constants.STATUS_HTTP_201_CREATED:
|
||||||
|
|
|
@ -65,7 +65,7 @@ import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||||
|
|
||||||
abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding {
|
abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding<Object> {
|
||||||
|
|
||||||
protected static final Set<String> ALLOWED_PARAMS;
|
protected static final Set<String> ALLOWED_PARAMS;
|
||||||
static {
|
static {
|
||||||
|
|
|
@ -51,7 +51,7 @@ import ca.uhn.fhir.rest.server.RestfulServer;
|
||||||
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;
|
||||||
|
|
||||||
public class GetTagsMethodBinding extends BaseMethodBinding {
|
public class GetTagsMethodBinding extends BaseMethodBinding<TagList> {
|
||||||
|
|
||||||
private Class<? extends IResource> myType;
|
private Class<? extends IResource> myType;
|
||||||
private Integer myIdParamIndex;
|
private Integer myIdParamIndex;
|
||||||
|
@ -80,7 +80,7 @@ public class GetTagsMethodBinding extends BaseMethodBinding {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) throws IOException, BaseServerResponseException {
|
public TagList invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) throws IOException, BaseServerResponseException {
|
||||||
if (theResponseStatusCode == Constants.STATUS_HTTP_200_OK) {
|
if (theResponseStatusCode == Constants.STATUS_HTTP_200_OK) {
|
||||||
IParser parser = createAppropriateParserForParsingResponse(theResponseMimeType, theResponseReader, theResponseStatusCode);
|
IParser parser = createAppropriateParserForParsingResponse(theResponseMimeType, theResponseReader, theResponseStatusCode);
|
||||||
TagList retVal = parser.parseTagList(theResponseReader);
|
TagList retVal = parser.parseTagList(theResponseReader);
|
||||||
|
|
|
@ -27,8 +27,8 @@ import java.util.Map;
|
||||||
|
|
||||||
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
||||||
|
|
||||||
public interface IClientResponseHandler {
|
public interface IClientResponseHandler<T> {
|
||||||
|
|
||||||
Object invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) throws IOException, BaseServerResponseException;
|
T invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) throws IOException, BaseServerResponseException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@ import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.servlet.ServletConfig;
|
import javax.servlet.ServletConfig;
|
||||||
import javax.servlet.ServletException;
|
import javax.servlet.ServletException;
|
||||||
|
@ -39,6 +40,7 @@ import org.apache.commons.io.IOUtils;
|
||||||
import org.apache.commons.io.output.WriterOutputStream;
|
import org.apache.commons.io.output.WriterOutputStream;
|
||||||
import org.apache.commons.lang3.StringEscapeUtils;
|
import org.apache.commons.lang3.StringEscapeUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.http.Header;
|
||||||
import org.apache.http.HttpEntity;
|
import org.apache.http.HttpEntity;
|
||||||
import org.apache.http.HttpEntityEnclosingRequest;
|
import org.apache.http.HttpEntityEnclosingRequest;
|
||||||
import org.apache.http.HttpResponse;
|
import org.apache.http.HttpResponse;
|
||||||
|
@ -66,10 +68,10 @@ import ca.uhn.fhir.rest.server.Constants;
|
||||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
||||||
|
|
||||||
public class PublicTesterServlet extends HttpServlet {
|
public class RestfulServerTesterServlet extends HttpServlet {
|
||||||
|
|
||||||
private static final boolean DEBUGMODE = true;
|
private static final boolean DEBUGMODE = true;
|
||||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(PublicTesterServlet.class);
|
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(RestfulServerTesterServlet.class);
|
||||||
private static final String PUBLIC_TESTER_RESULT_HTML = "/PublicTesterResult.html";
|
private static final String PUBLIC_TESTER_RESULT_HTML = "/PublicTesterResult.html";
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
private FhirContext myCtx;
|
private FhirContext myCtx;
|
||||||
|
@ -77,8 +79,9 @@ public class PublicTesterServlet extends HttpServlet {
|
||||||
private HashMap<String, String> myStaticResources;
|
private HashMap<String, String> myStaticResources;
|
||||||
|
|
||||||
private TemplateEngine myTemplateEngine;
|
private TemplateEngine myTemplateEngine;
|
||||||
|
private Set<String> myFilterHeaders;
|
||||||
|
|
||||||
public PublicTesterServlet() {
|
public RestfulServerTesterServlet() {
|
||||||
myStaticResources = new HashMap<String, String>();
|
myStaticResources = new HashMap<String, String>();
|
||||||
myStaticResources.put("jquery-2.1.0.min.js", "text/javascript");
|
myStaticResources.put("jquery-2.1.0.min.js", "text/javascript");
|
||||||
myStaticResources.put("PublicTester.js", "text/javascript");
|
myStaticResources.put("PublicTester.js", "text/javascript");
|
||||||
|
@ -95,6 +98,10 @@ public class PublicTesterServlet extends HttpServlet {
|
||||||
myCtx = new FhirContext();
|
myCtx = new FhirContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public FhirContext getFhirContext() {
|
||||||
|
return myCtx;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(ServletConfig theConfig) throws ServletException {
|
public void init(ServletConfig theConfig) throws ServletException {
|
||||||
myTemplateEngine = new TemplateEngine();
|
myTemplateEngine = new TemplateEngine();
|
||||||
|
@ -120,7 +127,7 @@ public class PublicTesterServlet extends HttpServlet {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void streamResponse(String theResourceName, String theContentType, HttpServletResponse theResp) throws IOException {
|
private void streamResponse(String theResourceName, String theContentType, HttpServletResponse theResp) throws IOException {
|
||||||
InputStream res = PublicTesterServlet.class.getResourceAsStream("/ca/uhn/fhir/rest/server/tester/" + theResourceName);
|
InputStream res = RestfulServerTesterServlet.class.getResourceAsStream("/ca/uhn/fhir/rest/server/tester/" + theResourceName);
|
||||||
theResp.setContentType(theContentType);
|
theResp.setContentType(theContentType);
|
||||||
IOUtils.copy(res, theResp.getOutputStream());
|
IOUtils.copy(res, theResp.getOutputStream());
|
||||||
}
|
}
|
||||||
|
@ -401,6 +408,9 @@ public class PublicTesterServlet extends HttpServlet {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Header[] requestHeaders = applyHeaderFilters(lastRequest.getAllHeaders());
|
||||||
|
Header[] responseHeaders = applyHeaderFilters(lastResponse.getAllHeaders());
|
||||||
|
|
||||||
WebContext ctx = new WebContext(theReq, theResp, theReq.getServletContext(), theReq.getLocale());
|
WebContext ctx = new WebContext(theReq, theResp, theReq.getServletContext(), theReq.getLocale());
|
||||||
ctx.setVariable("base", myServerBase);
|
ctx.setVariable("base", myServerBase);
|
||||||
ctx.setVariable("requestUrl", requestUrl);
|
ctx.setVariable("requestUrl", requestUrl);
|
||||||
|
@ -410,8 +420,8 @@ public class PublicTesterServlet extends HttpServlet {
|
||||||
ctx.setVariable("requestSyntaxHighlighterClass", requestSyntaxHighlighterClass);
|
ctx.setVariable("requestSyntaxHighlighterClass", requestSyntaxHighlighterClass);
|
||||||
ctx.setVariable("resultBody", StringEscapeUtils.escapeHtml4(resultBody));
|
ctx.setVariable("resultBody", StringEscapeUtils.escapeHtml4(resultBody));
|
||||||
ctx.setVariable("resultSyntaxHighlighterClass", resultSyntaxHighlighterClass);
|
ctx.setVariable("resultSyntaxHighlighterClass", resultSyntaxHighlighterClass);
|
||||||
ctx.setVariable("requestHeaders", lastRequest.getAllHeaders());
|
ctx.setVariable("requestHeaders", requestHeaders);
|
||||||
ctx.setVariable("responseHeaders", lastResponse.getAllHeaders());
|
ctx.setVariable("responseHeaders", responseHeaders);
|
||||||
ctx.setVariable("narrative", narrativeString);
|
ctx.setVariable("narrative", narrativeString);
|
||||||
|
|
||||||
myTemplateEngine.process(PUBLIC_TESTER_RESULT_HTML, ctx, theResp.getWriter());
|
myTemplateEngine.process(PUBLIC_TESTER_RESULT_HTML, ctx, theResp.getWriter());
|
||||||
|
@ -421,6 +431,32 @@ public class PublicTesterServlet extends HttpServlet {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Header[] applyHeaderFilters(Header[] theAllHeaders) {
|
||||||
|
if (myFilterHeaders == null || myFilterHeaders.isEmpty()) {
|
||||||
|
return theAllHeaders;
|
||||||
|
}
|
||||||
|
ArrayList<Header> retVal = new ArrayList<Header>();
|
||||||
|
for (Header next : theAllHeaders) {
|
||||||
|
if (!myFilterHeaders.contains(next.getName().toLowerCase())) {
|
||||||
|
retVal.add(next);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return retVal.toArray(new Header[retVal.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If set, the headers named here will be stripped from requests/responses before they are displayed to the user. This can be used, for instance, to filter out "Authorization" headers. Note that
|
||||||
|
* names are not case sensitive.
|
||||||
|
*/
|
||||||
|
public void setFilterHeaders(String... theHeaderNames) {
|
||||||
|
myFilterHeaders = new HashSet<String>();
|
||||||
|
if (theHeaderNames != null) {
|
||||||
|
for (String next : theHeaderNames) {
|
||||||
|
myFilterHeaders.add(next.toLowerCase());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private String parseNarrative(EncodingEnum theCtEnum, String theResultBody) {
|
private String parseNarrative(EncodingEnum theCtEnum, String theResultBody) {
|
||||||
try {
|
try {
|
||||||
IResource resource = theCtEnum.newParser(myCtx).parseResource(theResultBody);
|
IResource resource = theCtEnum.newParser(myCtx).parseResource(theResultBody);
|
||||||
|
@ -448,10 +484,10 @@ public class PublicTesterServlet extends HttpServlet {
|
||||||
public InputStream getResourceAsStream(TemplateProcessingParameters theTemplateProcessingParameters, String theName) {
|
public InputStream getResourceAsStream(TemplateProcessingParameters theTemplateProcessingParameters, String theName) {
|
||||||
ourLog.debug("Loading template: {}", theName);
|
ourLog.debug("Loading template: {}", theName);
|
||||||
if ("/".equals(theName)) {
|
if ("/".equals(theName)) {
|
||||||
return PublicTesterServlet.class.getResourceAsStream("/ca/uhn/fhir/rest/server/tester/PublicTester.html");
|
return RestfulServerTesterServlet.class.getResourceAsStream("/ca/uhn/fhir/rest/server/tester/PublicTester.html");
|
||||||
}
|
}
|
||||||
if (PUBLIC_TESTER_RESULT_HTML.equals(theName)) {
|
if (PUBLIC_TESTER_RESULT_HTML.equals(theName)) {
|
||||||
return PublicTesterServlet.class.getResourceAsStream("/ca/uhn/fhir/rest/server/tester/PublicTesterResult.html");
|
return RestfulServerTesterServlet.class.getResourceAsStream("/ca/uhn/fhir/rest/server/tester/PublicTesterResult.html");
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
|
@ -51,6 +51,15 @@ import ca.uhn.fhir.narrative.INarrativeGenerator;
|
||||||
public class JsonParserTest {
|
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);
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEncodingNullExtension() {
|
||||||
|
Patient p = new Patient();
|
||||||
|
p.addUndeclaredExtension(new ExtensionDt(false, "http://foo#bar"));
|
||||||
|
String str = new FhirContext().newJsonParser().encodeResourceToString(p);
|
||||||
|
|
||||||
|
assertEquals("{\"resourceType\":\"Patient\",\"extension\":[{\"url\":\"http://foo#bar\"}]}", str);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTagList() {
|
public void testTagList() {
|
||||||
|
|
||||||
|
|
|
@ -61,6 +61,7 @@ import ca.uhn.fhir.rest.param.DateRangeParam;
|
||||||
import ca.uhn.fhir.rest.param.QualifiedDateParam;
|
import ca.uhn.fhir.rest.param.QualifiedDateParam;
|
||||||
import ca.uhn.fhir.rest.server.Constants;
|
import ca.uhn.fhir.rest.server.Constants;
|
||||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException;
|
import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException;
|
||||||
|
@ -585,6 +586,30 @@ public class ClientTest {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReadFailureInternalError() throws Exception {
|
||||||
|
|
||||||
|
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), 500, "INTERNAL"));
|
||||||
|
Header[] headers = new Header[1];
|
||||||
|
headers[0] = new BasicHeader(Constants.HEADER_LAST_MODIFIED, "2011-01-02T22:01:02");
|
||||||
|
when(httpResponse.getAllHeaders()).thenReturn(headers);
|
||||||
|
when(httpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_TEXT));
|
||||||
|
when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader("Internal Failure"), Charset.forName("UTF-8")));
|
||||||
|
|
||||||
|
ITestClient client = ctx.newRestfulClient(ITestClient.class, "http://foo");
|
||||||
|
try {
|
||||||
|
client.getPatientById(new IdDt("111"));
|
||||||
|
fail();
|
||||||
|
} catch (InternalErrorException e) {
|
||||||
|
assertThat(e.getMessage(), containsString("INTERNAL"));
|
||||||
|
assertThat(e.getResponseBody(), containsString("Internal Failure"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReadNoCharset() throws Exception {
|
public void testReadNoCharset() throws Exception {
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
package ca.uhn.fhir.rest.client;
|
package ca.uhn.fhir.rest.client;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.mockito.Mockito.*;
|
import static org.junit.Assert.assertThat;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
|
@ -13,6 +16,7 @@ import org.apache.http.client.HttpClient;
|
||||||
import org.apache.http.client.methods.HttpUriRequest;
|
import org.apache.http.client.methods.HttpUriRequest;
|
||||||
import org.apache.http.message.BasicHeader;
|
import org.apache.http.message.BasicHeader;
|
||||||
import org.apache.http.message.BasicStatusLine;
|
import org.apache.http.message.BasicStatusLine;
|
||||||
|
import org.hamcrest.core.StringContains;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.mockito.ArgumentCaptor;
|
import org.mockito.ArgumentCaptor;
|
||||||
|
@ -24,7 +28,9 @@ import ca.uhn.fhir.model.dstu.resource.Encounter;
|
||||||
import ca.uhn.fhir.model.dstu.resource.Observation;
|
import ca.uhn.fhir.model.dstu.resource.Observation;
|
||||||
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.rest.client.exceptions.NonFhirResponseException;
|
||||||
import ca.uhn.fhir.rest.server.Constants;
|
import ca.uhn.fhir.rest.server.Constants;
|
||||||
|
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||||
|
|
||||||
public class GenericClientTest {
|
public class GenericClientTest {
|
||||||
|
|
||||||
|
@ -278,4 +284,52 @@ public class GenericClientTest {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
@Test
|
||||||
|
public void testSearchWithInternalServerError() throws Exception {
|
||||||
|
|
||||||
|
String msg = getPatientFeedWithOneResult();
|
||||||
|
|
||||||
|
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||||
|
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||||
|
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 500, "OK"));
|
||||||
|
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_TEXT + "; charset=UTF-8"));
|
||||||
|
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader("Server Issues!"), Charset.forName("UTF-8")));
|
||||||
|
|
||||||
|
IGenericClient client = myCtx.newRestfulGenericClient("http://example.com/fhir");
|
||||||
|
|
||||||
|
try {
|
||||||
|
client.search().forResource(Patient.class).execute();
|
||||||
|
fail();
|
||||||
|
} catch (InternalErrorException e) {
|
||||||
|
assertThat(e.getMessage(), StringContains.containsString("AAA"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
@Test
|
||||||
|
public void testSearchWithNonFhirResponse() throws Exception {
|
||||||
|
|
||||||
|
String msg = getPatientFeedWithOneResult();
|
||||||
|
|
||||||
|
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||||
|
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||||
|
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
|
||||||
|
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_TEXT + "; charset=UTF-8"));
|
||||||
|
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader("Server Issues!"), Charset.forName("UTF-8")));
|
||||||
|
|
||||||
|
IGenericClient client = myCtx.newRestfulGenericClient("http://example.com/fhir");
|
||||||
|
|
||||||
|
try {
|
||||||
|
client.search().forResource(Patient.class).execute();
|
||||||
|
fail();
|
||||||
|
} catch (NonFhirResponseException e) {
|
||||||
|
assertThat(e.getMessage(), StringContains.containsString("AAA"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ import ca.uhn.fhir.rest.annotation.Update;
|
||||||
import ca.uhn.fhir.rest.annotation.Validate;
|
import ca.uhn.fhir.rest.annotation.Validate;
|
||||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||||
import ca.uhn.fhir.rest.server.tester.PublicTesterServlet;
|
import ca.uhn.fhir.rest.server.tester.RestfulServerTesterServlet;
|
||||||
import ca.uhn.fhir.testutil.RandomServerPortProvider;
|
import ca.uhn.fhir.testutil.RandomServerPortProvider;
|
||||||
|
|
||||||
public class TesterTest {
|
public class TesterTest {
|
||||||
|
@ -62,7 +62,7 @@ public class TesterTest {
|
||||||
ServletContextHandler proxyHandler = new ServletContextHandler();
|
ServletContextHandler proxyHandler = new ServletContextHandler();
|
||||||
proxyHandler.setContextPath("/");
|
proxyHandler.setContextPath("/");
|
||||||
|
|
||||||
PublicTesterServlet testerServlet = new PublicTesterServlet();
|
RestfulServerTesterServlet testerServlet = new RestfulServerTesterServlet();
|
||||||
testerServlet.setServerBase("http://localhost:" + myPort + "/fhir/context");
|
testerServlet.setServerBase("http://localhost:" + myPort + "/fhir/context");
|
||||||
// testerServlet.setServerBase("http://fhir.healthintersections.com.au/open");
|
// testerServlet.setServerBase("http://fhir.healthintersections.com.au/open");
|
||||||
ServletHolder handler = new ServletHolder();
|
ServletHolder handler = new ServletHolder();
|
||||||
|
|
Loading…
Reference in New Issue