diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/ModelScanner.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/ModelScanner.java
index a6d2730204e..c26f527c507 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/ModelScanner.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/ModelScanner.java
@@ -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,7 +126,8 @@ class ModelScanner {
private void init(Set> toScan) {
toScan.add(DateDt.class);
toScan.add(CodeDt.class);
-
+ toScan.add(DecimalDt.class);
+
do {
for (Class extends IElement> nextClass : toScan) {
scan(nextClass);
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/BaseElement.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/BaseElement.java
index 615dc375316..d6179448e17 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/BaseElement.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/BaseElement.java
@@ -26,6 +26,9 @@ public abstract class BaseElement implements IElement, ISupportsUndeclaredExtens
@Override
public IdDt getId() {
+ if (myId == null) {
+ myId = new IdDt();
+ }
return myId;
}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/IQueryParameterAnd.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/IQueryParameterAnd.java
new file mode 100644
index 00000000000..4dc2f5fee06
--- /dev/null
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/IQueryParameterAnd.java
@@ -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
+ * 2.2.2 Search SearchParameter Types
+ * for information on the token format
+ */
+ public void setValuesAsQueryTokens(List> theParameters) throws InvalidRequestException;
+
+ /**
+ *
+ * @see See FHIR specification
+ * 2.2.2 Search SearchParameter Types
+ * for information on the token format
+ */
+ public List> getValuesAsQueryTokens();
+
+
+}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/dstu/composite/NarrativeDt.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/dstu/composite/NarrativeDt.java
index f58eab85710..5ecd1b429cc 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/dstu/composite/NarrativeDt.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/dstu/composite/NarrativeDt.java
@@ -137,8 +137,15 @@ 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);
+ }
+
-
}
\ No newline at end of file
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/dstu/resource/DiagnosticReport.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/dstu/resource/DiagnosticReport.java
index 24bf9f71786..4af544c50a3 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/dstu/resource/DiagnosticReport.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/dstu/resource/DiagnosticReport.java
@@ -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 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 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",
@@ -450,7 +450,6 @@ public class DiagnosticReport extends BaseResource implements IResource {
myName = theValue;
}
-
/**
* Gets the value(s) for status (registered | partial | final | corrected +).
@@ -481,7 +480,6 @@ public class DiagnosticReport extends BaseResource implements IResource {
myStatus = theValue;
}
-
/**
* Sets the value(s) for status (registered | partial | final | corrected +)
*
@@ -524,7 +522,6 @@ public class DiagnosticReport extends BaseResource implements IResource {
myIssued = theValue;
}
-
/**
* Sets the value for issued (Date this version was released)
*
@@ -533,8 +530,8 @@ public class DiagnosticReport extends BaseResource implements IResource {
* The date and/or time that this version of the report was released from the source diagnostic service
*
*/
- public void setIssued( Date theDate, TemporalPrecisionEnum thePrecision) {
- myIssued = new DateTimeDt(theDate, thePrecision);
+ public void setIssuedWithSecondsPrecision( Date theDate) {
+ myIssued = new DateTimeDt(theDate);
}
/**
@@ -545,8 +542,8 @@ public class DiagnosticReport extends BaseResource implements IResource {
* The date and/or time that this version of the report was released from the source diagnostic service
*
*/
- public void setIssuedWithSecondsPrecision( Date theDate) {
- myIssued = new DateTimeDt(theDate);
+ public void setIssued( Date theDate, TemporalPrecisionEnum thePrecision) {
+ myIssued = new DateTimeDt(theDate, thePrecision);
}
@@ -576,7 +573,6 @@ public class DiagnosticReport extends BaseResource implements IResource {
mySubject = theValue;
}
-
/**
* Gets the value(s) for performer (Responsible Diagnostic Service).
@@ -604,7 +600,6 @@ public class DiagnosticReport extends BaseResource implements IResource {
myPerformer = theValue;
}
-
/**
* Gets the value(s) for identifier (Id for external references to this report).
@@ -635,7 +630,6 @@ public class DiagnosticReport extends BaseResource implements IResource {
myIdentifier = theValue;
}
-
/**
* Gets the value(s) for requestDetail (What was requested).
@@ -666,7 +660,19 @@ public class DiagnosticReport extends BaseResource implements IResource {
myRequestDetail = theValue;
}
-
+ /**
+ * Adds and returns a new value for requestDetail (What was requested)
+ *
+ *
+ * Definition:
+ * Details concerning a test requested.
+ *
+ */
+ public ResourceReferenceDt addRequestDetail() {
+ ResourceReferenceDt newType = new ResourceReferenceDt();
+ getRequestDetail().add(newType);
+ return newType;
+ }
/**
* Gets the value(s) for serviceCategory (Biochemistry, Hematology etc.).
@@ -697,7 +703,6 @@ public class DiagnosticReport extends BaseResource implements IResource {
myServiceCategory = theValue;
}
-
/**
* Gets the value(s) for diagnostic[x] (Physiologically Relevant time/time-period for report).
@@ -725,7 +730,6 @@ public class DiagnosticReport extends BaseResource implements IResource {
myDiagnostic = theValue;
}
-
/**
* Gets the value(s) for specimen (Specimens this report is based on).
@@ -756,7 +760,19 @@ public class DiagnosticReport extends BaseResource implements IResource {
mySpecimen = theValue;
}
-
+ /**
+ * Adds and returns a new value for specimen (Specimens this report is based on)
+ *
+ *
+ * Definition:
+ * Details about the specimens on which this Disagnostic report is based
+ *
+ */
+ public ResourceReferenceDt addSpecimen() {
+ ResourceReferenceDt newType = new ResourceReferenceDt();
+ getSpecimen().add(newType);
+ return newType;
+ }
/**
* Gets the value(s) for result (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 result (Observations - simple, or complex nested groups)
+ *
+ *
+ * Definition:
+ * 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\")
+ *
+ */
+ public ResourceReferenceDt addResult() {
+ ResourceReferenceDt newType = new ResourceReferenceDt();
+ getResult().add(newType);
+ return newType;
+ }
/**
* Gets the value(s) for imagingStudy (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 imagingStudy (Reference to full details of imaging associated with the diagnostic report)
+ *
+ *
+ * Definition:
+ * 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
+ *
+ */
+ public ResourceReferenceDt addImagingStudy() {
+ ResourceReferenceDt newType = new ResourceReferenceDt();
+ getImagingStudy().add(newType);
+ return newType;
+ }
/**
* Gets the value(s) for image (Key images associated with this report).
@@ -862,7 +902,6 @@ public class DiagnosticReport extends BaseResource implements IResource {
getImage().add(newType);
return newType;
}
-
/**
* Gets the value(s) for conclusion (Clinical Interpretation of test results).
@@ -893,7 +932,6 @@ public class DiagnosticReport extends BaseResource implements IResource {
myConclusion = theValue;
}
-
/**
* Sets the value for conclusion (Clinical Interpretation of test results)
*
@@ -949,7 +987,6 @@ public class DiagnosticReport extends BaseResource implements IResource {
getCodedDiagnosis().add(newType);
return newType;
}
-
/**
* Gets the value(s) for presentedForm (Entire Report as issued).
@@ -993,7 +1030,6 @@ public class DiagnosticReport extends BaseResource implements IResource {
getPresentedForm().add(newType);
return newType;
}
-
/**
* Block class for child element: DiagnosticReport.image (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 comment (Comment about the image (e.g. explanation))
*
@@ -1110,7 +1145,6 @@ public class DiagnosticReport extends BaseResource implements IResource {
myLink = theValue;
}
-
}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/primitive/DecimalDt.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/primitive/DecimalDt.java
index b194525d800..ec1caabde51 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/primitive/DecimalDt.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/primitive/DecimalDt.java
@@ -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 {
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
*/
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/primitive/IdDt.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/primitive/IdDt.java
index 27ccadb9ca2..08d1fa3c318 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/primitive/IdDt.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/primitive/IdDt.java
@@ -114,4 +114,16 @@ public class IdDt extends BasePrimitive {
return myValue;
}
+ /**
+ * Returns the value of this ID as a big decimal, or null
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());
+ }
+
}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/primitive/XhtmlDt.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/primitive/XhtmlDt.java
index 7f126d3f7cd..66b5ceada73 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/primitive/XhtmlDt.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/primitive/XhtmlDt.java
@@ -66,17 +66,18 @@ public class XhtmlDt extends BasePrimitive> {
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);
} catch (FactoryConfigurationError e) {
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/XmlParser.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/XmlParser.java
index 18381f3690a..01a7ce9947b 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/XmlParser.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/XmlParser.java
@@ -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());
+ }
+
+ encodeCompositeElementToStreamWriter(theResource, theEventWriter, resDef);
- eventWriter.writeEndElement();
+ theEventWriter.writeEndElement();
}
private void encodeUndeclaredExtensions(XMLStreamWriter theWriter, List extensions, String tagName) throws XMLStreamException {
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/CodingListParam.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/CodingListParam.java
index 200a06ae372..dd377575f76 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/CodingListParam.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/CodingListParam.java
@@ -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 {
private List myCodings = new ArrayList();
@@ -14,6 +15,9 @@ public class CodingListParam implements IQueryParameterOr {
* Returns all Codings associated with this list
*/
public List getCodings() {
+ if (myCodings == null) {
+ myCodings = new ArrayList();
+ }
return myCodings;
}
@@ -35,6 +39,7 @@ public class CodingListParam implements IQueryParameterOr {
@Override
public void setValuesAsQueryTokens(List 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 iterator() {
+ return getCodings().iterator();
+ }
+
}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/DateRangeParam.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/DateRangeParam.java
new file mode 100644
index 00000000000..b856ce05ba1
--- /dev/null
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/DateRangeParam.java
@@ -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> getValuesAsQueryTokens() {
+ ArrayList> retVal = new ArrayList>();
+ 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> theParameters) throws InvalidRequestException {
+ for (List 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();
+ }
+
+}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/QueryParameterAndBinder.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/QueryParameterAndBinder.java
new file mode 100644
index 00000000000..aa973fd7cf0
--- /dev/null
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/QueryParameterAndBinder.java
@@ -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> encode(Object theString) throws InternalErrorException {
+ List> retVal = ((IQueryParameterAnd) theString).getValuesAsQueryTokens();
+ return retVal;
+ }
+
+ @Override
+ public Object parse(List> 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;
+ }
+}
\ No newline at end of file
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/SearchParameter.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/SearchParameter.java
index d8a36fd2dc1..7fe6ab3219b 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/SearchParameter.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/SearchParameter.java
@@ -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)) {
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/RestfulServer.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/RestfulServer.java
index 88833a06627..7556775d070 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/RestfulServer.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/RestfulServer.java
@@ -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 params = new HashMap(request.getParameterMap());
EncodingUtil responseEncoding = determineResponseEncoding(request, params);
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/exceptions/ResourceNotFoundException.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/exceptions/ResourceNotFoundException.java
index c7ea30f8aa2..c508dc2d0d0 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/exceptions/ResourceNotFoundException.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/exceptions/ResourceNotFoundException.java
@@ -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;
}
diff --git a/hapi-fhir-base/src/test/java/ca/uhn/fhir/parser/JsonParserTest.java b/hapi-fhir-base/src/test/java/ca/uhn/fhir/parser/JsonParserTest.java
index dbdc2cb259b..cc22506eacd 100644
--- a/hapi-fhir-base/src/test/java/ca/uhn/fhir/parser/JsonParserTest.java
+++ b/hapi-fhir-base/src/test/java/ca/uhn/fhir/parser/JsonParserTest.java
@@ -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("AAA
"));
+ 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("")));
+
+ }
+
+ @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);
+ }
}
diff --git a/hapi-fhir-base/src/test/java/ca/uhn/fhir/parser/XmlParserTest.java b/hapi-fhir-base/src/test/java/ca/uhn/fhir/parser/XmlParserTest.java
index 06801f1e0d9..3350b98d798 100644
--- a/hapi-fhir-base/src/test/java/ca/uhn/fhir/parser/XmlParserTest.java
+++ b/hapi-fhir-base/src/test/java/ca/uhn/fhir/parser/XmlParserTest.java
@@ -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("AAA
"));
+ 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(""));
+ assertThat(str, IsNot.not(StringContains.containsString("")));
+
+ }
+
+
@Test
public void testParseBundle() {
diff --git a/hapi-fhir-base/src/test/java/ca/uhn/fhir/rest/client/ClientTest.java b/hapi-fhir-base/src/test/java/ca/uhn/fhir/rest/client/ClientTest.java
index 90106708d06..794e3744616 100644
--- a/hapi-fhir-base/src/test/java/ca/uhn/fhir/rest/client/ClientTest.java
+++ b/hapi-fhir-base/src/test/java/ca/uhn/fhir/rest/client/ClientTest.java
@@ -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 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 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 {
diff --git a/hapi-fhir-base/src/test/java/ca/uhn/fhir/rest/client/ITestClient.java b/hapi-fhir-base/src/test/java/ca/uhn/fhir/rest/client/ITestClient.java
index 88c749fba84..9c7f6657dd3 100644
--- a/hapi-fhir-base/src/test/java/ca/uhn/fhir/rest/client/ITestClient.java
+++ b/hapi-fhir-base/src/test/java/ca/uhn/fhir/rest/client/ITestClient.java
@@ -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 getPatientMultipleIdentifiers(@Required(name = "ids") CodingListParam theIdentifiers);
+ @Search()
+ public List getPatientByDateRange(@Required(name = "dateRange") DateRangeParam theIdentifiers);
+
@Search()
public List getPatientByDob(@Required(name=Patient.SP_BIRTHDATE) QualifiedDateParam theBirthDate);
diff --git a/hapi-fhir-base/src/test/java/ca/uhn/fhir/rest/server/ResfulServerMethodTest.java b/hapi-fhir-base/src/test/java/ca/uhn/fhir/rest/server/ResfulServerMethodTest.java
index 194007fa214..56bfb189119 100644
--- a/hapi-fhir-base/src/test/java/ca/uhn/fhir/rest/server/ResfulServerMethodTest.java
+++ b/hapi-fhir-base/src/test/java/ca/uhn/fhir/rest/server/ResfulServerMethodTest.java
@@ -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 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;
+ }
+
}
}
diff --git a/hapi-tinder-plugin/src/main/resources/vm/templates.vm b/hapi-tinder-plugin/src/main/resources/vm/templates.vm
index 25771f57864..059e182da7c 100644
--- a/hapi-tinder-plugin/src/main/resources/vm/templates.vm
+++ b/hapi-tinder-plugin/src/main/resources/vm/templates.vm
@@ -106,7 +106,21 @@
return newType;
}
#end
-
+#if( ${child.repeatable} && ${child.singleChildInstantiable} && ${child.resourceRef} )
+ /**
+ * Adds and returns a new value for ${child.elementName} (${child.shortName})
+ *
+ *
+ * Definition:
+ * ${child.definition}
+ *
+ */
+ 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 ${child.elementName} (${child.shortName})