Some unit test fixes, still some failures
This commit is contained in:
parent
2c425ca144
commit
79bdd94f72
|
@ -27,6 +27,9 @@ public class FhirContext {
|
|||
this(toCollection(theResourceType));
|
||||
}
|
||||
|
||||
public FhirContext() {
|
||||
}
|
||||
|
||||
public FhirContext(Class<?>... theResourceTypes) {
|
||||
this(toCollection(theResourceTypes));
|
||||
}
|
||||
|
|
|
@ -1,14 +1,45 @@
|
|||
package ca.uhn.fhir.model.api;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
|
||||
import org.apache.commons.lang3.time.DateUtils;
|
||||
|
||||
public enum TemporalPrecisionEnum {
|
||||
|
||||
YEAR(Calendar.YEAR),
|
||||
MONTH(Calendar.MONTH),
|
||||
DAY(Calendar.DATE),
|
||||
SECOND(Calendar.SECOND),
|
||||
MILLI(Calendar.MILLISECOND),
|
||||
YEAR(Calendar.YEAR) {
|
||||
@Override
|
||||
public Date add(Date theInput, int theAmount) {
|
||||
return DateUtils.addYears(theInput, theAmount);
|
||||
}
|
||||
},
|
||||
|
||||
MONTH(Calendar.MONTH) {
|
||||
@Override
|
||||
public Date add(Date theInput, int theAmount) {
|
||||
return DateUtils.addMonths(theInput, theAmount);
|
||||
}
|
||||
},
|
||||
DAY(Calendar.DATE) {
|
||||
@Override
|
||||
public Date add(Date theInput, int theAmount) {
|
||||
return DateUtils.addDays(theInput, theAmount);
|
||||
}
|
||||
},
|
||||
SECOND(Calendar.SECOND) {
|
||||
@Override
|
||||
public Date add(Date theInput, int theAmount) {
|
||||
return DateUtils.addSeconds(theInput, theAmount);
|
||||
}
|
||||
},
|
||||
|
||||
MILLI(Calendar.MILLISECOND) {
|
||||
@Override
|
||||
public Date add(Date theInput, int theAmount) {
|
||||
return DateUtils.addMilliseconds(theInput, theAmount);
|
||||
}
|
||||
},
|
||||
|
||||
;
|
||||
|
||||
private int myCalendarConstant;
|
||||
|
@ -17,7 +48,10 @@ public enum TemporalPrecisionEnum {
|
|||
myCalendarConstant = theCalendarConstant;
|
||||
}
|
||||
|
||||
public abstract Date add(Date theInput, int theAmount);
|
||||
|
||||
public int getCalendarConstant() {
|
||||
return myCalendarConstant;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ public abstract class BaseParser implements IParser {
|
|||
public IResource parseResource(Reader theReader) throws ConfigurationException, DataFormatException {
|
||||
return parseResource(null, theReader);
|
||||
}
|
||||
|
||||
public void containResourcesForEncoding(IResource theResource) {
|
||||
List<ResourceReferenceDt> allElements = theResource.getAllPopulatedChildElementsOfType(ResourceReferenceDt.class);
|
||||
|
||||
|
@ -46,7 +47,7 @@ public abstract class BaseParser implements IParser {
|
|||
theResource.getContained().getContainedResources().add(resource);
|
||||
allIds.add(resource.getId().getValue());
|
||||
}
|
||||
|
||||
|
||||
next.setReference("#" + resource.getId().getValue());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ public interface IParser {
|
|||
|
||||
<T extends IResource> T parseResource(Class<T> theResourceType, String theMessageString);
|
||||
|
||||
IResource parseResource(Class<? extends IResource> theResourceType, Reader theReader);
|
||||
<T extends IResource> T parseResource(Class<T> theResourceType, Reader theReader);
|
||||
|
||||
IParser setPrettyPrint(boolean thePrettyPrint);
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import static org.apache.commons.lang3.StringUtils.*;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.util.ArrayList;
|
||||
|
@ -65,21 +66,6 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
return stringWriter.toString();
|
||||
}
|
||||
|
||||
private void writeTagWithTextNode(JsonGenerator theEventWriter, String theElementName, StringDt theStringDt) {
|
||||
if (StringUtils.isNotBlank(theStringDt.getValue())) {
|
||||
theEventWriter.write(theElementName, theStringDt.getValue());
|
||||
} else {
|
||||
theEventWriter.writeNull(theElementName);
|
||||
}
|
||||
}
|
||||
|
||||
private void writeOptionalTagWithTextNode(JsonGenerator theEventWriter, String theElementName, IPrimitiveDatatype<?> theInstantDt) {
|
||||
String str = theInstantDt.getValueAsString();
|
||||
if (StringUtils.isNotBlank(str)) {
|
||||
theEventWriter.write(theElementName, theInstantDt.getValueAsString());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void encodeBundleToWriter(Bundle theBundle, Writer theWriter) throws IOException {
|
||||
JsonGenerator eventWriter = createJsonGenerator(theWriter);
|
||||
|
@ -132,26 +118,6 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
eventWriter.close();
|
||||
}
|
||||
|
||||
private void writeAuthor(BaseBundle theBundle, JsonGenerator eventWriter) {
|
||||
if (StringUtils.isNotBlank(theBundle.getAuthorName().getValue())) {
|
||||
eventWriter.writeStartArray("author");
|
||||
eventWriter.writeStartObject();
|
||||
writeTagWithTextNode(eventWriter, "name", theBundle.getAuthorName());
|
||||
writeOptionalTagWithTextNode(eventWriter, "uri", theBundle.getAuthorUri());
|
||||
eventWriter.writeEnd();
|
||||
eventWriter.writeEnd();
|
||||
}
|
||||
}
|
||||
|
||||
private void writeAtomLink(JsonGenerator theEventWriter, String theRel, StringDt theLink) {
|
||||
if (isNotBlank(theLink.getValue())) {
|
||||
theEventWriter.writeStartObject();
|
||||
theEventWriter.write("rel", theRel);
|
||||
theEventWriter.write("href", theLink.getValue());
|
||||
theEventWriter.writeEnd();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String encodeResourceToString(IResource theResource) throws DataFormatException, IOException {
|
||||
Writer stringWriter = new StringWriter();
|
||||
|
@ -172,16 +138,6 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
// }
|
||||
}
|
||||
|
||||
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 Bundle parseBundle(Reader theReader) {
|
||||
// TODO Auto-generated method stub
|
||||
|
@ -195,24 +151,29 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
}
|
||||
|
||||
@Override
|
||||
public IResource parseResource(Class<? extends IResource> theResourceType, Reader theReader) {
|
||||
public <T extends IResource> T parseResource(Class<T> theResourceType, String theMessageString) {
|
||||
return parseResource(theResourceType, new StringReader(theMessageString));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends IResource> T parseResource(Class<T> theResourceType, Reader theReader) {
|
||||
JsonReader reader = Json.createReader(theReader);
|
||||
JsonObject object = reader.readObject();
|
||||
|
||||
JsonValue resourceTypeObj = object.remove("resourceType");
|
||||
|
||||
JsonValue resourceTypeObj = object.get("resourceType");
|
||||
assertObjectOfType(resourceTypeObj, JsonValue.ValueType.STRING, "resourceType");
|
||||
String resourceType = ((JsonString)resourceTypeObj).getString();
|
||||
|
||||
String resourceType = ((JsonString) resourceTypeObj).getString();
|
||||
|
||||
if (theResourceType != null) {
|
||||
RuntimeResourceDefinition def = myContext.getResourceDefinition(theResourceType);
|
||||
}else {
|
||||
} else {
|
||||
RuntimeResourceDefinition def = myContext.getResourceDefinition(resourceType);
|
||||
}
|
||||
|
||||
|
||||
PushbackJsonParser parser = new PushbackJsonParser(Json.createParser(theReader));
|
||||
|
||||
|
||||
while (parser.hasNext()) {
|
||||
|
||||
|
||||
Event next = parser.next();
|
||||
switch (next) {
|
||||
case END_ARRAY:
|
||||
|
@ -236,28 +197,14 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void assertObjectOfType(JsonValue theResourceTypeObj, ValueType theValueType, String thePosition) {
|
||||
if (theResourceTypeObj.getValueType() != theValueType) {
|
||||
throw new DataFormatException("Invalid content of element " + thePosition + ", expected " + theValueType);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends IResource> T parseResource(Class<T> theResourceType, String theMessageString) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public IParser setPrettyPrint(boolean thePrettyPrint) {
|
||||
myPrettyPrint = thePrettyPrint;
|
||||
|
@ -279,6 +226,22 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
}
|
||||
}
|
||||
|
||||
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(JsonGenerator theWriter, IElement theValue, BaseRuntimeElementDefinition<?> theChildDef, String theChildName) throws IOException {
|
||||
|
||||
switch (theChildDef.getChildType()) {
|
||||
|
@ -318,7 +281,7 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
if (theChildName != null) {
|
||||
theWriter.writeStartObject(theChildName);
|
||||
} else {
|
||||
theWriter.flush();//TODO: remove
|
||||
theWriter.flush();// TODO: remove
|
||||
theWriter.writeStartObject();
|
||||
}
|
||||
encodeCompositeElementToStreamWriter(theValue, theWriter, childCompositeDef);
|
||||
|
@ -424,7 +387,7 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
}
|
||||
currentChildName = childName;
|
||||
} else {
|
||||
theEventWriter.flush();//TODO: remove
|
||||
theEventWriter.flush();// TODO: remove
|
||||
encodeChildElementToStreamWriter(theEventWriter, nextValue, childDef, null);
|
||||
}
|
||||
|
||||
|
@ -462,7 +425,7 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
}
|
||||
|
||||
if (!haveContent) {
|
||||
// theEventWriter.writeEnd();
|
||||
// theEventWriter.writeEnd();
|
||||
theEventWriter.flush(); // TODO: remove
|
||||
theEventWriter.writeNull();
|
||||
}
|
||||
|
@ -520,7 +483,7 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
}
|
||||
|
||||
theEventWriter.write("resourceType", resDef.getName());
|
||||
if (theResource.getId() !=null && isNotBlank(theResource.getId().getValue())) {
|
||||
if (theResource.getId() != null && isNotBlank(theResource.getId().getValue())) {
|
||||
theEventWriter.write("id", theResource.getId().getValue());
|
||||
}
|
||||
|
||||
|
@ -559,6 +522,41 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
theWriter.writeEnd();
|
||||
}
|
||||
|
||||
private void writeAtomLink(JsonGenerator theEventWriter, String theRel, StringDt theLink) {
|
||||
if (isNotBlank(theLink.getValue())) {
|
||||
theEventWriter.writeStartObject();
|
||||
theEventWriter.write("rel", theRel);
|
||||
theEventWriter.write("href", theLink.getValue());
|
||||
theEventWriter.writeEnd();
|
||||
}
|
||||
}
|
||||
|
||||
private void writeAuthor(BaseBundle theBundle, JsonGenerator eventWriter) {
|
||||
if (StringUtils.isNotBlank(theBundle.getAuthorName().getValue())) {
|
||||
eventWriter.writeStartArray("author");
|
||||
eventWriter.writeStartObject();
|
||||
writeTagWithTextNode(eventWriter, "name", theBundle.getAuthorName());
|
||||
writeOptionalTagWithTextNode(eventWriter, "uri", theBundle.getAuthorUri());
|
||||
eventWriter.writeEnd();
|
||||
eventWriter.writeEnd();
|
||||
}
|
||||
}
|
||||
|
||||
private void writeOptionalTagWithTextNode(JsonGenerator theEventWriter, String theElementName, IPrimitiveDatatype<?> theInstantDt) {
|
||||
String str = theInstantDt.getValueAsString();
|
||||
if (StringUtils.isNotBlank(str)) {
|
||||
theEventWriter.write(theElementName, theInstantDt.getValueAsString());
|
||||
}
|
||||
}
|
||||
|
||||
private void writeTagWithTextNode(JsonGenerator theEventWriter, String theElementName, StringDt theStringDt) {
|
||||
if (StringUtils.isNotBlank(theStringDt.getValue())) {
|
||||
theEventWriter.write(theElementName, theStringDt.getValue());
|
||||
} else {
|
||||
theEventWriter.writeNull(theElementName);
|
||||
}
|
||||
}
|
||||
|
||||
private class HeldExtension {
|
||||
|
||||
private UndeclaredExtension myUndeclaredExtension;
|
||||
|
|
|
@ -115,8 +115,8 @@ class ParserState<T extends IElement> {
|
|||
* @param theResourceType
|
||||
* May be null
|
||||
*/
|
||||
public static ParserState<IResource> getPreResourceInstance(Class<? extends IResource> theResourceType, FhirContext theContext) throws DataFormatException {
|
||||
ParserState<IResource> retVal = new ParserState<IResource>(theContext);
|
||||
public static <T extends IResource> ParserState<T> getPreResourceInstance(Class<T> theResourceType, FhirContext theContext) throws DataFormatException {
|
||||
ParserState<T> retVal = new ParserState<T>(theContext);
|
||||
retVal.push(retVal.new PreResourceState(theResourceType));
|
||||
return retVal;
|
||||
}
|
||||
|
|
|
@ -138,6 +138,10 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
|
||||
@Override
|
||||
public String encodeResourceToString(IResource theResource) throws DataFormatException {
|
||||
if (theResource==null) {
|
||||
throw new NullPointerException("Resource can not be null");
|
||||
}
|
||||
|
||||
Writer stringWriter = new StringWriter();
|
||||
encodeResourceToWriter(theResource, stringWriter);
|
||||
return stringWriter.toString();
|
||||
|
@ -183,7 +187,7 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
}
|
||||
|
||||
@Override
|
||||
public IResource parseResource(Class<? extends IResource> theResourceType, Reader theReader) {
|
||||
public <T extends IResource> T parseResource(Class<T> theResourceType, Reader theReader) {
|
||||
XMLEventReader streamReader;
|
||||
try {
|
||||
streamReader = myXmlInputFactory.createXMLEventReader(theReader);
|
||||
|
@ -545,8 +549,8 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
return doXmlLoop(theStreamReader, parserState);
|
||||
}
|
||||
|
||||
private IResource parseResource(Class<? extends IResource> theResourceType, XMLEventReader theStreamReader) {
|
||||
ParserState<IResource> parserState = ParserState.getPreResourceInstance(theResourceType, myContext);
|
||||
private <T extends IResource> T parseResource(Class<T> theResourceType, XMLEventReader theStreamReader) {
|
||||
ParserState<T> parserState = ParserState.getPreResourceInstance(theResourceType, myContext);
|
||||
return doXmlLoop(theStreamReader, parserState);
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import java.util.Date;
|
|||
import java.util.List;
|
||||
|
||||
import ca.uhn.fhir.model.api.IQueryParameterAnd;
|
||||
import ca.uhn.fhir.model.dstu.valueset.QuantityCompararatorEnum;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
|
||||
public class DateRangeParam implements IQueryParameterAnd {
|
||||
|
@ -91,13 +92,39 @@ public class DateRangeParam implements IQueryParameterAnd {
|
|||
}
|
||||
|
||||
public Date getLowerBoundAsInstant() {
|
||||
// TODO: account for precision
|
||||
return myLowerBound.getValue();
|
||||
Date retVal = myLowerBound.getValue();
|
||||
if (myLowerBound.getComparator() != null) {
|
||||
switch (myLowerBound.getComparator()) {
|
||||
case GREATERTHAN:
|
||||
retVal = myLowerBound.getPrecision().add(retVal, 1);
|
||||
break;
|
||||
case GREATERTHAN_OR_EQUALS:
|
||||
break;
|
||||
case LESSTHAN:
|
||||
case LESSTHAN_OR_EQUALS:
|
||||
throw new IllegalStateException("Unvalid lower bound comparator: " + myLowerBound.getComparator());
|
||||
}
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public Date getUpperBoundAsInstant() {
|
||||
// TODO: account for precision
|
||||
return myUpperBound.getValue();
|
||||
Date retVal = myUpperBound.getValue();
|
||||
if (myUpperBound.getComparator() != null) {
|
||||
switch (myUpperBound.getComparator()) {
|
||||
case LESSTHAN:
|
||||
retVal = new Date(retVal.getTime() - 1L);
|
||||
break;
|
||||
case LESSTHAN_OR_EQUALS:
|
||||
retVal = myUpperBound.getPrecision().add(retVal, 1);
|
||||
retVal = new Date(retVal.getTime() - 1L);
|
||||
break;
|
||||
case GREATERTHAN_OR_EQUALS:
|
||||
case GREATERTHAN:
|
||||
throw new IllegalStateException("Unvalid upper bound comparator: " + myUpperBound.getComparator());
|
||||
}
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -17,12 +17,7 @@ public class FhirContextIntro {
|
|||
|
||||
public static void creatingContext() {
|
||||
// START SNIPPET: creatingContext
|
||||
/*
|
||||
* Create a FhirContex instance which is able to parse and encode
|
||||
* the Patient and Observation resources, and any resources referenced
|
||||
* from these.
|
||||
*/
|
||||
FhirContext ctx = new FhirContext(Patient.class, Observation.class);
|
||||
FhirContext ctx = new FhirContext();
|
||||
// END SNIPPET: creatingContext
|
||||
|
||||
}
|
||||
|
@ -103,7 +98,7 @@ StringDt familyName = patient.getName().get(0).getFamily().get(0);
|
|||
CodeDt gender = patient.getGender().getCoding().get(0).getCode();
|
||||
|
||||
/*
|
||||
* The
|
||||
* The various datatype classes have accessors called getValue()
|
||||
*/
|
||||
System.out.println(patientId.getValue()); // PRP1660
|
||||
System.out.println(familyName.getValue()); // Cardinal
|
||||
|
|
|
@ -24,6 +24,7 @@ import ca.uhn.fhir.rest.annotation.Required;
|
|||
import ca.uhn.fhir.rest.annotation.Search;
|
||||
import ca.uhn.fhir.rest.client.ITestClient;
|
||||
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.IResourceProvider;
|
||||
|
||||
|
@ -161,6 +162,22 @@ public List<DiagnosticReport> getDiagnosticReport( @Required(name=DiagnosticRepo
|
|||
}
|
||||
//END SNIPPET: pathSpec
|
||||
|
||||
//START SNIPPET: dateRange
|
||||
@Search()
|
||||
public List<Observation> getObservationsByDateRange(@Required(name="subject.identifier") IdentifierDt theSubjectId,
|
||||
@Required(name=Observation.SP_DATE) DateRangeParam theRange) {
|
||||
List<Observation> retVal = new ArrayList<Observation>();
|
||||
|
||||
// The following two will be set as the start and end
|
||||
// of the range specified by the query parameter
|
||||
Date from = theRange.getLowerBoundAsInstant();
|
||||
Date to = theRange.getUpperBoundAsInstant();
|
||||
|
||||
// ... populate ...
|
||||
return retVal;
|
||||
}
|
||||
//END SNIPPET: dateRange
|
||||
|
||||
private DiagnosticReport loadSomeDiagnosticReportFromDatabase(IdentifierDt theIdentifier) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -159,15 +159,15 @@
|
|||
may be optional. To add a second required parameter, annotate the
|
||||
parameter with
|
||||
<a href="./apidocs/ca/uhn/fhir/rest/server/parameters/Required.html">@Required</a>.
|
||||
To add an optional parameter (which will be pased in as <code>null</code> if no value
|
||||
To add an optional parameter (which will be passed in as <code>null</code> if no value
|
||||
is supplied), annotate the method with
|
||||
<a href="./apidocs/ca/uhn/fhir/rest/server/parameters/Required.html">@Optional</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
You may annotate a method with any combination of as many @Required and as many @Optional
|
||||
parameters as you want. It is valid to have no @Required parameters, or
|
||||
no @Optional parameters as well.
|
||||
parameters as you want. It is valid to have only @Required parameters, or
|
||||
only @Optional parameters, or any combination of the two.
|
||||
</p>
|
||||
|
||||
<macro name="snippet">
|
||||
|
@ -230,7 +230,7 @@
|
|||
|
||||
</subsection>
|
||||
|
||||
<subsection name="Date Parameters">
|
||||
<subsection name="Date Parameters - Simple">
|
||||
|
||||
<p>
|
||||
The FHIR specification provides a sytax for specifying
|
||||
|
@ -270,6 +270,46 @@
|
|||
|
||||
</subsection>
|
||||
|
||||
<subsection name="Date Parameters - Ranges">
|
||||
|
||||
<p>
|
||||
A common scenario in searches is to allow searching for resources
|
||||
with values (i.e timestamps) within a range of dates.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
FHIR allows for multiple parameters with the same key, and interprets
|
||||
these as being an "AND" set. So, for example, a range of<br/>
|
||||
<code>DATE >= 2011-01-01</code> and <code>DATE < 2011-02-01</code><br/>
|
||||
can be interpreted as any date within January 2011.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The following snippet shows how to accept such a range, and combines it
|
||||
with a specific identifier, which is a common scenario. (i.e. Give me a list
|
||||
of observations for a specific patient within a given date range)
|
||||
</p>
|
||||
<macro name="snippet">
|
||||
<param name="id" value="dateRange" />
|
||||
<param name="file" value="src/site/example/java/example/RestfulPatientResourceProviderMore.java" />
|
||||
</macro>
|
||||
|
||||
<p>
|
||||
Example URL to invoke this method:<br/>
|
||||
<code>http://fhir.example.com/Observation?subject.identifier=7000135&date=>=2011-01-01&date=<2011-02-01</code>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Invoking a client of thie type involves the following syntax:
|
||||
</p>
|
||||
|
||||
<macro name="snippet">
|
||||
<param name="id" value="dateClient" />
|
||||
<param name="file" value="src/site/example/java/example/RestfulPatientResourceProviderMore.java" />
|
||||
</macro>
|
||||
|
||||
</subsection>
|
||||
|
||||
<subsection name="Resource Includes (_include)">
|
||||
|
||||
<p>
|
||||
|
|
|
@ -80,17 +80,19 @@ public class JsonParserTest {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleParse() throws DataFormatException, IOException {
|
||||
|
||||
String msg = IOUtils.toString(XmlParser.class.getResourceAsStream("/example-patient-general.json"));
|
||||
FhirContext ctx = new FhirContext(Patient.class);
|
||||
IParser p = ctx.newJsonParser();
|
||||
ourLog.info("Reading in message: {}", msg);
|
||||
Patient res = p.parseResource(Patient.class, msg);
|
||||
|
||||
String encoded = ctx.newXmlParser().setPrettyPrint(true).encodeResourceToString(res);
|
||||
ourLog.info(encoded);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEncodeContainedResourcesMore() throws IOException {
|
||||
|
|
|
@ -82,7 +82,7 @@ public class XmlParserTest {
|
|||
String str = p.encodeResourceToString(rpt);
|
||||
|
||||
ourLog.info(str);
|
||||
assertThat(str, StringContains.containsString("<div>AAA</div>"));
|
||||
assertThat(str, StringContains.containsString("<div xmlns=\"\">AAA</div>"));
|
||||
assertThat(str, StringContains.containsString("reference value=\"#"));
|
||||
|
||||
int idx = str.indexOf("reference value=\"#") + "reference value=\"#".length();
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
package ca.uhn.fhir.rest.param;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
|
||||
public class DateRangeParamTest {
|
||||
|
||||
private static SimpleDateFormat ourFmt;
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() {
|
||||
ourFmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSS");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testYear() throws Exception {
|
||||
assertEquals(parse("2011-01-01 00:00:00.0000"), create(">=2011", "<2012").getLowerBoundAsInstant());
|
||||
assertEquals(parseM1("2012-01-01 00:00:00.0000"), create(">=2011", "<2012").getUpperBoundAsInstant());
|
||||
|
||||
assertEquals(parse("2012-01-01 00:00:00.0000"), create(">2011", "<=2012").getLowerBoundAsInstant());
|
||||
assertEquals(parseM1("2014-01-01 00:00:00.0000"), create(">2011", "<=2013").getUpperBoundAsInstant());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMonth() throws Exception {
|
||||
assertEquals(parse("2011-01-01 00:00:00.0000"), create(">=2011-01", "<2011-02").getLowerBoundAsInstant());
|
||||
assertEquals(parseM1("2011-02-01 00:00:00.0000"), create(">=2011-01", "<2011-02").getUpperBoundAsInstant());
|
||||
|
||||
assertEquals(parse("2011-02-01 00:00:00.0000"), create(">2011-01", "<=2011-02").getLowerBoundAsInstant());
|
||||
assertEquals(parseM1("2011-03-01 00:00:00.0000"), create(">2011-01", "<=2011-02").getUpperBoundAsInstant());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDay() throws Exception {
|
||||
assertEquals(parse("2011-01-01 00:00:00.0000"), create(">=2011-01-01", "<2011-01-02").getLowerBoundAsInstant());
|
||||
assertEquals(parseM1("2011-01-02 00:00:00.0000"), create(">=2011-01-01", "<2011-01-02").getUpperBoundAsInstant());
|
||||
|
||||
assertEquals(parse("2011-01-02 00:00:00.0000"), create(">2011-01-01", "<=2011-01-02").getLowerBoundAsInstant());
|
||||
assertEquals(parseM1("2011-01-03 00:00:00.0000"), create(">2011-01-01", "<=2011-01-02").getUpperBoundAsInstant());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSecond() throws Exception {
|
||||
assertEquals(parse("2011-01-01 00:00:00.0000"), create(">=2011-01-01T00:00:00", "<2011-01-01T01:00:00").getLowerBoundAsInstant());
|
||||
assertEquals(parseM1("2011-01-01 02:00:00.0000"), create(">=2011-01-01T00:00:00", "<2011-01-01T02:00:00").getUpperBoundAsInstant());
|
||||
|
||||
assertEquals(parse("2011-01-01 00:00:01.0000"), create(">2011-01-01T00:00:00", "<=2011-01-01T02:00:00").getLowerBoundAsInstant());
|
||||
assertEquals(parseM1("2011-01-01 02:00:01.0000"), create(">2011-01-01T00:00:00", "<=2011-01-01T02:00:00").getUpperBoundAsInstant());
|
||||
}
|
||||
|
||||
private Date parse(String theString) throws ParseException {
|
||||
return ourFmt.parse(theString);
|
||||
}
|
||||
|
||||
private Date parseM1(String theString) throws ParseException {
|
||||
return new Date(ourFmt.parse(theString).getTime() - 1L);
|
||||
}
|
||||
|
||||
private Date parseP1(String theString) throws ParseException {
|
||||
return new Date(ourFmt.parse(theString).getTime() + 1L);
|
||||
}
|
||||
|
||||
|
||||
private static DateRangeParam create(String theLower, String theUpper) throws InvalidRequestException {
|
||||
DateRangeParam p = new DateRangeParam();
|
||||
List<List<String>> tokens=new ArrayList<List<String>>();
|
||||
tokens.add(Collections.singletonList(theLower));
|
||||
tokens.add(Collections.singletonList(theUpper));
|
||||
p.setValuesAsQueryTokens(tokens);
|
||||
return p;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue