diff --git a/hapi-fhir-base/src/changes/changes.xml b/hapi-fhir-base/src/changes/changes.xml
index fcbbfb29031..4861d6929e0 100644
--- a/hapi-fhir-base/src/changes/changes.xml
+++ b/hapi-fhir-base/src/changes/changes.xml
@@ -49,7 +49,7 @@
Transaction server method is now allowed to return an OperationOutcome in addition to the
- incoming resources. The public test server now does this in ordeer to return status information
+ incoming resources. The public test server now does this in order to return status information
about the transaction processing.
@@ -67,6 +67,11 @@
Added narrative generator template for OperationOutcome resource
+
+ Date/time types did not correctly parse values in the format "yyyymmdd" (although the FHIR-defined format
+ is "yyyy-mm-dd" anyhow, and this is correctly handled). Thanks to Jeffrey Ting of Systems Made Simple
+ for reporting!
+
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/BaseRuntimeElementCompositeDefinition.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/BaseRuntimeElementCompositeDefinition.java
index 5bc4ba0549b..b3989eab7ac 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/BaseRuntimeElementCompositeDefinition.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/BaseRuntimeElementCompositeDefinition.java
@@ -34,6 +34,7 @@ import ca.uhn.fhir.parser.DataFormatException;
public abstract class BaseRuntimeElementCompositeDefinition extends BaseRuntimeElementDefinition {
private List myChildren = new ArrayList();
+ private List myChildrenAndExtensions;
private Map myNameToChild = new HashMap();
public BaseRuntimeElementCompositeDefinition(String theName, Class extends T> theImplementingClass) {
@@ -65,6 +66,10 @@ public abstract class BaseRuntimeElementCompositeDefinition getChildrenAndExtension() {
+ return myChildrenAndExtensions;
+ }
+
@Override
public void sealAndInitialize(Map, BaseRuntimeElementDefinition>> theClassToElementDefinitions) {
super.sealAndInitialize(theClassToElementDefinitions);
@@ -90,5 +95,12 @@ public abstract class BaseRuntimeElementCompositeDefinition children = new ArrayList();
+ children.addAll(myChildren);
+ children.addAll(getExtensionsModifier());
+ children.addAll(getExtensionsNonModifier());
+ myChildrenAndExtensions=Collections.unmodifiableList(children);
}
+
}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/FhirContext.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/FhirContext.java
index 44feecb337f..77b1195324e 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/FhirContext.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/FhirContext.java
@@ -179,7 +179,7 @@ public class FhirContext {
* Create and return a new JSON parser.
*
*
- * Performance Note: This class is cheap to create, and may be called once for every message being processed without incurring any performance penalty
+ * Performance Note: This method is cheap to call, and may be called once for every message being processed without incurring any performance penalty
*
*/
public IParser newJsonParser() {
@@ -192,7 +192,7 @@ public class FhirContext {
* href="http://hl7api.sourceforge.net/hapi-fhir/doc_rest_client.html">RESTful Client documentation for more information on how to define this interface.
*
*
- * Performance Note: This class is cheap to create, and may be called once for every message being processed without incurring any performance penalty
+ * Performance Note: This method is cheap to call, and may be called once for every operation invocation without incurring any performance penalty
*
*
* @param theClientType
@@ -210,8 +210,9 @@ public class FhirContext {
/**
* Instantiates a new generic client. A generic client is able to perform any of the FHIR RESTful operations against a compliant server, but does not have methods defining the specific
* functionality required (as is the case with {@link #newRestfulClient(Class, String) non-generic clients}).
+ *
*
- * In most cases it is preferable to use the non-generic clients instead of this mechanism, but not always.
+ * Performance Note: This method is cheap to call, and may be called once for every operation invocation without incurring any performance penalty
*
*
* @param theServerBase
@@ -227,10 +228,10 @@ public class FhirContext {
}
/**
- * Create and return a new JSON parser.
+ * Create and return a new XML parser.
*
*
- * Performance Note: This class is cheap to create, and may be called once for every message being processed without incurring any performance penalty
+ * Performance Note: This method is cheap to call, and may be called once for every message being processed without incurring any performance penalty
*
*/
public IParser newXmlParser() {
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/Bundle.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/Bundle.java
index 02f8a7e5e58..4f242e019c3 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/Bundle.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/api/Bundle.java
@@ -37,8 +37,6 @@ import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.InstantDt;
import ca.uhn.fhir.model.primitive.IntegerDt;
import ca.uhn.fhir.model.primitive.StringDt;
-import ca.uhn.fhir.rest.client.IGenericClient;
-import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor;
import ca.uhn.fhir.rest.server.Constants;
public class Bundle extends BaseBundle /* implements IElement */{
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/primitive/BaseDateTimeDt.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/primitive/BaseDateTimeDt.java
index 52879b03b1d..8d3dae77db3 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/primitive/BaseDateTimeDt.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/primitive/BaseDateTimeDt.java
@@ -31,6 +31,7 @@ import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.TimeZone;
+import java.util.regex.Pattern;
import javax.xml.bind.DatatypeConverter;
@@ -165,13 +166,19 @@ public abstract class BaseDateTimeDt extends BasePrimitive {
myValue = theValue;
}
+ private Pattern ourYearPattern = Pattern.compile("[0-9]{4}");
+ private Pattern ourYearDashMonthPattern = Pattern.compile("[0-9]{4}-[0-9]{2}");
+ private Pattern ourYearDashMonthDashDayPattern = Pattern.compile("[0-9]{4}-[0-9]{2}-[0-9]{2}");
+ private Pattern ourYearMonthPattern = Pattern.compile("[0-9]{4}[0-9]{2}");
+ private Pattern ourYearMonthDayPattern = Pattern.compile("[0-9]{4}[0-9]{2}[0-9]{2}");
+
@Override
public void setValueAsString(String theValue) throws DataFormatException {
try {
if (theValue == null) {
myValue = null;
clearTimeZone();
- } else if (theValue.length() == 4) {
+ } else if (theValue.length() == 4 && ourYearPattern.matcher(theValue).matches()) {
if (isPrecisionAllowed(YEAR)) {
setValue((ourYearFormat).parse(theValue));
setPrecision(YEAR);
@@ -179,7 +186,7 @@ public abstract class BaseDateTimeDt extends BasePrimitive {
} else {
throw new DataFormatException("Invalid date/time string (datatype " + getClass().getSimpleName() + " does not support YEAR precision): " + theValue);
}
- } else if (theValue.length() == 7) {
+ } else if (theValue.length() == 7 && ourYearDashMonthPattern.matcher(theValue).matches()) {
// E.g. 1984-01 (this is valid according to the spec)
if (isPrecisionAllowed(MONTH)) {
setValue((ourYearMonthFormat).parse(theValue));
@@ -188,16 +195,16 @@ public abstract class BaseDateTimeDt extends BasePrimitive {
} else {
throw new DataFormatException("Invalid date/time string (datatype " + getClass().getSimpleName() + " does not support MONTH precision): " + theValue);
}
- } else if (theValue.length() == 8) {
+ } else if (theValue.length() == 8 && ourYearMonthDayPattern.matcher(theValue).matches()) {
//Eg. 19840101 (allow this just to be lenient)
if (isPrecisionAllowed(DAY)) {
setValue((ourYearMonthDayNoDashesFormat).parse(theValue));
- setPrecision(MONTH);
+ setPrecision(DAY);
clearTimeZone();
} else {
throw new DataFormatException("Invalid date/time string (datatype " + getClass().getSimpleName() + " does not support DAY precision): " + theValue);
}
- } else if (theValue.length() == 10) {
+ } else if (theValue.length() == 10 && ourYearDashMonthDashDayPattern.matcher(theValue).matches()) {
// E.g. 1984-01-01 (this is valid according to the spec)
if (isPrecisionAllowed(DAY)) {
setValue((ourYearMonthDayFormat).parse(theValue));
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/IParser.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/IParser.java
index 6141959bbd4..be5e36577b7 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/IParser.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/IParser.java
@@ -74,7 +74,7 @@ public interface IParser {
* specify a class which extends a built-in type (e.g. a custom
* type extending the default Patient class)
* @param theReader
- * The reader to parse inpou from
+ * The reader to parse input from. Note that the Reader will not be closed by the parser upon completion.
* @return A parsed resource
* @throws DataFormatException
* If the resource can not be parsed because the data is not
@@ -98,8 +98,28 @@ public interface IParser {
*/
T parseResource(Class theResourceType, String theString) throws DataFormatException;
+ /**
+ * Parses a resource
+ *
+ * @param theReader
+ * The reader to parse input from. Note that the Reader will not be closed by the parser upon completion.
+ * @return A parsed resource
+ * @throws DataFormatException
+ * If the resource can not be parsed because the data is not
+ * recognized or invalid for any reason
+ */
IResource parseResource(Reader theReader) throws ConfigurationException, DataFormatException;
+ /**
+ * Parses a resource
+ *
+ * @param theString
+ * The string to parse
+ * @return A parsed resource
+ * @throws DataFormatException
+ * If the resource can not be parsed because the data is not
+ * recognized or invalid for any reason
+ */
IResource parseResource(String theMessageString) throws ConfigurationException, DataFormatException;
/**
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/BaseParam.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/BaseParam.java
new file mode 100644
index 00000000000..55e33b8ac51
--- /dev/null
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/BaseParam.java
@@ -0,0 +1,59 @@
+package ca.uhn.fhir.rest.param;
+
+import ca.uhn.fhir.model.api.IQueryParameterType;
+import ca.uhn.fhir.rest.server.Constants;
+
+/**
+ * Base class for RESTful operation parameter types
+ */
+public class BaseParam implements IQueryParameterType {
+
+ private Boolean myMissing;
+
+ /**
+ * If set to non-null value, indicates that this parameter has been populated with a "[name]:missing=true" or "[name]:missing=false" vale
+ * instead of a normal value
+ */
+ public Boolean getMissing() {
+ return myMissing;
+ }
+
+
+
+ @Override
+ public String getQueryParameterQualifier() {
+ if (myMissing) {
+ return Constants.PARAMQUALIFIER_MISSING;
+ }
+ return null;
+ }
+
+
+ @Override
+ public String getValueAsQueryToken() {
+ if (myMissing != null) {
+ return myMissing ? "true" : "false";
+ }
+ return null;
+ }
+
+
+
+ /**
+ * If set to non-null value, indicates that this parameter has been populated with a "[name]:missing=true" or "[name]:missing=false" vale
+ * instead of a normal value
+ */
+ public void setMissing(Boolean theMissing) {
+ myMissing = theMissing;
+ }
+
+ @Override
+ public void setValueAsQueryToken(String theQualifier, String theValue) {
+ if (Constants.PARAMQUALIFIER_MISSING.equals(theQualifier)) {
+ myMissing = "true".equals(theValue);
+ } else {
+ myMissing = null;
+ }
+ }
+
+}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/DateParam.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/DateParam.java
index 90e7c44a206..a192772c2c0 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/DateParam.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/DateParam.java
@@ -36,6 +36,7 @@ import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
public class DateParam extends DateTimeDt implements IQueryParameterType, IQueryParameterOr {
private QuantityCompararatorEnum myComparator;
+ private BaseParam myBase=new BaseParam();
/**
* Constructor
@@ -78,11 +79,17 @@ public class DateParam extends DateTimeDt implements IQueryParameterType, IQuery
@Override
public String getQueryParameterQualifier() {
+ if (myBase.getMissing()!=null) {
+ return myBase.getQueryParameterQualifier();
+ }
return null;
}
@Override
public String getValueAsQueryToken() {
+ if (myBase.getMissing()!=null) {
+ return myBase.getValueAsQueryToken();
+ }
if (myComparator != null && getValue() != null) {
return myComparator.getCode() + getValueAsString();
} else if (myComparator == null && getValue() != null) {
@@ -112,6 +119,13 @@ public class DateParam extends DateTimeDt implements IQueryParameterType, IQuery
@Override
public void setValueAsQueryToken(String theQualifier, String theValue) {
+ myBase.setValueAsQueryToken(theQualifier, theValue);
+ if (myBase.getMissing()!=null) {
+ setValue(null);
+ myComparator=null;
+ return;
+ }
+
if (theValue.length() < 2) {
throw new DataFormatException("Invalid qualified date parameter: " + theValue);
}
@@ -141,8 +155,10 @@ public class DateParam extends DateTimeDt implements IQueryParameterType, IQuery
@Override
public void setValuesAsQueryTokens(QualifiedParamList theParameters) {
+ myBase.setMissing(null);
myComparator = null;
setValueAsString(null);
+
if (theParameters.size() == 1) {
setValueAsString(theParameters.get(0));
} else if (theParameters.size() > 1) {
@@ -159,6 +175,9 @@ public class DateParam extends DateTimeDt implements IQueryParameterType, IQuery
b.append(myComparator.getCode());
}
b.append(getValueAsString());
+ if (myBase.getMissing()!=null) {
+ b.append(" missing=").append(myBase.getMissing());
+ }
b.append("]");
return b.toString();
}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/QuantityParam.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/QuantityParam.java
index 10307ffc6ac..62128ecbd78 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/QuantityParam.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/QuantityParam.java
@@ -36,7 +36,7 @@ import ca.uhn.fhir.model.primitive.DecimalDt;
import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.model.primitive.UriDt;
-public class QuantityParam implements IQueryParameterType {
+public class QuantityParam extends BaseParam implements IQueryParameterType {
private boolean myApproximate;
private QuantityDt myQuantity = new QuantityDt();
@@ -131,6 +131,7 @@ public class QuantityParam implements IQueryParameterType {
}
private void clear() {
+ setMissing(null);
myQuantity.setComparator((BoundCodeDt) null);
myQuantity.setCode((CodeDt) null);
myQuantity.setSystem((UriDt) null);
@@ -162,6 +163,10 @@ public class QuantityParam implements IQueryParameterType {
@Override
public String getValueAsQueryToken() {
+ if (super.getMissing()!=null) {
+ return super.getValueAsQueryToken();
+ }
+
StringBuilder b = new StringBuilder();
if (myQuantity.getComparator() != null) {
b.append(ParameterUtil.escape(myQuantity.getComparator().getValue()));
@@ -248,6 +253,11 @@ public class QuantityParam implements IQueryParameterType {
public void setValueAsQueryToken(String theQualifier, String theValue) {
clear();
+ super.setValueAsQueryToken(theQualifier, theValue);
+ if (getMissing()!=null) {
+ return;
+ }
+
if (theValue == null) {
return;
}
@@ -290,6 +300,9 @@ public class QuantityParam implements IQueryParameterType {
b.append("value", myQuantity.getValue().getValueAsString());
b.append("system", myQuantity.getSystem().getValueAsString());
b.append("units", myQuantity.getUnits().getValueAsString());
+ if (getMissing()!=null) {
+ b.append("missing", getMissing());
+ }
return b.toString();
}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/ReferenceParam.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/ReferenceParam.java
index 7a74b8c1a5e..c8d93432235 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/ReferenceParam.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/ReferenceParam.java
@@ -30,6 +30,7 @@ import ca.uhn.fhir.model.primitive.IdDt;
public class ReferenceParam extends IdDt implements IQueryParameterType {
private String myChain;
+ private BaseParam myBase=new BaseParam();
public ReferenceParam() {
}
@@ -58,6 +59,10 @@ public class ReferenceParam extends IdDt implements IQueryParameterType {
@Override
public String getQueryParameterQualifier() {
+ if (myBase.getMissing()!=null) {
+ return myBase.getQueryParameterQualifier();
+ }
+
StringBuilder b = new StringBuilder();
if (isNotBlank(getResourceType())) {
b.append(':');
@@ -75,6 +80,9 @@ public class ReferenceParam extends IdDt implements IQueryParameterType {
@Override
public String getValueAsQueryToken() {
+ if (myBase.getMissing()!=null) {
+ return myBase.getValueAsQueryToken();
+ }
return getIdPart();
}
@@ -91,6 +99,13 @@ public class ReferenceParam extends IdDt implements IQueryParameterType {
@Override
public void setValueAsQueryToken(String theQualifier, String theValue) {
+ myBase.setValueAsQueryToken(theQualifier, theValue);
+ if (myBase.getMissing()!=null) {
+ myChain=null;
+ setValue(null);
+ return;
+ }
+
String q = theQualifier;
String resourceType = null;
if (isNotBlank(q)) {
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/StringParam.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/StringParam.java
index 797e6a4f0c2..7e548bcafb7 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/StringParam.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/StringParam.java
@@ -30,7 +30,7 @@ import ca.uhn.fhir.model.api.IQueryParameterType;
import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.rest.server.Constants;
-public class StringParam implements IQueryParameterType {
+public class StringParam extends BaseParam implements IQueryParameterType {
private boolean myExact;
private String myValue;
@@ -52,7 +52,7 @@ public class StringParam implements IQueryParameterType {
if (isExact()) {
return Constants.PARAMQUALIFIER_STRING_EXACT;
} else {
- return null;
+ return super.getQueryParameterQualifier();
}
}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/TokenParam.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/TokenParam.java
index a82846caec8..11f0caaf961 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/TokenParam.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/TokenParam.java
@@ -33,7 +33,7 @@ import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
import ca.uhn.fhir.model.primitive.UriDt;
import ca.uhn.fhir.rest.server.Constants;
-public class TokenParam implements IQueryParameterType {
+public class TokenParam extends BaseParam implements IQueryParameterType {
private String mySystem;
private boolean myText;
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/Constants.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/Constants.java
index 11adbc31a0b..7a7a6f301c4 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/Constants.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/Constants.java
@@ -80,6 +80,7 @@ public class Constants {
public static final String PARAM_SORT_DESC = "_sort:desc";
public static final String PARAM_TAGS = "_tags";
public static final String PARAM_VALIDATE = "_validate";
+ public static final String PARAMQUALIFIER_MISSING = ":missing";
public static final String PARAMQUALIFIER_STRING_EXACT = ":exact";
public static final String PARAMQUALIFIER_TOKEN_TEXT = ":text";
public static final int STATUS_HTTP_200_OK = 200;
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 5e18e26483b..eb199fd7d91 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
@@ -581,13 +581,13 @@ public class RestfulServer extends HttpServlet {
*/
private int escapedLength(String theServletPath) {
int delta = 0;
- for(int i =0;i references = theContext.newTerser().getAllPopulatedChildElementsOfType(next, ResourceReferenceDt.class);
- for (ResourceReferenceDt nextRef : references) {
- IResource nextRes = nextRef.getResource();
- if (nextRes != null) {
- if (nextRes.getId().hasIdPart()) {
- IdDt id = nextRes.getId().toVersionless();
- if (id.hasResourceType()==false) {
- String resName = theContext.getResourceDefinition(nextRes).getName();
- id = id.withResourceType(resName);
+ do {
+ List addedResourcesThisPass = new ArrayList();
+
+ for (ResourceReferenceDt nextRef : references) {
+ IResource nextRes = nextRef.getResource();
+ if (nextRes != null) {
+ if (nextRes.getId().hasIdPart()) {
+ IdDt id = nextRes.getId().toVersionless();
+ if (id.hasResourceType() == false) {
+ String resName = theContext.getResourceDefinition(nextRes).getName();
+ id = id.withResourceType(resName);
+ }
+
+ if (!addedResourceIds.contains(id)) {
+ addedResourceIds.add(id);
+ addedResourcesThisPass.add(nextRes);
+ }
+
+ nextRef.setResource(null);
+ nextRef.setReference(id);
}
-
- if (!addedResourceIds.contains(id)) {
- addedResourceIds.add(id);
- addedResources.add(nextRes);
- }
-
- nextRef.setResource(null);
- nextRef.setReference(id);
}
}
- }
-
+
+ // Linked resources may themselves have linked resources
+ references = new ArrayList();
+ for (IResource iResource : addedResourcesThisPass) {
+ List newReferences = theContext.newTerser().getAllPopulatedChildElementsOfType(iResource, ResourceReferenceDt.class);
+ references.addAll(newReferences);
+ }
+
+ addedResources.addAll(addedResourcesThisPass);
+
+ } while (references.isEmpty() == false);
bundle.addResource(next, theContext, theServerBase);
}
for (IResource next : addedResources) {
bundle.addResource(next, theContext, theServerBase);
}
-
+
bundle.getTotalResults().setValue(theTotalResults);
return bundle;
}
@@ -1056,7 +1069,7 @@ public class RestfulServer extends HttpServlet {
if (next.getId() == null || next.getId().isEmpty()) {
if (!(next instanceof OperationOutcome)) {
throw new InternalErrorException("Server method returned resource of type[" + next.getClass().getSimpleName() + "] with no ID specified (IResource#setId(IdDt) must be called)");
- }
+ }
}
}
@@ -1110,8 +1123,7 @@ public class RestfulServer extends HttpServlet {
String fullId = theResource.getId().withServerBase(theServerBase, resName);
theHttpResponse.addHeader(Constants.HEADER_CONTENT_LOCATION, fullId);
}
-
-
+
if (theResource instanceof Binary) {
Binary bin = (Binary) theResource;
if (isNotBlank(bin.getContentType())) {
@@ -1122,9 +1134,9 @@ public class RestfulServer extends HttpServlet {
if (bin.getContent() == null || bin.getContent().length == 0) {
return;
}
-
+
theHttpResponse.addHeader(Constants.HEADER_CONTENT_DISPOSITION, "Attachment;");
-
+
theHttpResponse.setContentLength(bin.getContent().length);
ServletOutputStream oos = theHttpResponse.getOutputStream();
oos.write(bin.getContent());
@@ -1190,6 +1202,4 @@ public class RestfulServer extends HttpServlet {
}
}
-
-
}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/FhirTerser.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/FhirTerser.java
index 67c35af67b4..1aa4144ff21 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/FhirTerser.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/FhirTerser.java
@@ -143,7 +143,7 @@ public class FhirTerser {
case COMPOSITE_DATATYPE:
case RESOURCE: {
BaseRuntimeElementCompositeDefinition> childDef = (BaseRuntimeElementCompositeDefinition>) theDefinition;
- for (BaseRuntimeChildDefinition nextChild : childDef.getChildren()) {
+ for (BaseRuntimeChildDefinition nextChild : childDef.getChildrenAndExtension()) {
List extends IElement> values = nextChild.getAccessor().getValues(theElement);
if (values != null) {
for (IElement nextValue : values) {
diff --git a/hapi-fhir-base/src/site/xdoc/doc_cors.xml b/hapi-fhir-base/src/site/xdoc/doc_cors.xml
index 37e7ebc31c9..3aef8ea6edd 100644
--- a/hapi-fhir-base/src/site/xdoc/doc_cors.xml
+++ b/hapi-fhir-base/src/site/xdoc/doc_cors.xml
@@ -71,7 +71,7 @@
A comma separated list of allowed headers when making a non simple CORS request.cors.allowed.headers
- X-FHIR-Starter,Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers
+ X-FHIR-Starter,Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,AuthorizationA comma separated list non-standard response headers that will be exposed to XHR2 object.
diff --git a/hapi-fhir-base/src/site/xdoc/doc_resource_references.xml b/hapi-fhir-base/src/site/xdoc/doc_resource_references.xml
index 4108d77e2a0..cffe514f28e 100644
--- a/hapi-fhir-base/src/site/xdoc/doc_resource_references.xml
+++ b/hapi-fhir-base/src/site/xdoc/doc_resource_references.xml
@@ -70,23 +70,21 @@
- In server code, you may wish to return "contained" resources. A simple way to do this
- is to add these resources directly to the reference field and ensure that the resource
- has no ID populated. When this condition is detected, HAPI will automatically create a local
- reference ID and add the resource to the "contained" section when it encodes the resource.
+ In server code, you will often want to return a resource which contains
+ a link to another resource. Generally these "linked" resources are
+ not actually included in the response, but rather a link to the
+ resource is included and the client may request that resource directly
+ (by ID) if it is needed.
The following example shows a Patient resource being created which will have a
- contained resource as its managing organization when encoded from a server:
+ link to its managing organization when encoded from a server:
+ On the other hand, if the linked resource
+ does not have an ID set, the linked resource will
+ be included in the returned bundle as a "contained" resource. In this
+ case, HAPI itself will define a local reference ID (e.g. "#001").
+