Fixing URL detection

This commit is contained in:
jamesagnew 2014-03-20 18:29:34 -04:00
parent 80826b62fd
commit 2c425ca144
21 changed files with 538 additions and 65 deletions

View File

@ -41,6 +41,7 @@ import ca.uhn.fhir.model.primitive.BoundCodeDt;
import ca.uhn.fhir.model.primitive.BoundCodeableConceptDt;
import ca.uhn.fhir.model.primitive.CodeDt;
import ca.uhn.fhir.model.primitive.DateDt;
import ca.uhn.fhir.model.primitive.DecimalDt;
import ca.uhn.fhir.model.primitive.ICodedDatatype;
import ca.uhn.fhir.model.primitive.XhtmlDt;
import ca.uhn.fhir.util.ReflectionUtil;
@ -125,6 +126,7 @@ class ModelScanner {
private void init(Set<Class<? extends IElement>> toScan) {
toScan.add(DateDt.class);
toScan.add(CodeDt.class);
toScan.add(DecimalDt.class);
do {
for (Class<? extends IElement> nextClass : toScan) {

View File

@ -26,6 +26,9 @@ public abstract class BaseElement implements IElement, ISupportsUndeclaredExtens
@Override
public IdDt getId() {
if (myId == null) {
myId = new IdDt();
}
return myId;
}

View File

@ -0,0 +1,26 @@
package ca.uhn.fhir.model.api;
import java.util.List;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
public interface IQueryParameterAnd {
/**
*
* @see See FHIR specification
* <a href="http://www.hl7.org/implement/standards/fhir/search.html#ptypes">2.2.2 Search SearchParameter Types</a>
* for information on the <b>token</b> format
*/
public void setValuesAsQueryTokens(List<List<String>> theParameters) throws InvalidRequestException;
/**
*
* @see See FHIR specification
* <a href="http://www.hl7.org/implement/standards/fhir/search.html#ptypes">2.2.2 Search SearchParameter Types</a>
* for information on the <b>token</b> format
*/
public List<List<String>> getValuesAsQueryTokens();
}

View File

@ -137,6 +137,13 @@ public class NarrativeDt extends BaseElement implements ICompositeDatatype {
myDiv = theValue;
}
/**
* Sets the value using a textual DIV (or simple text block which will be
* converted to XHTML)
*/
public void setDiv(String theTextDiv) {
myDiv = new XhtmlDt(theTextDiv);
}

View File

@ -296,10 +296,10 @@ public class DiagnosticReport extends BaseResource implements IResource {
private DateTimeDt myIssued;
@Child(name="subject", order=3, min=1, max=1, type={
ca.uhn.fhir.model.dstu.resource.Patient.class,
ca.uhn.fhir.model.dstu.resource.Group.class,
ca.uhn.fhir.model.dstu.resource.Device.class,
ca.uhn.fhir.model.dstu.resource.Location.class,
Patient.class,
Group.class,
Device.class,
Location.class,
})
@Description(
shortDefinition="The subject of the report, usually, but not always, the patient",
@ -308,8 +308,8 @@ public class DiagnosticReport extends BaseResource implements IResource {
private ResourceReferenceDt mySubject;
@Child(name="performer", order=4, min=1, max=1, type={
ca.uhn.fhir.model.dstu.resource.Practitioner.class,
ca.uhn.fhir.model.dstu.resource.Organization.class,
Practitioner.class,
Organization.class,
})
@Description(
shortDefinition="Responsible Diagnostic Service",
@ -325,7 +325,7 @@ public class DiagnosticReport extends BaseResource implements IResource {
private IdentifierDt myIdentifier;
@Child(name="requestDetail", order=6, min=0, max=Child.MAX_UNLIMITED, type={
ca.uhn.fhir.model.dstu.resource.DiagnosticOrder.class,
DiagnosticOrder.class,
})
@Description(
shortDefinition="What was requested",
@ -351,7 +351,7 @@ public class DiagnosticReport extends BaseResource implements IResource {
private IDatatype myDiagnostic;
@Child(name="specimen", order=9, min=0, max=Child.MAX_UNLIMITED, type={
ca.uhn.fhir.model.dstu.resource.Specimen.class,
Specimen.class,
})
@Description(
shortDefinition="Specimens this report is based on",
@ -360,7 +360,7 @@ public class DiagnosticReport extends BaseResource implements IResource {
private java.util.List<ResourceReferenceDt> mySpecimen;
@Child(name="result", order=10, min=0, max=Child.MAX_UNLIMITED, type={
ca.uhn.fhir.model.dstu.resource.Observation.class,
Observation.class,
})
@Description(
shortDefinition="Observations - simple, or complex nested groups",
@ -369,7 +369,7 @@ public class DiagnosticReport extends BaseResource implements IResource {
private java.util.List<ResourceReferenceDt> myResult;
@Child(name="imagingStudy", order=11, min=0, max=Child.MAX_UNLIMITED, type={
ca.uhn.fhir.model.dstu.resource.ImagingStudy.class,
ImagingStudy.class,
})
@Description(
shortDefinition="Reference to full details of imaging associated with the diagnostic report",
@ -451,7 +451,6 @@ public class DiagnosticReport extends BaseResource implements IResource {
}
/**
* Gets the value(s) for <b>status</b> (registered | partial | final | corrected +).
* creating it if it does
@ -481,7 +480,6 @@ public class DiagnosticReport extends BaseResource implements IResource {
myStatus = theValue;
}
/**
* Sets the value(s) for <b>status</b> (registered | partial | final | corrected +)
*
@ -524,6 +522,17 @@ public class DiagnosticReport extends BaseResource implements IResource {
myIssued = theValue;
}
/**
* Sets the value for <b>issued</b> (Date this version was released)
*
* <p>
* <b>Definition:</b>
* The date and/or time that this version of the report was released from the source diagnostic service
* </p>
*/
public void setIssuedWithSecondsPrecision( Date theDate) {
myIssued = new DateTimeDt(theDate);
}
/**
* Sets the value for <b>issued</b> (Date this version was released)
@ -537,18 +546,6 @@ public class DiagnosticReport extends BaseResource implements IResource {
myIssued = new DateTimeDt(theDate, thePrecision);
}
/**
* Sets the value for <b>issued</b> (Date this version was released)
*
* <p>
* <b>Definition:</b>
* The date and/or time that this version of the report was released from the source diagnostic service
* </p>
*/
public void setIssuedWithSecondsPrecision( Date theDate) {
myIssued = new DateTimeDt(theDate);
}
/**
* Gets the value(s) for <b>subject</b> (The subject of the report, usually, but not always, the patient).
@ -577,7 +574,6 @@ public class DiagnosticReport extends BaseResource implements IResource {
}
/**
* Gets the value(s) for <b>performer</b> (Responsible Diagnostic Service).
* creating it if it does
@ -605,7 +601,6 @@ public class DiagnosticReport extends BaseResource implements IResource {
}
/**
* Gets the value(s) for <b>identifier</b> (Id for external references to this report).
* creating it if it does
@ -636,7 +631,6 @@ public class DiagnosticReport extends BaseResource implements IResource {
}
/**
* Gets the value(s) for <b>requestDetail</b> (What was requested).
* creating it if it does
@ -666,7 +660,19 @@ public class DiagnosticReport extends BaseResource implements IResource {
myRequestDetail = theValue;
}
/**
* Adds and returns a new value for <b>requestDetail</b> (What was requested)
*
* <p>
* <b>Definition:</b>
* Details concerning a test requested.
* </p>
*/
public ResourceReferenceDt addRequestDetail() {
ResourceReferenceDt newType = new ResourceReferenceDt();
getRequestDetail().add(newType);
return newType;
}
/**
* Gets the value(s) for <b>serviceCategory</b> (Biochemistry, Hematology etc.).
@ -698,7 +704,6 @@ public class DiagnosticReport extends BaseResource implements IResource {
}
/**
* Gets the value(s) for <b>diagnostic[x]</b> (Physiologically Relevant time/time-period for report).
* creating it if it does
@ -726,7 +731,6 @@ public class DiagnosticReport extends BaseResource implements IResource {
}
/**
* Gets the value(s) for <b>specimen</b> (Specimens this report is based on).
* creating it if it does
@ -756,7 +760,19 @@ public class DiagnosticReport extends BaseResource implements IResource {
mySpecimen = theValue;
}
/**
* Adds and returns a new value for <b>specimen</b> (Specimens this report is based on)
*
* <p>
* <b>Definition:</b>
* Details about the specimens on which this Disagnostic report is based
* </p>
*/
public ResourceReferenceDt addSpecimen() {
ResourceReferenceDt newType = new ResourceReferenceDt();
getSpecimen().add(newType);
return newType;
}
/**
* Gets the value(s) for <b>result</b> (Observations - simple, or complex nested groups).
@ -787,7 +803,19 @@ public class DiagnosticReport extends BaseResource implements IResource {
myResult = theValue;
}
/**
* Adds and returns a new value for <b>result</b> (Observations - simple, or complex nested groups)
*
* <p>
* <b>Definition:</b>
* Observations that are part of this diagnostic report. Observations can be simple name/value pairs (e.g. \"atomic\" results), or they can be grouping observations that include references to other members of the group (e.g. \"panels\")
* </p>
*/
public ResourceReferenceDt addResult() {
ResourceReferenceDt newType = new ResourceReferenceDt();
getResult().add(newType);
return newType;
}
/**
* Gets the value(s) for <b>imagingStudy</b> (Reference to full details of imaging associated with the diagnostic report).
@ -818,7 +846,19 @@ public class DiagnosticReport extends BaseResource implements IResource {
myImagingStudy = theValue;
}
/**
* Adds and returns a new value for <b>imagingStudy</b> (Reference to full details of imaging associated with the diagnostic report)
*
* <p>
* <b>Definition:</b>
* One or more links to full details of any imaging performed during the diagnostic investigation. Typically, this is imaging performed by DICOM enabled modalities, but this is not required. A fully enabled PACS viewer can use this information to provide views of the source images
* </p>
*/
public ResourceReferenceDt addImagingStudy() {
ResourceReferenceDt newType = new ResourceReferenceDt();
getImagingStudy().add(newType);
return newType;
}
/**
* Gets the value(s) for <b>image</b> (Key images associated with this report).
@ -863,7 +903,6 @@ public class DiagnosticReport extends BaseResource implements IResource {
return newType;
}
/**
* Gets the value(s) for <b>conclusion</b> (Clinical Interpretation of test results).
* creating it if it does
@ -893,7 +932,6 @@ public class DiagnosticReport extends BaseResource implements IResource {
myConclusion = theValue;
}
/**
* Sets the value for <b>conclusion</b> (Clinical Interpretation of test results)
*
@ -950,7 +988,6 @@ public class DiagnosticReport extends BaseResource implements IResource {
return newType;
}
/**
* Gets the value(s) for <b>presentedForm</b> (Entire Report as issued).
* creating it if it does
@ -994,7 +1031,6 @@ public class DiagnosticReport extends BaseResource implements IResource {
return newType;
}
/**
* Block class for child element: <b>DiagnosticReport.image</b> (Key images associated with this report)
*
@ -1014,7 +1050,7 @@ public class DiagnosticReport extends BaseResource implements IResource {
private StringDt myComment;
@Child(name="link", order=1, min=1, max=1, type={
ca.uhn.fhir.model.dstu.resource.Media.class,
Media.class,
})
@Description(
shortDefinition="Reference to the image source",
@ -1067,7 +1103,6 @@ public class DiagnosticReport extends BaseResource implements IResource {
myComment = theValue;
}
/**
* Sets the value for <b>comment</b> (Comment about the image (e.g. explanation))
*
@ -1112,7 +1147,6 @@ public class DiagnosticReport extends BaseResource implements IResource {
}

View File

@ -1,6 +1,8 @@
package ca.uhn.fhir.model.primitive;
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import ca.uhn.fhir.model.api.BasePrimitive;
import ca.uhn.fhir.model.api.annotation.DatatypeDef;
@ -35,6 +37,31 @@ public class DecimalDt extends BasePrimitive<BigDecimal> {
setValue(new BigDecimal(theValue));
}
/**
* Rounds the value to the given prevision
*
* @see MathContext#getPrecision()
*/
public void round(int thePrecision) {
if (getValue()!=null) {
BigDecimal newValue = getValue().round(new MathContext(thePrecision));
setValue(newValue);
}
}
/**
* Rounds the value to the given prevision
*
* @see MathContext#getPrecision()
* @see MathContext#getRoundingMode()
*/
public void round(int thePrecision, RoundingMode theRoundingMode) {
if (getValue()!=null) {
BigDecimal newValue = getValue().round(new MathContext(thePrecision, theRoundingMode));
setValue(newValue);
}
}
/**
* Constructor
*/

View File

@ -114,4 +114,16 @@ public class IdDt extends BasePrimitive<String> {
return myValue;
}
/**
* Returns the value of this ID as a big decimal, or <code>null</code> if the value is null
*
* @throws NumberFormatException If the value is not a valid BigDecimal
*/
public BigDecimal asBigDecimal() {
if (getValue() == null){
return null;
}
return new BigDecimal(getValueAsString());
}
}

View File

@ -66,16 +66,17 @@ public class XhtmlDt extends BasePrimitive<List<XMLEvent>> {
XMLEventReader er = XMLInputFactory.newInstance().createXMLEventReader(new StringReader(val));
boolean first = true;
while (er.hasNext()) {
XMLEvent next = er.nextEvent();
if (first) {
first = false;
continue;
}
XMLEvent next = er.nextEvent();
if (er.hasNext()) {
// don't add the last event
value.add(next);
}
}
setValue(value);
} catch (XMLStreamException e) {
throw new DataFormatException("String does not appear to be valid XML/XHTML", e);

View File

@ -43,6 +43,7 @@ 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.UndeclaredExtension;
import ca.uhn.fhir.model.dstu.composite.ContainedDt;
import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt;
import ca.uhn.fhir.model.primitive.InstantDt;
import ca.uhn.fhir.model.primitive.StringDt;
@ -122,7 +123,7 @@ public class XmlParser extends BaseParser implements IParser {
eventWriter.writeAttribute("type", "text/xml");
IResource resource = nextEntry.getResource();
encodeResourceToXmlStreamWriter(resource, eventWriter);
encodeResourceToXmlStreamWriter(resource, eventWriter, false);
eventWriter.writeEndElement(); // content
eventWriter.writeEndElement(); // entry
@ -149,7 +150,7 @@ public class XmlParser extends BaseParser implements IParser {
eventWriter = myXmlOutputFactory.createXMLStreamWriter(stringWriter);
eventWriter = decorateStreamWriter(eventWriter);
encodeResourceToXmlStreamWriter(theResource, eventWriter);
encodeResourceToXmlStreamWriter(theResource, eventWriter, false);
eventWriter.flush();
} catch (XMLStreamException e) {
throw new ConfigurationException("Failed to initialize STaX event factory", e);
@ -323,6 +324,15 @@ public class XmlParser extends BaseParser implements IParser {
}
break;
}
case CONTAINED_RESOURCES: {
ContainedDt value = (ContainedDt) nextValue;
theEventWriter.writeStartElement("contained");
for (IResource next : value.getContainedResources()) {
encodeResourceToXmlStreamWriter(next, theEventWriter, true);
}
theEventWriter.writeEndElement();
break;
}
case RESOURCE: {
throw new IllegalStateException(); // should not happen
}
@ -333,8 +343,9 @@ public class XmlParser extends BaseParser implements IParser {
}
break;
}
case EXTENSION_DECLARED:
case UNDECL_EXT: {
throw new IllegalStateException("should not happen");
throw new IllegalStateException("state should not happen: " + childDef.getName());
}
}
@ -405,7 +416,7 @@ public class XmlParser extends BaseParser implements IParser {
}
private void encodeResourceToXmlStreamWriter(IResource theResource, XMLStreamWriter eventWriter) throws XMLStreamException, DataFormatException {
private void encodeResourceToXmlStreamWriter(IResource theResource, XMLStreamWriter theEventWriter, boolean theIncludeResourceId) throws XMLStreamException, DataFormatException {
super.containResourcesForEncoding(theResource);
RuntimeResourceDefinition resDef = myContext.getResourceDefinition(theResource);
@ -413,12 +424,16 @@ public class XmlParser extends BaseParser implements IParser {
throw new ConfigurationException("Unknown resource type: " + theResource.getClass());
}
eventWriter.writeStartElement(resDef.getName());
eventWriter.writeDefaultNamespace(FHIR_NS);
theEventWriter.writeStartElement(resDef.getName());
theEventWriter.writeDefaultNamespace(FHIR_NS);
encodeCompositeElementToStreamWriter(theResource, eventWriter, resDef);
if (theIncludeResourceId && StringUtils.isNotBlank(theResource.getId().getValue())) {
theEventWriter.writeAttribute("id", theResource.getId().getValue());
}
eventWriter.writeEndElement();
encodeCompositeElementToStreamWriter(theResource, theEventWriter, resDef);
theEventWriter.writeEndElement();
}
private void encodeUndeclaredExtensions(XMLStreamWriter theWriter, List<UndeclaredExtension> extensions, String tagName) throws XMLStreamException {

View File

@ -1,12 +1,13 @@
package ca.uhn.fhir.rest.param;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import ca.uhn.fhir.model.api.IQueryParameterOr;
import ca.uhn.fhir.model.dstu.composite.CodingDt;
public class CodingListParam implements IQueryParameterOr {
public class CodingListParam implements IQueryParameterOr, Iterable<CodingDt> {
private List<CodingDt> myCodings = new ArrayList<CodingDt>();
@ -14,6 +15,9 @@ public class CodingListParam implements IQueryParameterOr {
* Returns all Codings associated with this list
*/
public List<CodingDt> getCodings() {
if (myCodings == null) {
myCodings = new ArrayList<CodingDt>();
}
return myCodings;
}
@ -35,6 +39,7 @@ public class CodingListParam implements IQueryParameterOr {
@Override
public void setValuesAsQueryTokens(List<String> theParameters) {
getCodings().clear();
for (String string : theParameters) {
CodingDt dt = new CodingDt();
dt.setValueAsQueryToken(string);
@ -46,4 +51,9 @@ public class CodingListParam implements IQueryParameterOr {
myCodings.add(theCodingDt);
}
@Override
public Iterator<CodingDt> iterator() {
return getCodings().iterator();
}
}

View File

@ -0,0 +1,103 @@
package ca.uhn.fhir.rest.param;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import ca.uhn.fhir.model.api.IQueryParameterAnd;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
public class DateRangeParam implements IQueryParameterAnd {
private QualifiedDateParam myLowerBound;
private QualifiedDateParam myUpperBound;
private void addParam(QualifiedDateParam theParsed) throws InvalidRequestException {
if (theParsed.getComparator() == null) {
if (myLowerBound != null || myUpperBound != null) {
throw new InvalidRequestException("Can not have multiple date range parameters for the same param without a qualifier");
}
myLowerBound = theParsed;
myUpperBound = theParsed;
// TODO: in this case, should set lower and upper to exact moments using specified precision
} else {
switch (theParsed.getComparator()) {
case GREATERTHAN:
case GREATERTHAN_OR_EQUALS:
if (myLowerBound != null) {
throw new InvalidRequestException("Can not have multiple date range parameters for the same param that specify a lower bound");
}
myLowerBound = theParsed;
break;
case LESSTHAN:
case LESSTHAN_OR_EQUALS:
if (myUpperBound != null) {
throw new InvalidRequestException("Can not have multiple date range parameters for the same param that specify an upper bound");
}
myUpperBound = theParsed;
break;
default:
throw new InvalidRequestException("Unknown comparator: " + theParsed.getComparator());
}
}
}
public QualifiedDateParam getLowerBound() {
return myLowerBound;
}
public QualifiedDateParam getUpperBound() {
return myUpperBound;
}
@Override
public List<List<String>> getValuesAsQueryTokens() {
ArrayList<List<String>> retVal = new ArrayList<List<String>>();
if (myLowerBound != null) {
retVal.add(Collections.singletonList(myLowerBound.getValueAsQueryToken()));
}
if (myUpperBound != null) {
retVal.add(Collections.singletonList(myUpperBound.getValueAsQueryToken()));
}
return retVal;
}
public void setLowerBound(QualifiedDateParam theLowerBound) {
myLowerBound = theLowerBound;
}
public void setUpperBound(QualifiedDateParam theUpperBound) {
myUpperBound = theUpperBound;
}
@Override
public void setValuesAsQueryTokens(List<List<String>> theParameters) throws InvalidRequestException {
for (List<String> paramList : theParameters) {
if (paramList.size() == 0) {
continue;
}
if (paramList.size() > 1) {
throw new InvalidRequestException("DateRange parameter does not suppport OR queries");
}
String param = paramList.get(0);
QualifiedDateParam parsed = new QualifiedDateParam();
parsed.setValueAsQueryToken(param);
addParam(parsed);
}
}
public Date getLowerBoundAsInstant() {
// TODO: account for precision
return myLowerBound.getValue();
}
public Date getUpperBoundAsInstant() {
// TODO: account for precision
return myUpperBound.getValue();
}
}

View File

@ -0,0 +1,37 @@
package ca.uhn.fhir.rest.param;
import java.util.List;
import ca.uhn.fhir.model.api.IQueryParameterAnd;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
final class QueryParameterAndBinder implements IParamBinder {
private final Class<? extends IQueryParameterAnd> myType;
QueryParameterAndBinder(Class<? extends IQueryParameterAnd> theType) {
myType = theType;
}
@Override
public List<List<String>> encode(Object theString) throws InternalErrorException {
List<List<String>> retVal = ((IQueryParameterAnd) theString).getValuesAsQueryTokens();
return retVal;
}
@Override
public Object parse(List<List<String>> theString) throws InternalErrorException, InvalidRequestException {
IQueryParameterAnd dt;
try {
dt = myType.newInstance();
dt.setValuesAsQueryTokens(theString);
} catch (InstantiationException e) {
throw new InternalErrorException(e);
} catch (IllegalAccessException e) {
throw new InternalErrorException(e);
} catch (SecurityException e) {
throw new InternalErrorException(e);
}
return dt;
}
}

View File

@ -4,6 +4,7 @@ import java.util.Collection;
import java.util.List;
import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.model.api.IQueryParameterAnd;
import ca.uhn.fhir.model.api.IQueryParameterOr;
import ca.uhn.fhir.model.api.IQueryParameterType;
import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
@ -79,6 +80,8 @@ public class SearchParameter implements IParameter {
this.parser = new QueryParameterTypeBinder((Class<? extends IQueryParameterType>) type);
} else if (IQueryParameterOr.class.isAssignableFrom(type)) {
this.parser = new QueryParameterOrBinder((Class<? extends IQueryParameterOr>) type);
} else if (IQueryParameterAnd.class.isAssignableFrom(type)) {
this.parser = new QueryParameterAndBinder((Class<? extends IQueryParameterAnd>) type);
} else {
throw new ConfigurationException("Unsupported data type for parameter: " + type.getCanonicalName());
}
@ -87,6 +90,8 @@ public class SearchParameter implements IParameter {
myParamType = SearchParamTypeEnum.STRING;
} else if (QualifiedDateParam.class.isAssignableFrom(type)) {
myParamType = SearchParamTypeEnum.DATE;
} else if (DateRangeParam.class.isAssignableFrom(type)) {
myParamType = SearchParamTypeEnum.DATE;
} else if (CodingListParam.class.isAssignableFrom(type)) {
myParamType = SearchParamTypeEnum.TOKEN;
} else if (IdentifierDt.class.isAssignableFrom(type)) {

View File

@ -186,6 +186,19 @@ public abstract class RestfulServer extends HttpServlet {
String requestFullPath = StringUtils.defaultString(request.getRequestURI());
// String contextPath = StringUtils.defaultString(request.getContextPath());
String servletPath = StringUtils.defaultString(request.getServletPath());
StringBuffer requestUrl = request.getRequestURL();
String servletContextPath = "";
if (request.getServletContext() != null) {
servletContextPath = StringUtils.defaultString(request.getServletContext().getContextPath());
}
ourLog.info("Request FullPath: {}", requestFullPath);
ourLog.info("Servlet Path: {}", servletPath);
ourLog.info("Request Url: {}", requestUrl);
ourLog.info("Context Path: {}", servletContextPath);
servletPath = servletContextPath;
IdDt id = null;
IdDt versionId = null;
String operation = null;
@ -195,13 +208,10 @@ public abstract class RestfulServer extends HttpServlet {
requestPath = requestPath.substring(1);
}
StringBuffer requestUrl = request.getRequestURL();
int contextIndex = requestUrl.indexOf(servletPath);
String fhirServerBase = requestUrl.substring(0, contextIndex + servletPath.length());
String completeUrl = StringUtils.isNotBlank(request.getQueryString()) ? requestUrl + "?" + request.getQueryString() : requestUrl.toString();
ourLog.info("Request URI: {}", requestPath);
Map<String, String[]> params = new HashMap<String, String[]>(request.getParameterMap());
EncodingUtil responseEncoding = determineResponseEncoding(request, params);

View File

@ -1,5 +1,7 @@
package ca.uhn.fhir.rest.server.exceptions;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
import ca.uhn.fhir.model.primitive.IdDt;
public class ResourceNotFoundException extends BaseServerResponseException {
@ -8,6 +10,10 @@ public class ResourceNotFoundException extends BaseServerResponseException {
super(404, "Resource " + (theId != null ? theId.getValue() : "") + " is not known");
}
public ResourceNotFoundException(Class<? extends IResource> theClass, IdentifierDt thePatientId) {
super(404, "Resource of type " + theClass.getSimpleName() + " with ID " + thePatientId + " is not known");
}
private static final long serialVersionUID = 1L;
}

View File

@ -11,6 +11,8 @@ import net.sf.json.JSON;
import net.sf.json.JSONSerializer;
import org.apache.commons.io.IOUtils;
import org.hamcrest.core.IsNot;
import org.hamcrest.core.StringContains;
import org.junit.Test;
import ca.uhn.fhir.context.FhirContext;
@ -19,6 +21,8 @@ import ca.uhn.fhir.model.api.UndeclaredExtension;
import ca.uhn.fhir.model.dstu.resource.DiagnosticReport;
import ca.uhn.fhir.model.dstu.resource.Observation;
import ca.uhn.fhir.model.dstu.resource.Patient;
import ca.uhn.fhir.model.dstu.resource.Specimen;
import ca.uhn.fhir.model.primitive.DecimalDt;
public class JsonParserTest {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(JsonParserTest.class);
@ -88,5 +92,39 @@ public class JsonParserTest {
}
@Test
public void testEncodeContainedResourcesMore() throws IOException {
DiagnosticReport rpt = new DiagnosticReport();
Specimen spm = new Specimen();
spm.getText().setDiv("AAA");
rpt.addSpecimen().setResource(spm);
IParser p = new FhirContext(DiagnosticReport.class).newJsonParser().setPrettyPrint(true);
String str = p.encodeResourceToString(rpt);
ourLog.info(str);
assertThat(str, StringContains.containsString("<div>AAA</div>"));
String substring = "\"resource\":\"#";
assertThat(str, StringContains.containsString(substring));
int idx = str.indexOf(substring) + substring.length();
int idx2 = str.indexOf('"', idx+1);
String id = str.substring(idx, idx2);
assertThat(str, StringContains.containsString("\"id\":\"" + id + "\""));
assertThat(str, IsNot.not(StringContains.containsString("<?xml version='1.0'?>")));
}
@Test
public void testEncodeInvalidChildGoodException() throws IOException {
Observation obs = new Observation();
obs.setValue(new DecimalDt(112.22));
IParser p = new FhirContext(Observation.class).newXmlParser();
// Should have good error message
p.encodeResourceToString(obs);
}
}

View File

@ -8,6 +8,8 @@ import java.io.StringReader;
import org.apache.commons.io.IOUtils;
import org.custommonkey.xmlunit.Diff;
import org.custommonkey.xmlunit.XMLUnit;
import org.hamcrest.core.IsNot;
import org.hamcrest.core.StringContains;
import org.junit.BeforeClass;
import org.junit.Test;
import org.xml.sax.SAXException;
@ -18,12 +20,15 @@ import ca.uhn.fhir.context.ResourceWithExtensionsA;
import ca.uhn.fhir.model.api.Bundle;
import ca.uhn.fhir.model.api.BundleEntry;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.dstu.composite.NarrativeDt;
import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt;
import ca.uhn.fhir.model.dstu.resource.DiagnosticReport;
import ca.uhn.fhir.model.dstu.resource.Observation;
import ca.uhn.fhir.model.dstu.resource.Patient;
import ca.uhn.fhir.model.dstu.resource.Specimen;
import ca.uhn.fhir.model.dstu.resource.ValueSet;
import ca.uhn.fhir.model.dstu.valueset.NarrativeStatusEnum;
import ca.uhn.fhir.model.primitive.DecimalDt;
public class XmlParserTest {
@ -54,6 +59,41 @@ public class XmlParserTest {
}
@Test
public void testEncodeInvalidChildGoodException() throws IOException {
Observation obs = new Observation();
obs.setValue(new DecimalDt(112.22));
IParser p = new FhirContext(Observation.class).newXmlParser();
// Should have good error message
p.encodeResourceToString(obs);
}
@Test
public void testEncodeContainedResources() throws IOException {
DiagnosticReport rpt = new DiagnosticReport();
Specimen spm = new Specimen();
spm.getText().setDiv("AAA");
rpt.addSpecimen().setResource(spm);
IParser p = new FhirContext(DiagnosticReport.class).newXmlParser().setPrettyPrint(true);
String str = p.encodeResourceToString(rpt);
ourLog.info(str);
assertThat(str, StringContains.containsString("<div>AAA</div>"));
assertThat(str, StringContains.containsString("reference value=\"#"));
int idx = str.indexOf("reference value=\"#") + "reference value=\"#".length();
int idx2 = str.indexOf('"', idx+1);
String id = str.substring(idx, idx2);
assertThat(str, StringContains.containsString("<Specimen xmlns=\"http://hl7.org/fhir\" id=\"" + id + "\">"));
assertThat(str, IsNot.not(StringContains.containsString("<?xml version='1.0'?>")));
}
@Test
public void testParseBundle() {

View File

@ -32,6 +32,7 @@ import ca.uhn.fhir.model.dstu.valueset.QuantityCompararatorEnum;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.rest.param.CodingListParam;
import ca.uhn.fhir.rest.param.DateRangeParam;
import ca.uhn.fhir.rest.param.QualifiedDateParam;
import ca.uhn.fhir.rest.server.Constants;
@ -134,6 +135,32 @@ public class ClientTest {
}
@Test
public void testSearchByDateRange() throws Exception {
String msg = getPatientFeedWithOneResult();
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
when(httpClient.execute(capt.capture())).thenReturn(httpResponse);
when(httpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
when(httpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(httpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));
ITestClient client = clientFactory.newClient(ITestClient.class, "http://foo");
DateRangeParam param = new DateRangeParam();
param.setLowerBound(new QualifiedDateParam(QuantityCompararatorEnum.GREATERTHAN_OR_EQUALS, "2011-01-01"));
param.setUpperBound(new QualifiedDateParam(QuantityCompararatorEnum.LESSTHAN_OR_EQUALS, "2021-01-01"));
List<Patient> response = client.getPatientByDateRange(param);
assertEquals("http://foo/Patient?dateRange=%3E%3D2011-01-01&dateRange=%3C%3D2021-01-01", capt.getValue().getURI().toString());
}
@Test
public void testSearchByDob() throws Exception {

View File

@ -15,6 +15,7 @@ import ca.uhn.fhir.rest.annotation.Required;
import ca.uhn.fhir.rest.annotation.Search;
import ca.uhn.fhir.rest.client.api.IBasicClient;
import ca.uhn.fhir.rest.param.CodingListParam;
import ca.uhn.fhir.rest.param.DateRangeParam;
import ca.uhn.fhir.rest.param.QualifiedDateParam;
public interface ITestClient extends IBasicClient {
@ -34,6 +35,9 @@ public interface ITestClient extends IBasicClient {
@Search()
public List<Patient> getPatientMultipleIdentifiers(@Required(name = "ids") CodingListParam theIdentifiers);
@Search()
public List<Patient> getPatientByDateRange(@Required(name = "dateRange") DateRangeParam theIdentifiers);
@Search()
public List<Patient> getPatientByDob(@Required(name=Patient.SP_BIRTHDATE) QualifiedDateParam theBirthDate);

View File

@ -7,6 +7,7 @@ import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -25,6 +26,7 @@ import org.eclipse.jetty.servlet.ServletHolder;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.experimental.theories.Theories;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.Bundle;
@ -33,6 +35,7 @@ import ca.uhn.fhir.model.dstu.composite.CodingDt;
import ca.uhn.fhir.model.dstu.composite.HumanNameDt;
import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
import ca.uhn.fhir.model.dstu.resource.Conformance;
import ca.uhn.fhir.model.dstu.resource.DiagnosticReport;
import ca.uhn.fhir.model.dstu.resource.Patient;
import ca.uhn.fhir.model.dstu.valueset.IdentifierUseEnum;
import ca.uhn.fhir.model.primitive.IdDt;
@ -45,6 +48,7 @@ import ca.uhn.fhir.rest.annotation.Read;
import ca.uhn.fhir.rest.annotation.Required;
import ca.uhn.fhir.rest.annotation.Search;
import ca.uhn.fhir.rest.param.CodingListParam;
import ca.uhn.fhir.rest.param.DateRangeParam;
import ca.uhn.fhir.rest.param.QualifiedDateParam;
import ca.uhn.fhir.rest.server.provider.ServerProfileProvider;
import ca.uhn.fhir.testutil.RandomServerPortProvider;
@ -142,16 +146,16 @@ public class ResfulServerMethodTest {
ourLog.info("Response:\n{}", enc);
assertTrue(enc.contains(ExtensionConstants.CONF_ALSO_CHAIN));
}
// {
// IParser p = ourCtx.newJsonParser().setPrettyPrint(true);
//
// p.encodeResourceToWriter(bundle, new OutputStreamWriter(System.out));
//
// String enc = p.encodeResourceToString(bundle);
// ourLog.info("Response:\n{}", enc);
// assertTrue(enc.contains(ExtensionConstants.CONF_ALSO_CHAIN));
//
// }
// {
// IParser p = ourCtx.newJsonParser().setPrettyPrint(true);
//
// p.encodeResourceToWriter(bundle, new OutputStreamWriter(System.out));
//
// String enc = p.encodeResourceToString(bundle);
// ourLog.info("Response:\n{}", enc);
// assertTrue(enc.contains(ExtensionConstants.CONF_ALSO_CHAIN));
//
// }
}
@Test
@ -212,6 +216,18 @@ public class ResfulServerMethodTest {
assertEquals("urn:bbb|bbb", patient.getIdentifier().get(2).getValueAsQueryToken());
}
// @Test
// public void testSearchByComplex() throws Exception {
//
// HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?Patient.identifier=urn:oid:2.16.840.1.113883.3.239.18.148%7C7000135&name=urn:oid:1.3.6.1.4.1.12201.102.5%7C522&date=");
// HttpResponse status = ourClient.execute(httpGet);
//
// String responseContent = IOUtils.toString(status.getEntity().getContent());
// ourLog.info("Response was:\n{}", responseContent);
//
// assertEquals(200, status.getStatusLine().getStatusCode());
// }
@Test
public void testSearchByDob() throws Exception {
@ -361,11 +377,30 @@ public class ResfulServerMethodTest {
assertEquals(200, status.getStatusLine().getStatusCode());
// TODO: enable once JSON parser is written
// Patient patient = (Patient)
// ourCtx.newJsonParser().parseResource(responseContent);
// assertEquals("PatientOne",
// patient.getName().get(0).getGiven().get(0).getValue());
Patient patient = (Patient) ourCtx.newJsonParser().parseResource(responseContent);
assertEquals("PatientOne", patient.getName().get(0).getGiven().get(0).getValue());
}
@Test
public void testDateRangeParam() throws Exception {
// HttpPost httpPost = new HttpPost("http://localhost:" + ourPort +
// "/Patient/1");
// httpPost.setEntity(new StringEntity("test",
// ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?dateRange=%3E%3D2011-01-01&dateRange=%3C%3D2021-01-01");
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
ourLog.info("Response was:\n{}", responseContent);
assertEquals(200, status.getStatusLine().getStatusCode());
Patient patient = (Patient) ourCtx.newXmlParser().parseBundle(responseContent).getEntries().get(0).getResource();
assertEquals(">=2011-01-01", patient.getName().get(0).getSuffix().get(0).getValue());
assertEquals("<=2021-01-01", patient.getName().get(0).getSuffix().get(1).getValue());
}
@ -517,6 +552,15 @@ public class ResfulServerMethodTest {
return null;
}
@SuppressWarnings("unused")
public List<Patient> findDiagnosticReportsByPatient(
@Required(name="Patient.identifier") IdentifierDt thePatientId,
@Required(name=DiagnosticReport.SP_NAME) CodingListParam theNames,
@Optional(name=DiagnosticReport.SP_DATE) DateRangeParam theDateRange
) throws Exception {
return Collections.emptyList();
}
@Search()
public Patient getPatientWithDOB(@Required(name = "dob") QualifiedDateParam theDob) {
Patient next = getIdToPatient().get("1");
@ -601,6 +645,14 @@ public class ResfulServerMethodTest {
return Patient.class;
}
@Search()
public Patient getPatientByDateRange(@Required(name = "dateRange") DateRangeParam theIdentifiers) {
Patient retVal = getIdToPatient().get("1");
retVal.getName().get(0).addSuffix().setValue(theIdentifiers.getLowerBound().getValueAsQueryToken());
retVal.getName().get(0).addSuffix().setValue(theIdentifiers.getUpperBound().getValueAsQueryToken());
return retVal;
}
}
}

View File

@ -106,7 +106,21 @@
return newType;
}
#end
#if( ${child.repeatable} && ${child.singleChildInstantiable} && ${child.resourceRef} )
/**
* Adds and returns a new value for <b>${child.elementName}</b> (${child.shortName})
*
* <p>
* <b>Definition:</b>
* ${child.definition}
* </p>
*/
public ResourceReferenceDt add${child.methodName}() {
ResourceReferenceDt newType = new ResourceReferenceDt();
get${child.methodName}().add(newType);
return newType;
}
#end
#if ( ${child.boundCode} && ${child.repeatable} )
/**
* Add a value for <b>${child.elementName}</b> (${child.shortName})