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%
|
||||
*/
|
||||
|
||||
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.Reader;
|
||||
|
@ -45,13 +47,10 @@ import javax.json.JsonValue;
|
|||
import javax.json.JsonValue.ValueType;
|
||||
import javax.json.stream.JsonGenerator;
|
||||
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.Validate;
|
||||
|
||||
import ch.qos.logback.core.boolex.EventEvaluator;
|
||||
import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
|
||||
import ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition;
|
||||
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.model.api.BaseBundle;
|
||||
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.ExtensionDt;
|
||||
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.IResource;
|
||||
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.annotation.Child;
|
||||
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 {
|
||||
|
||||
private static final Set<String> BUNDLE_TEXTNODE_CHILDREN;
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(JsonParser.HeldExtension.class);
|
||||
|
||||
static {
|
||||
HashSet<String> hashSet = new HashSet<String>();
|
||||
hashSet.add("title");
|
||||
|
@ -105,6 +106,48 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
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 void encodeBundleToWriter(Bundle theBundle, Writer theWriter) throws IOException {
|
||||
JsonGenerator eventWriter = createJsonGenerator(theWriter);
|
||||
|
@ -170,173 +213,8 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
eventWriter.close();
|
||||
}
|
||||
|
||||
@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();
|
||||
}
|
||||
|
||||
@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 {
|
||||
private void encodeChildElementToStreamWriter(RuntimeResourceDefinition theResDef, IResource theResource, JsonGenerator theWriter, IElement theValue, BaseRuntimeElementDefinition<?> theChildDef,
|
||||
String theChildName) throws IOException {
|
||||
|
||||
switch (theChildDef.getChildType()) {
|
||||
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) {
|
||||
if (nextChild instanceof RuntimeChildNarrativeDefinition) {
|
||||
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.getChildren());
|
||||
}
|
||||
|
@ -598,12 +478,52 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
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
|
||||
* direct children (e.g. not in some object called _name): resource
|
||||
* extensions, and extension extensions
|
||||
* This is useful only for the two cases where extensions are encoded as direct children (e.g. not in some object called _name): resource extensions, and extension extensions
|
||||
*/
|
||||
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> 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) {
|
||||
for (String nextName : theObject.keySet()) {
|
||||
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) {
|
||||
if (isNotBlank(theLink.getValue())) {
|
||||
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) {
|
||||
theEventWriter.writeStartArray("extension");
|
||||
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 {
|
||||
IElement value = ext.getValue();
|
||||
|
||||
theEventWriter.writeStartObject();
|
||||
theEventWriter.write("url", ext.getUrl().getValue());
|
||||
|
||||
IElement value = ext.getValue();
|
||||
if (value == null && ext.getAllUndeclaredExtensions().isEmpty()) {
|
||||
theEventWriter.writeNull();
|
||||
ourLog.debug("Extension with URL[{}] has no value", ext.getUrl().getValue());
|
||||
} else if (value == null) {
|
||||
theEventWriter.writeStartArray("extension");
|
||||
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;
|
||||
|
||||
/**
|
||||
* 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 FHIR
|
||||
* specification)
|
||||
* 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
|
||||
* FHIR specification)
|
||||
*/
|
||||
public EncodingEnum getEncoding() {
|
||||
return myEncoding;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* 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
|
||||
* specification)
|
||||
*/
|
||||
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
|
||||
* this method may change!
|
||||
* For now, this is a part of the internal API of HAPI - Use with caution as this method may change!
|
||||
*/
|
||||
public HttpResponse getLastResponse() {
|
||||
return myLastResponse;
|
||||
}
|
||||
|
||||
/**
|
||||
* For now, this is a part of the internal API of HAPI - Use with caution as
|
||||
* this method may change!
|
||||
* For now, this is a part of the internal API of HAPI - Use with caution as this method may change!
|
||||
*/
|
||||
public String getLastResponseBody() {
|
||||
return myLastResponseBody;
|
||||
|
@ -106,11 +100,11 @@ public abstract class BaseClient {
|
|||
return myUrlBase;
|
||||
}
|
||||
|
||||
Object invokeClient(IClientResponseHandler binding, BaseClientInvocation clientInvocation) {
|
||||
<T> T invokeClient(IClientResponseHandler<T> binding, BaseClientInvocation clientInvocation) {
|
||||
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,
|
||||
// and ensure it's passed upwards
|
||||
HttpRequestBase httpRequest;
|
||||
|
@ -160,13 +154,24 @@ public abstract class BaseClient {
|
|||
}
|
||||
|
||||
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 {
|
||||
return binding.invokeClient(mimeType, reader, response.getStatusLine().getStatusCode(), headers);
|
||||
} finally {
|
||||
reader.close();
|
||||
IOUtils.closeQuietly(reader);
|
||||
}
|
||||
|
||||
} 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
|
||||
* this method may change!
|
||||
* For now, this is a part of the internal API of HAPI - Use with caution as this method may change!
|
||||
*/
|
||||
public boolean isKeepResponses() {
|
||||
return myKeepResponses;
|
||||
}
|
||||
|
||||
/**
|
||||
* For now, this is a part of the internal API of HAPI - Use with caution as
|
||||
* this method may change!
|
||||
* For now, this is a part of the internal API of HAPI - Use with caution as this method may change!
|
||||
*/
|
||||
public void setKeepResponses(boolean theKeepResponses) {
|
||||
myKeepResponses = theKeepResponses;
|
||||
}
|
||||
|
||||
/**
|
||||
* For now, this is a part of the internal API of HAPI - Use with caution as
|
||||
* this method may change!
|
||||
* For now, this is a part of the internal API of HAPI - Use with caution as this method may change!
|
||||
*/
|
||||
public void setLastResponse(HttpResponse theLastResponse) {
|
||||
myLastResponse = theLastResponse;
|
||||
}
|
||||
|
||||
/**
|
||||
* For now, this is a part of the internal API of HAPI - Use with caution as
|
||||
* this method may change!
|
||||
* For now, this is a part of the internal API of HAPI - Use with caution as this method may change!
|
||||
*/
|
||||
public void setLastResponseBody(String 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
|
||||
* return "pretty printed" responses. Note that this is currently a
|
||||
* non-standard flag (_pretty) which is supported only by HAPI based servers
|
||||
* (and any other servers which might implement it).
|
||||
* 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
|
||||
* HAPI based servers (and any other servers which might implement it).
|
||||
*/
|
||||
public boolean isPrettyPrint() {
|
||||
return myPrettyPrint;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 HAPI based servers
|
||||
* (and any other servers which might implement it).
|
||||
* 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
|
||||
* HAPI based servers (and any other servers which might implement it).
|
||||
*/
|
||||
public BaseClient setPrettyPrint(boolean thePrettyPrint) {
|
||||
myPrettyPrint = thePrettyPrint;
|
||||
|
|
|
@ -35,7 +35,7 @@ import ca.uhn.fhir.rest.server.EncodingEnum;
|
|||
|
||||
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>();
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -70,7 +70,7 @@ public class ClientInvocationHandler extends BaseClient implements InvocationHan
|
|||
return directRetVal;
|
||||
}
|
||||
|
||||
BaseMethodBinding binding = myBindings.get(theMethod);
|
||||
BaseMethodBinding<?> binding = myBindings.get(theMethod);
|
||||
if (binding != null) {
|
||||
BaseClientInvocation clientInvocation = binding.invokeClient(theArgs);
|
||||
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.parser.IParser;
|
||||
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.ICriterionInternal;
|
||||
import ca.uhn.fhir.rest.gclient.IQuery;
|
||||
|
@ -68,8 +69,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
private HttpRequestBase myLastRequest;
|
||||
|
||||
/**
|
||||
* For now, this is a part of the internal API of HAPI - Use with caution as
|
||||
* this method may change!
|
||||
* For now, this is a part of the internal API of HAPI - Use with caution as this method may change!
|
||||
*/
|
||||
public GenericClient(FhirContext theContext, HttpClient theHttpClient, String theServerBase) {
|
||||
super(theHttpClient, theServerBase);
|
||||
|
@ -83,16 +83,8 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
myLastRequest = invocation.asHttpRequest(getServerBase(), createExtraParams(), getEncoding());
|
||||
}
|
||||
|
||||
IClientResponseHandler binding = new IClientResponseHandler() {
|
||||
@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.parseResource(Conformance.class, theResponseReader);
|
||||
}
|
||||
};
|
||||
|
||||
Conformance resp = (Conformance) invokeClient(binding, invocation);
|
||||
ResourceResponseHandler<Conformance> binding = new ResourceResponseHandler<Conformance>(Conformance.class);
|
||||
Conformance resp = invokeClient(binding, invocation);
|
||||
return resp;
|
||||
}
|
||||
|
||||
|
@ -106,15 +98,9 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
RuntimeResourceDefinition def = myContext.getResourceDefinition(theResource);
|
||||
final String resourceName = def.getName();
|
||||
|
||||
IClientResponseHandler binding = new IClientResponseHandler() {
|
||||
@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;
|
||||
}
|
||||
};
|
||||
OutcomeResponseHandler binding = new OutcomeResponseHandler(resourceName);
|
||||
|
||||
MethodOutcome resp = (MethodOutcome) invokeClient(binding, invocation);
|
||||
MethodOutcome resp = invokeClient(binding, invocation);
|
||||
return resp;
|
||||
|
||||
}
|
||||
|
@ -127,15 +113,8 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
}
|
||||
|
||||
final String resourceName = myContext.getResourceDefinition(theType).getName();
|
||||
IClientResponseHandler binding = new IClientResponseHandler() {
|
||||
@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);
|
||||
OutcomeResponseHandler binding = new OutcomeResponseHandler(resourceName);
|
||||
MethodOutcome resp = invokeClient(binding, invocation);
|
||||
return resp;
|
||||
}
|
||||
|
||||
|
@ -155,16 +134,8 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
myLastRequest = invocation.asHttpRequest(getServerBase(), createExtraParams(), getEncoding());
|
||||
}
|
||||
|
||||
IClientResponseHandler binding = new IClientResponseHandler() {
|
||||
@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(theType, theResponseReader);
|
||||
}
|
||||
};
|
||||
|
||||
Bundle resp = (Bundle) invokeClient(binding, invocation);
|
||||
BundleResponseHandler binding = new BundleResponseHandler(theType);
|
||||
Bundle resp = invokeClient(binding, invocation);
|
||||
return resp;
|
||||
|
||||
}
|
||||
|
@ -181,17 +152,8 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
myLastRequest = invocation.asHttpRequest(getServerBase(), createExtraParams(), getEncoding());
|
||||
}
|
||||
|
||||
IClientResponseHandler binding = new IClientResponseHandler() {
|
||||
@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.parseResource(theType, theResponseReader);
|
||||
}
|
||||
};
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
T resp = (T) invokeClient(binding, invocation);
|
||||
ResourceResponseHandler<T> binding = new ResourceResponseHandler<T>(theType);
|
||||
T resp = invokeClient(binding, invocation);
|
||||
return resp;
|
||||
}
|
||||
|
||||
|
@ -221,22 +183,13 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
myLastRequest = invocation.asHttpRequest(getServerBase(), createExtraParams(), getEncoding());
|
||||
}
|
||||
|
||||
IClientResponseHandler binding = new IClientResponseHandler() {
|
||||
@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(theType, theResponseReader);
|
||||
}
|
||||
};
|
||||
|
||||
Bundle resp = (Bundle) invokeClient(binding, invocation);
|
||||
BundleResponseHandler binding = new BundleResponseHandler(theType);
|
||||
Bundle resp = invokeClient(binding, invocation);
|
||||
return resp;
|
||||
}
|
||||
|
||||
/**
|
||||
* For now, this is a part of the internal API of HAPI - Use with caution as
|
||||
* this method may change!
|
||||
* For now, this is a part of the internal API of HAPI - Use with caution as this method may change!
|
||||
*/
|
||||
public void setLastRequest(HttpRequestBase theLastRequest) {
|
||||
myLastRequest = theLastRequest;
|
||||
|
@ -252,15 +205,8 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
RuntimeResourceDefinition def = myContext.getResourceDefinition(theResource);
|
||||
final String resourceName = def.getName();
|
||||
|
||||
IClientResponseHandler binding = new IClientResponseHandler() {
|
||||
@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);
|
||||
OutcomeResponseHandler binding = new OutcomeResponseHandler(resourceName);
|
||||
MethodOutcome resp = invokeClient(binding, invocation);
|
||||
return resp;
|
||||
}
|
||||
|
||||
|
@ -279,15 +225,8 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
RuntimeResourceDefinition def = myContext.getResourceDefinition(theResource);
|
||||
final String resourceName = def.getName();
|
||||
|
||||
IClientResponseHandler binding = new IClientResponseHandler() {
|
||||
@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);
|
||||
OutcomeResponseHandler binding = new OutcomeResponseHandler(resourceName);
|
||||
MethodOutcome resp = invokeClient(binding, invocation);
|
||||
return resp;
|
||||
}
|
||||
|
||||
|
@ -298,17 +237,8 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
myLastRequest = invocation.asHttpRequest(getServerBase(), createExtraParams(), getEncoding());
|
||||
}
|
||||
|
||||
IClientResponseHandler binding = new IClientResponseHandler() {
|
||||
@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.parseResource(theType, theResponseReader);
|
||||
}
|
||||
};
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
T resp = (T) invokeClient(binding, invocation);
|
||||
ResourceResponseHandler<T> binding = new ResourceResponseHandler<T>(theType);
|
||||
T resp = invokeClient(binding, invocation);
|
||||
return resp;
|
||||
}
|
||||
|
||||
|
@ -321,6 +251,57 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
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 List<ICriterionInternal> myCriterion = new ArrayList<ICriterionInternal>();
|
||||
|
@ -403,16 +384,9 @@ public class GenericClient extends BaseClient implements IGenericClient {
|
|||
myLastRequest = invocation.asHttpRequest(getServerBase(), createExtraParams(), getEncoding());
|
||||
}
|
||||
|
||||
IClientResponseHandler binding = new IClientResponseHandler() {
|
||||
@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);
|
||||
}
|
||||
};
|
||||
BundleResponseHandler binding = new BundleResponseHandler(myResourceType);
|
||||
|
||||
Bundle resp = (Bundle) invokeClient(binding, invocation, myLogRequestAndResponse);
|
||||
Bundle resp = invokeClient(binding, invocation, myLogRequestAndResponse);
|
||||
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
|
||||
* to requests
|
||||
* <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>
|
||||
*/
|
||||
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.InvalidRequestException;
|
||||
|
||||
public abstract class BaseAddOrDeleteTagsMethodBinding extends BaseMethodBinding {
|
||||
public abstract class BaseAddOrDeleteTagsMethodBinding extends BaseMethodBinding<Void> {
|
||||
|
||||
private Class<? extends IResource> myType;
|
||||
private Integer myIdParamIndex;
|
||||
|
@ -89,7 +89,7 @@ public abstract class BaseAddOrDeleteTagsMethodBinding extends BaseMethodBinding
|
|||
}
|
||||
|
||||
@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) {
|
||||
case Constants.STATUS_HTTP_200_OK:
|
||||
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.util.ReflectionUtil;
|
||||
|
||||
public abstract class BaseMethodBinding implements IClientResponseHandler {
|
||||
public abstract class BaseMethodBinding<T> implements IClientResponseHandler<T> {
|
||||
|
||||
private FhirContext myContext;
|
||||
private Method myMethod;
|
||||
|
@ -160,7 +160,7 @@ public abstract class BaseMethodBinding implements IClientResponseHandler {
|
|||
}
|
||||
|
||||
@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);
|
||||
Search search = theMethod.getAnnotation(Search.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.InternalErrorException;
|
||||
|
||||
public abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding {
|
||||
public abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<MethodOutcome> {
|
||||
private static final String LABEL = "label=\"";
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseOutcomeReturningMethodBinding.class);
|
||||
private static final String SCHEME = "scheme=\"";
|
||||
|
@ -94,7 +94,7 @@ public abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBindin
|
|||
}
|
||||
|
||||
@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) {
|
||||
case Constants.STATUS_HTTP_200_OK:
|
||||
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.ResourceNotFoundException;
|
||||
|
||||
abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding {
|
||||
abstract class BaseResourceReturningMethodBinding extends BaseMethodBinding<Object> {
|
||||
|
||||
protected static final Set<String> ALLOWED_PARAMS;
|
||||
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.InternalErrorException;
|
||||
|
||||
public class GetTagsMethodBinding extends BaseMethodBinding {
|
||||
public class GetTagsMethodBinding extends BaseMethodBinding<TagList> {
|
||||
|
||||
private Class<? extends IResource> myType;
|
||||
private Integer myIdParamIndex;
|
||||
|
@ -80,7 +80,7 @@ public class GetTagsMethodBinding extends BaseMethodBinding {
|
|||
}
|
||||
|
||||
@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) {
|
||||
IParser parser = createAppropriateParserForParsingResponse(theResponseMimeType, theResponseReader, theResponseStatusCode);
|
||||
TagList retVal = parser.parseTagList(theResponseReader);
|
||||
|
|
|
@ -27,8 +27,8 @@ import java.util.Map;
|
|||
|
||||
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.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.ServletConfig;
|
||||
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.lang3.StringEscapeUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.http.Header;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpEntityEnclosingRequest;
|
||||
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.exceptions.BaseServerResponseException;
|
||||
|
||||
public class PublicTesterServlet extends HttpServlet {
|
||||
public class RestfulServerTesterServlet extends HttpServlet {
|
||||
|
||||
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 long serialVersionUID = 1L;
|
||||
private FhirContext myCtx;
|
||||
|
@ -77,8 +79,9 @@ public class PublicTesterServlet extends HttpServlet {
|
|||
private HashMap<String, String> myStaticResources;
|
||||
|
||||
private TemplateEngine myTemplateEngine;
|
||||
private Set<String> myFilterHeaders;
|
||||
|
||||
public PublicTesterServlet() {
|
||||
public RestfulServerTesterServlet() {
|
||||
myStaticResources = new HashMap<String, String>();
|
||||
myStaticResources.put("jquery-2.1.0.min.js", "text/javascript");
|
||||
myStaticResources.put("PublicTester.js", "text/javascript");
|
||||
|
@ -95,6 +98,10 @@ public class PublicTesterServlet extends HttpServlet {
|
|||
myCtx = new FhirContext();
|
||||
}
|
||||
|
||||
public FhirContext getFhirContext() {
|
||||
return myCtx;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(ServletConfig theConfig) throws ServletException {
|
||||
myTemplateEngine = new TemplateEngine();
|
||||
|
@ -120,7 +127,7 @@ public class PublicTesterServlet extends HttpServlet {
|
|||
}
|
||||
|
||||
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);
|
||||
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());
|
||||
ctx.setVariable("base", myServerBase);
|
||||
ctx.setVariable("requestUrl", requestUrl);
|
||||
|
@ -410,8 +420,8 @@ public class PublicTesterServlet extends HttpServlet {
|
|||
ctx.setVariable("requestSyntaxHighlighterClass", requestSyntaxHighlighterClass);
|
||||
ctx.setVariable("resultBody", StringEscapeUtils.escapeHtml4(resultBody));
|
||||
ctx.setVariable("resultSyntaxHighlighterClass", resultSyntaxHighlighterClass);
|
||||
ctx.setVariable("requestHeaders", lastRequest.getAllHeaders());
|
||||
ctx.setVariable("responseHeaders", lastResponse.getAllHeaders());
|
||||
ctx.setVariable("requestHeaders", requestHeaders);
|
||||
ctx.setVariable("responseHeaders", responseHeaders);
|
||||
ctx.setVariable("narrative", narrativeString);
|
||||
|
||||
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) {
|
||||
try {
|
||||
IResource resource = theCtEnum.newParser(myCtx).parseResource(theResultBody);
|
||||
|
@ -448,10 +484,10 @@ public class PublicTesterServlet extends HttpServlet {
|
|||
public InputStream getResourceAsStream(TemplateProcessingParameters theTemplateProcessingParameters, String theName) {
|
||||
ourLog.debug("Loading template: {}", 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)) {
|
||||
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;
|
|
@ -51,6 +51,15 @@ import ca.uhn.fhir.narrative.INarrativeGenerator;
|
|||
public class JsonParserTest {
|
||||
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
|
||||
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.server.Constants;
|
||||
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.ResourceNotFoundException;
|
||||
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
|
||||
public void testReadNoCharset() throws Exception {
|
||||
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
package ca.uhn.fhir.rest.client;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
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.nio.charset.Charset;
|
||||
|
@ -13,6 +16,7 @@ import org.apache.http.client.HttpClient;
|
|||
import org.apache.http.client.methods.HttpUriRequest;
|
||||
import org.apache.http.message.BasicHeader;
|
||||
import org.apache.http.message.BasicStatusLine;
|
||||
import org.hamcrest.core.StringContains;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
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.Organization;
|
||||
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.exceptions.InternalErrorException;
|
||||
|
||||
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.api.MethodOutcome;
|
||||
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;
|
||||
|
||||
public class TesterTest {
|
||||
|
@ -62,7 +62,7 @@ public class TesterTest {
|
|||
ServletContextHandler proxyHandler = new ServletContextHandler();
|
||||
proxyHandler.setContextPath("/");
|
||||
|
||||
PublicTesterServlet testerServlet = new PublicTesterServlet();
|
||||
RestfulServerTesterServlet testerServlet = new RestfulServerTesterServlet();
|
||||
testerServlet.setServerBase("http://localhost:" + myPort + "/fhir/context");
|
||||
// testerServlet.setServerBase("http://fhir.healthintersections.com.au/open");
|
||||
ServletHolder handler = new ServletHolder();
|
||||
|
|
Loading…
Reference in New Issue