Work on #164 - Add support for :missing in JPA server
This commit is contained in:
parent
35cdfaabbd
commit
3fc6958ff2
|
@ -59,4 +59,16 @@ public interface IQueryParameterType {
|
|||
*/
|
||||
public String getQueryParameterQualifier();
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
Boolean getMissing();
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
void setMissing(Boolean theMissing);
|
||||
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ import ca.uhn.fhir.model.primitive.CodeDt;
|
|||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.model.primitive.UriDt;
|
||||
import ca.uhn.fhir.rest.param.ParameterUtil;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
|
||||
public abstract class BaseCodingDt extends BaseIdentifiableElement implements ICompositeDatatype, IQueryParameterType {
|
||||
|
||||
|
@ -172,4 +173,28 @@ public abstract class BaseCodingDt extends BaseIdentifiableElement implements IC
|
|||
public abstract BaseCodingDt setSystem(String theUri);
|
||||
|
||||
|
||||
/**
|
||||
* <b>Not supported!</b>
|
||||
*
|
||||
* @deprecated get/setMissing is not supported in StringDt. Use {@link TokenParam} instead if you
|
||||
* need this functionality
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
public Boolean getMissing() {
|
||||
throw new UnsupportedOperationException("get/setMissing is not supported in StringDt. Use {@link StringParam} instead if you need this functionality");
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>Not supported!</b>
|
||||
*
|
||||
* @deprecated get/setMissing is not supported in StringDt. Use {@link TokenParam} instead if you
|
||||
* need this functionality
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
public void setMissing(Boolean theMissing) {
|
||||
throw new UnsupportedOperationException("get/setMissing is not supported in StringDt. Use {@link StringParam} instead if you need this functionality");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ import ca.uhn.fhir.model.api.IQueryParameterType;
|
|||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.model.primitive.UriDt;
|
||||
import ca.uhn.fhir.rest.param.ParameterUtil;
|
||||
import ca.uhn.fhir.rest.param.StringParam;
|
||||
|
||||
public abstract class BaseIdentifierDt extends BaseIdentifiableElement implements ICompositeDatatype, IQueryParameterType {
|
||||
|
||||
|
@ -112,4 +113,29 @@ public abstract class BaseIdentifierDt extends BaseIdentifiableElement implement
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <b>Not supported!</b>
|
||||
*
|
||||
* @deprecated get/setMissing is not supported in StringDt. Use {@link StringParam} instead if you
|
||||
* need this functionality
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
public Boolean getMissing() {
|
||||
throw new UnsupportedOperationException("get/setMissing is not supported in StringDt. Use {@link StringParam} instead if you need this functionality");
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>Not supported!</b>
|
||||
*
|
||||
* @deprecated get/setMissing is not supported in StringDt. Use {@link StringParam} instead if you
|
||||
* need this functionality
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
public void setMissing(Boolean theMissing) {
|
||||
throw new UnsupportedOperationException("get/setMissing is not supported in StringDt. Use {@link StringParam} instead if you need this functionality");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -33,6 +33,8 @@ import ca.uhn.fhir.model.primitive.CodeDt;
|
|||
import ca.uhn.fhir.model.primitive.DecimalDt;
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.model.primitive.UriDt;
|
||||
import ca.uhn.fhir.rest.param.QuantityParam;
|
||||
import ca.uhn.fhir.rest.param.StringParam;
|
||||
|
||||
public abstract class BaseQuantityDt extends BaseIdentifiableElement implements ICompositeDatatype, IQueryParameterType {
|
||||
|
||||
|
@ -208,4 +210,30 @@ public abstract class BaseQuantityDt extends BaseIdentifiableElement implements
|
|||
* </p>
|
||||
*/
|
||||
public abstract DecimalDt getValueElement();
|
||||
|
||||
/**
|
||||
* <b>Not supported!</b>
|
||||
*
|
||||
* @deprecated get/setMissing is not supported in StringDt. Use {@link QuantityParam} instead if you
|
||||
* need this functionality
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
public Boolean getMissing() {
|
||||
throw new UnsupportedOperationException("get/setMissing is not supported in StringDt. Use {@link StringParam} instead if you need this functionality");
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>Not supported!</b>
|
||||
*
|
||||
* @deprecated get/setMissing is not supported in StringDt. Use {@link QuantityParam} instead if you
|
||||
* need this functionality
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
public void setMissing(Boolean theMissing) {
|
||||
throw new UnsupportedOperationException("get/setMissing is not supported in StringDt. Use {@link StringParam} instead if you need this functionality");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ import ca.uhn.fhir.model.api.BasePrimitive;
|
|||
import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||
import ca.uhn.fhir.model.api.annotation.DatatypeDef;
|
||||
import ca.uhn.fhir.model.api.annotation.SimpleSetter;
|
||||
import ca.uhn.fhir.rest.param.StringParam;
|
||||
|
||||
@DatatypeDef(name = "string")
|
||||
public class StringDt extends BasePrimitive<String> implements IQueryParameterType {
|
||||
|
@ -122,4 +123,28 @@ public class StringDt extends BasePrimitive<String> implements IQueryParameterTy
|
|||
return theValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>Not supported!</b>
|
||||
*
|
||||
* @deprecated get/setMissing is not supported in StringDt. Use {@link StringParam} instead if you
|
||||
* need this functionality
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
public Boolean getMissing() {
|
||||
throw new UnsupportedOperationException("get/setMissing is not supported in StringDt. Use {@link StringParam} instead if you need this functionality");
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>Not supported!</b>
|
||||
*
|
||||
* @deprecated get/setMissing is not supported in StringDt. Use {@link StringParam} instead if you
|
||||
* need this functionality
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
public void setMissing(Boolean theMissing) {
|
||||
throw new UnsupportedOperationException("get/setMissing is not supported in StringDt. Use {@link StringParam} instead if you need this functionality");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
package ca.uhn.fhir.rest.gclient;
|
||||
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
|
||||
abstract class BaseClientParam implements IParam {
|
||||
|
||||
@Override
|
||||
public ICriterion<?> isMissing(boolean theMissing) {
|
||||
return new MissingCriterion(theMissing ? Constants.PARAMQUALIFIER_MISSING_TRUE : Constants.PARAMQUALIFIER_MISSING_FALSE);
|
||||
}
|
||||
|
||||
private class MissingCriterion implements ICriterion<IParam>, ICriterionInternal
|
||||
{
|
||||
private String myParameterValue;
|
||||
|
||||
|
||||
public MissingCriterion(String theParameterValue) {
|
||||
myParameterValue = theParameterValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getParameterValue() {
|
||||
return myParameterValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getParameterName() {
|
||||
return BaseClientParam.this.getParamName() + Constants.PARAMQUALIFIER_MISSING;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -23,7 +23,7 @@ package ca.uhn.fhir.rest.gclient;
|
|||
/**
|
||||
* Composite parameter type for use in fluent client interfaces
|
||||
*/
|
||||
public class CompositeClientParam<A extends IParam, B extends IParam> implements IParam {
|
||||
public class CompositeClientParam<A extends IParam, B extends IParam> extends BaseClientParam implements IParam {
|
||||
|
||||
private String myName;
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ import ca.uhn.fhir.model.primitive.DateTimeDt;
|
|||
/**
|
||||
* Date parameter type for use in fluent client interfaces
|
||||
*/
|
||||
public class DateClientParam implements IParam {
|
||||
public class DateClientParam extends BaseClientParam implements IParam {
|
||||
|
||||
private String myParamName;
|
||||
|
||||
|
|
|
@ -22,6 +22,16 @@ package ca.uhn.fhir.rest.gclient;
|
|||
|
||||
public interface IParam {
|
||||
|
||||
/**
|
||||
* Returns the name of this parameter
|
||||
*/
|
||||
String getParamName();
|
||||
|
||||
/**
|
||||
* Sets the <code>:missing</code> qualifier for this parameter. Set this to <code>true</code>
|
||||
* to indicate that the server should return resources with this value <p>populated</p>. Set this to
|
||||
* <code>false</code> to indicate that the server should return resources with this value <b>missing</b>.
|
||||
*/
|
||||
ICriterion<?> isMissing(boolean theMissing);
|
||||
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ package ca.uhn.fhir.rest.gclient;
|
|||
/**
|
||||
* Token parameter type for use in fluent client interfaces
|
||||
*/
|
||||
public class NumberClientParam implements IParam {
|
||||
public class NumberClientParam extends BaseClientParam implements IParam {
|
||||
|
||||
private String myParamName;
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ import ca.uhn.fhir.rest.gclient.NumberClientParam.IMatches;
|
|||
/**
|
||||
* Token parameter type for use in fluent client interfaces
|
||||
*/
|
||||
public class QuantityClientParam implements IParam {
|
||||
public class QuantityClientParam extends BaseClientParam implements IParam {
|
||||
|
||||
private String myParamName;
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ import ca.uhn.fhir.model.primitive.IdDt;
|
|||
*/
|
||||
|
||||
|
||||
public class ReferenceClientParam implements IParam {
|
||||
public class ReferenceClientParam extends BaseClientParam implements IParam {
|
||||
|
||||
private String myName;
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ import ca.uhn.fhir.rest.server.Constants;
|
|||
* @author james
|
||||
*
|
||||
*/
|
||||
public class StringClientParam implements IParam {
|
||||
public class StringClientParam extends BaseClientParam implements IParam {
|
||||
|
||||
private final String myParamName;
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ import ca.uhn.fhir.model.base.composite.BaseIdentifierDt;
|
|||
/**
|
||||
* Token parameter type for use in fluent client interfaces
|
||||
*/
|
||||
public class TokenClientParam implements IParam {
|
||||
public class TokenClientParam extends BaseClientParam implements IParam {
|
||||
|
||||
private String myParamName;
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ import ca.uhn.fhir.model.primitive.StringDt;
|
|||
/**
|
||||
*
|
||||
*/
|
||||
public class UriClientParam implements IParam {
|
||||
public class UriClientParam extends BaseClientParam implements IParam {
|
||||
|
||||
//TODO: handle :above and :below
|
||||
|
||||
|
|
|
@ -26,54 +26,75 @@ import ca.uhn.fhir.rest.server.Constants;
|
|||
/**
|
||||
* Base class for RESTful operation parameter types
|
||||
*/
|
||||
public class BaseParam implements IQueryParameterType {
|
||||
abstract class BaseParam implements IQueryParameterType {
|
||||
|
||||
private Boolean myMissing;
|
||||
|
||||
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
|
||||
* 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
|
||||
*/
|
||||
@Override
|
||||
public Boolean getMissing() {
|
||||
return myMissing;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String getQueryParameterQualifier() {
|
||||
public final String getQueryParameterQualifier() {
|
||||
if (myMissing != null) {
|
||||
return Constants.PARAMQUALIFIER_MISSING;
|
||||
}
|
||||
return null;
|
||||
return doGetQueryParameterQualifier();
|
||||
}
|
||||
|
||||
abstract String doGetQueryParameterQualifier();
|
||||
|
||||
abstract String doGetValueAsQueryToken();
|
||||
|
||||
@Override
|
||||
public String getValueAsQueryToken() {
|
||||
public final String getValueAsQueryToken() {
|
||||
if (myMissing != null) {
|
||||
return myMissing ? "true" : "false";
|
||||
return myMissing ? Constants.PARAMQUALIFIER_MISSING_TRUE : Constants.PARAMQUALIFIER_MISSING_FALSE;
|
||||
}
|
||||
return null;
|
||||
return doGetValueAsQueryToken();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
* 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
|
||||
*/
|
||||
@Override
|
||||
public void setMissing(Boolean theMissing) {
|
||||
myMissing = theMissing;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValueAsQueryToken(String theQualifier, String theValue) {
|
||||
public final void setValueAsQueryToken(String theQualifier, String theValue) {
|
||||
if (Constants.PARAMQUALIFIER_MISSING.equals(theQualifier)) {
|
||||
myMissing = "true".equals(theValue);
|
||||
} else {
|
||||
myMissing = null;
|
||||
doSetValueAsQueryToken(theQualifier, theValue);
|
||||
}
|
||||
}
|
||||
|
||||
abstract void doSetValueAsQueryToken(String theQualifier, String theValue);
|
||||
|
||||
static class ComposableBaseParam extends BaseParam{
|
||||
|
||||
@Override
|
||||
String doGetQueryParameterQualifier() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
String doGetValueAsQueryToken() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
void doSetValueAsQueryToken(String theQualifier, String theValue) {
|
||||
// nothing
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ import ca.uhn.fhir.context.ConfigurationException;
|
|||
import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
|
||||
public class CompositeParam<A extends IQueryParameterType, B extends IQueryParameterType> implements IQueryParameterType {
|
||||
public class CompositeParam<A extends IQueryParameterType, B extends IQueryParameterType> extends BaseParam implements IQueryParameterType {
|
||||
|
||||
private A myLeftType;
|
||||
private B myRightType;
|
||||
|
@ -59,27 +59,13 @@ public class CompositeParam<A extends IQueryParameterType, B extends IQueryParam
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the left value for this parameter (the first of two parameters in this composite)
|
||||
*/
|
||||
public A getLeftValue() {
|
||||
return myLeftType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getQueryParameterQualifier() {
|
||||
String doGetQueryParameterQualifier() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the right value for this parameter (the second of two parameters in this composite)
|
||||
*/
|
||||
public B getRightValue() {
|
||||
return myRightType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValueAsQueryToken() {
|
||||
String doGetValueAsQueryToken() {
|
||||
StringBuilder b = new StringBuilder();
|
||||
if (myLeftType != null) {
|
||||
b.append(myLeftType.getValueAsQueryToken());
|
||||
|
@ -92,7 +78,7 @@ public class CompositeParam<A extends IQueryParameterType, B extends IQueryParam
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setValueAsQueryToken(String theQualifier, String theValue) {
|
||||
void doSetValueAsQueryToken(String theQualifier, String theValue) {
|
||||
if (isBlank(theValue)) {
|
||||
myLeftType.setValueAsQueryToken(theQualifier, "");
|
||||
myRightType.setValueAsQueryToken(theQualifier, "");
|
||||
|
@ -108,4 +94,18 @@ public class CompositeParam<A extends IQueryParameterType, B extends IQueryParam
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the left value for this parameter (the first of two parameters in this composite)
|
||||
*/
|
||||
public A getLeftValue() {
|
||||
return myLeftType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the right value for this parameter (the second of two parameters in this composite)
|
||||
*/
|
||||
public B getRightValue() {
|
||||
return myRightType;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
|||
public class DateParam extends DateTimeDt implements IQueryParameterType, IQueryParameterOr<DateParam> {
|
||||
|
||||
private QuantityCompararatorEnum myComparator;
|
||||
private BaseParam myBase=new BaseParam();
|
||||
private BaseParam myBase=new BaseParam.ComposableBaseParam();
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
|
@ -191,4 +191,14 @@ public class DateParam extends DateTimeDt implements IQueryParameterType, IQuery
|
|||
return new DateTimeDt(getValueAsString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean getMissing() {
|
||||
return myBase.getMissing();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMissing(Boolean theMissing) {
|
||||
myBase.setMissing(theMissing);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -365,6 +365,16 @@ public class InternalCodingDt extends BaseCodingDt implements ICompositeDatatype
|
|||
return getDisplay();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean getMissing() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMissing(Boolean theMissing) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -414,6 +414,16 @@ class InternalQuantityDt
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean getMissing() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMissing(Boolean theMissing) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -45,32 +45,24 @@ public class NumberParam extends BaseParam implements IQueryParameterType {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String doGetQueryParameterQualifier() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
String doGetValueAsQueryToken() {
|
||||
StringBuilder b = new StringBuilder();
|
||||
b.append(getClass().getSimpleName());
|
||||
b.append("[");
|
||||
if (myQuantity.getComparatorElement().isEmpty() == false) {
|
||||
b.append(myQuantity.getComparatorElement().getValue());
|
||||
}
|
||||
if (myQuantity.getValueElement().isEmpty() == false) {
|
||||
b.append(myQuantity.getValueElement().toString());
|
||||
}
|
||||
b.append("]");
|
||||
return b.toString();
|
||||
}
|
||||
|
||||
public QuantityCompararatorEnum getComparator() {
|
||||
return myQuantity.getComparatorElement().getValueAsEnum();
|
||||
}
|
||||
|
||||
public BigDecimal getValue() {
|
||||
return myQuantity.getValueElement().getValue();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setValueAsQueryToken(String theQualifier, String theValue) {
|
||||
super.setValueAsQueryToken(theQualifier, theValue);
|
||||
void doSetValueAsQueryToken(String theQualifier, String theValue) {
|
||||
if (getMissing() != null && isBlank(theValue)) {
|
||||
return;
|
||||
}
|
||||
|
@ -91,26 +83,29 @@ public class NumberParam extends BaseParam implements IQueryParameterType {
|
|||
myQuantity.setValue(new BigDecimal(theValue));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public QuantityCompararatorEnum getComparator() {
|
||||
return myQuantity.getComparatorElement().getValueAsEnum();
|
||||
}
|
||||
|
||||
public BigDecimal getValue() {
|
||||
return myQuantity.getValueElement().getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValueAsQueryToken() {
|
||||
if (getMissing() != null) {
|
||||
return super.getQueryParameterQualifier();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuilder b = new StringBuilder();
|
||||
b.append(getClass().getSimpleName());
|
||||
b.append("[");
|
||||
if (myQuantity.getComparatorElement().isEmpty() == false) {
|
||||
b.append(myQuantity.getComparatorElement().getValue());
|
||||
}
|
||||
if (myQuantity.getValueElement().isEmpty() == false) {
|
||||
b.append(myQuantity.getValueElement().toString());
|
||||
}
|
||||
b.append("]");
|
||||
return b.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getQueryParameterQualifier() {
|
||||
return super.getQueryParameterQualifier();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -142,29 +142,13 @@ public class QuantityParam extends BaseParam implements IQueryParameterType {
|
|||
myApproximate = false;
|
||||
}
|
||||
|
||||
public QuantityCompararatorEnum getComparator() {
|
||||
return myQuantity.getComparatorElement().getValueAsEnum();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getQueryParameterQualifier() {
|
||||
String doGetQueryParameterQualifier() {
|
||||
return super.getQueryParameterQualifier();
|
||||
}
|
||||
|
||||
public UriDt getSystem() {
|
||||
return myQuantity.getSystemElement();
|
||||
}
|
||||
|
||||
public String getUnits() {
|
||||
return myQuantity.getUnitsElement().getValue();
|
||||
}
|
||||
|
||||
public DecimalDt getValue() {
|
||||
return myQuantity.getValueElement();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValueAsQueryToken() {
|
||||
String doGetValueAsQueryToken() {
|
||||
if (super.getMissing() != null) {
|
||||
return super.getValueAsQueryToken();
|
||||
}
|
||||
|
@ -191,6 +175,67 @@ public class QuantityParam extends BaseParam implements IQueryParameterType {
|
|||
return b.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
void doSetValueAsQueryToken(String theQualifier, String theValue) {
|
||||
clear();
|
||||
|
||||
super.setValueAsQueryToken(theQualifier, theValue);
|
||||
if (getMissing() != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (theValue == null) {
|
||||
return;
|
||||
}
|
||||
List<String> parts = ParameterUtil.splitParameterString(theValue, '|', true);
|
||||
|
||||
if (parts.size() > 0 && StringUtils.isNotBlank(parts.get(0))) {
|
||||
if (parts.get(0).startsWith("~")) {
|
||||
myQuantity.setComparator((QuantityCompararatorEnum) null);
|
||||
myApproximate = true;
|
||||
myQuantity.setValue(new BigDecimal(parts.get(0).substring(1)));
|
||||
} else if (parts.get(0).startsWith("<=")) {
|
||||
myQuantity.setComparator(QuantityCompararatorEnum.LESSTHAN_OR_EQUALS);
|
||||
myQuantity.setValue(new BigDecimal(parts.get(0).substring(2)));
|
||||
} else if (parts.get(0).startsWith("<")) {
|
||||
myQuantity.setComparator(QuantityCompararatorEnum.LESSTHAN);
|
||||
String valStr = parts.get(0).substring(1);
|
||||
myQuantity.setValue(new BigDecimal(valStr));
|
||||
} else if (parts.get(0).startsWith(">=")) {
|
||||
myQuantity.setComparator(QuantityCompararatorEnum.GREATERTHAN_OR_EQUALS);
|
||||
myQuantity.setValue(new BigDecimal(parts.get(0).substring(2)));
|
||||
} else if (parts.get(0).startsWith(">")) {
|
||||
myQuantity.setComparator(QuantityCompararatorEnum.GREATERTHAN);
|
||||
myQuantity.setValue(new BigDecimal(parts.get(0).substring(1)));
|
||||
} else {
|
||||
myQuantity.setValue(new BigDecimal(parts.get(0)));
|
||||
}
|
||||
}
|
||||
if (parts.size() > 1 && StringUtils.isNotBlank(parts.get(1))) {
|
||||
myQuantity.setSystem(parts.get(1));
|
||||
}
|
||||
if (parts.size() > 2 && StringUtils.isNotBlank(parts.get(2))) {
|
||||
myQuantity.setUnits(parts.get(2));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public QuantityCompararatorEnum getComparator() {
|
||||
return myQuantity.getComparatorElement().getValueAsEnum();
|
||||
}
|
||||
|
||||
public UriDt getSystem() {
|
||||
return myQuantity.getSystemElement();
|
||||
}
|
||||
|
||||
public String getUnits() {
|
||||
return myQuantity.getUnitsElement().getValue();
|
||||
}
|
||||
|
||||
public DecimalDt getValue() {
|
||||
return myQuantity.getValueElement();
|
||||
}
|
||||
|
||||
public boolean isApproximate() {
|
||||
return myApproximate;
|
||||
}
|
||||
|
@ -253,51 +298,6 @@ public class QuantityParam extends BaseParam implements IQueryParameterType {
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValueAsQueryToken(String theQualifier, String theValue) {
|
||||
clear();
|
||||
|
||||
super.setValueAsQueryToken(theQualifier, theValue);
|
||||
if (getMissing() != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (theValue == null) {
|
||||
return;
|
||||
}
|
||||
List<String> parts = ParameterUtil.splitParameterString(theValue, '|', true);
|
||||
|
||||
if (parts.size() > 0 && StringUtils.isNotBlank(parts.get(0))) {
|
||||
if (parts.get(0).startsWith("~")) {
|
||||
myQuantity.setComparator((QuantityCompararatorEnum) null);
|
||||
myApproximate = true;
|
||||
myQuantity.setValue(new BigDecimal(parts.get(0).substring(1)));
|
||||
} else if (parts.get(0).startsWith("<=")) {
|
||||
myQuantity.setComparator(QuantityCompararatorEnum.LESSTHAN_OR_EQUALS);
|
||||
myQuantity.setValue(new BigDecimal(parts.get(0).substring(2)));
|
||||
} else if (parts.get(0).startsWith("<")) {
|
||||
myQuantity.setComparator(QuantityCompararatorEnum.LESSTHAN);
|
||||
String valStr = parts.get(0).substring(1);
|
||||
myQuantity.setValue(new BigDecimal(valStr));
|
||||
} else if (parts.get(0).startsWith(">=")) {
|
||||
myQuantity.setComparator(QuantityCompararatorEnum.GREATERTHAN_OR_EQUALS);
|
||||
myQuantity.setValue(new BigDecimal(parts.get(0).substring(2)));
|
||||
} else if (parts.get(0).startsWith(">")) {
|
||||
myQuantity.setComparator(QuantityCompararatorEnum.GREATERTHAN);
|
||||
myQuantity.setValue(new BigDecimal(parts.get(0).substring(1)));
|
||||
} else {
|
||||
myQuantity.setValue(new BigDecimal(parts.get(0)));
|
||||
}
|
||||
}
|
||||
if (parts.size() > 1 && StringUtils.isNotBlank(parts.get(1))) {
|
||||
myQuantity.setSystem(parts.get(1));
|
||||
}
|
||||
if (parts.size() > 2 && StringUtils.isNotBlank(parts.get(2))) {
|
||||
myQuantity.setUnits(parts.get(2));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
ToStringBuilder b = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE);
|
||||
|
|
|
@ -32,7 +32,7 @@ import ca.uhn.fhir.model.primitive.IdDt;
|
|||
public class ReferenceParam extends IdDt implements IQueryParameterType {
|
||||
|
||||
private String myChain;
|
||||
private BaseParam myBase=new BaseParam();
|
||||
private BaseParam myBase=new BaseParam.ComposableBaseParam();
|
||||
|
||||
public ReferenceParam() {
|
||||
}
|
||||
|
@ -206,4 +206,14 @@ public class ReferenceParam extends IdDt implements IQueryParameterType {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean getMissing() {
|
||||
return myBase.getMissing();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMissing(Boolean theMissing) {
|
||||
myBase.setMissing(theMissing);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -48,23 +48,35 @@ public class StringParam extends BaseParam implements IQueryParameterType {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getQueryParameterQualifier() {
|
||||
if (getMissing() != null) {
|
||||
return super.getQueryParameterQualifier();
|
||||
}else if (isExact()) {
|
||||
String doGetQueryParameterQualifier() {
|
||||
if (isExact()) {
|
||||
return Constants.PARAMQUALIFIER_STRING_EXACT;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
String doGetValueAsQueryToken() {
|
||||
return ParameterUtil.escape(myValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
void doSetValueAsQueryToken(String theQualifier, String theValue) {
|
||||
if (Constants.PARAMQUALIFIER_STRING_EXACT.equals(theQualifier)) {
|
||||
setExact(true);
|
||||
} else {
|
||||
setExact(false);
|
||||
}
|
||||
myValue = ParameterUtil.unescape(theValue);
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return myValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValueAsQueryToken() {
|
||||
return ParameterUtil.escape(myValue);
|
||||
public StringDt getValueAsStringDt() {
|
||||
return new StringDt(myValue);
|
||||
}
|
||||
|
||||
public String getValueNotNull() {
|
||||
|
@ -87,16 +99,6 @@ public class StringParam extends BaseParam implements IQueryParameterType {
|
|||
myValue = theValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValueAsQueryToken(String theQualifier, String theValue) {
|
||||
if (Constants.PARAMQUALIFIER_STRING_EXACT.equals(theQualifier)) {
|
||||
setExact(true);
|
||||
} else {
|
||||
setExact(false);
|
||||
}
|
||||
myValue = ParameterUtil.unescape(theValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
ToStringBuilder builder = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE);
|
||||
|
@ -107,8 +109,4 @@ public class StringParam extends BaseParam implements IQueryParameterType {
|
|||
return builder.toString();
|
||||
}
|
||||
|
||||
public StringDt getValueAsStringDt() {
|
||||
return new StringDt(myValue);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -41,21 +41,6 @@ public class TokenParam extends BaseParam implements IQueryParameterType {
|
|||
public TokenParam() {
|
||||
}
|
||||
|
||||
public TokenParam(String theSystem, String theValue) {
|
||||
setSystem(theSystem);
|
||||
setValue(theValue);
|
||||
}
|
||||
|
||||
public TokenParam(String theSystem, String theValue, boolean theText) {
|
||||
if (theText && isNotBlank(theSystem)) {
|
||||
throw new IllegalArgumentException(
|
||||
"theSystem can not be non-blank if theText is true (:text searches do not include a system). In other words, set the first parameter to null for a text search");
|
||||
}
|
||||
setSystem(theSystem);
|
||||
setValue(theValue);
|
||||
setText(theText);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor which copies the {@link InternalCodingDt#getSystemElement() system} and {@link InternalCodingDt#getCodeElement() code} from a {@link InternalCodingDt} instance and adds it as a parameter
|
||||
*
|
||||
|
@ -76,21 +61,56 @@ public class TokenParam extends BaseParam implements IQueryParameterType {
|
|||
this(toSystemValue(theIdentifierDt.getSystemElement()), theIdentifierDt.getValueElement().getValue());
|
||||
}
|
||||
|
||||
private static String toSystemValue(UriDt theSystem) {
|
||||
return theSystem.getValueAsString();
|
||||
public TokenParam(String theSystem, String theValue) {
|
||||
setSystem(theSystem);
|
||||
setValue(theValue);
|
||||
}
|
||||
|
||||
public TokenParam(String theSystem, String theValue, boolean theText) {
|
||||
if (theText && isNotBlank(theSystem)) {
|
||||
throw new IllegalArgumentException(
|
||||
"theSystem can not be non-blank if theText is true (:text searches do not include a system). In other words, set the first parameter to null for a text search");
|
||||
}
|
||||
setSystem(theSystem);
|
||||
setValue(theValue);
|
||||
setText(theText);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getQueryParameterQualifier() {
|
||||
if (getMissing() != null) {
|
||||
return super.getQueryParameterQualifier();
|
||||
} else if (isText()) {
|
||||
String doGetQueryParameterQualifier() {
|
||||
if (isText()) {
|
||||
return Constants.PARAMQUALIFIER_TOKEN_TEXT;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
String doGetValueAsQueryToken() {
|
||||
if (getSystem() != null) {
|
||||
return ParameterUtil.escape(StringUtils.defaultString(getSystem())) + '|' + ParameterUtil.escape(getValue());
|
||||
} else {
|
||||
return ParameterUtil.escape(getValue());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
void doSetValueAsQueryToken(String theQualifier, String theParameter) {
|
||||
int barIndex = ParameterUtil.nonEscapedIndexOf(theParameter, '|');
|
||||
if (barIndex != -1) {
|
||||
setSystem(theParameter.substring(0, barIndex));
|
||||
setValue(ParameterUtil.unescape(theParameter.substring(barIndex + 1)));
|
||||
} else {
|
||||
setValue(ParameterUtil.unescape(theParameter));
|
||||
}
|
||||
}
|
||||
|
||||
public String getSystem() {
|
||||
return mySystem;
|
||||
}
|
||||
|
@ -99,18 +119,8 @@ public class TokenParam extends BaseParam implements IQueryParameterType {
|
|||
return myValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String getValueAsQueryToken() {
|
||||
if (getMissing() != null) {
|
||||
return super.getValueAsQueryToken();
|
||||
} else if (getSystem() != null) {
|
||||
return ParameterUtil.escape(StringUtils.defaultString(getSystem())) + '|' + ParameterUtil.escape(getValue());
|
||||
} else {
|
||||
return ParameterUtil.escape(getValue());
|
||||
}
|
||||
public InternalCodingDt getValueAsCoding() {
|
||||
return new InternalCodingDt(mySystem, myValue);
|
||||
}
|
||||
|
||||
public String getValueNotNull() {
|
||||
|
@ -137,25 +147,6 @@ public class TokenParam extends BaseParam implements IQueryParameterType {
|
|||
myValue = theValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setValueAsQueryToken(String theQualifier, String theParameter) {
|
||||
super.setValueAsQueryToken(theQualifier, theParameter);
|
||||
if (getMissing() != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
int barIndex = ParameterUtil.nonEscapedIndexOf(theParameter, '|');
|
||||
if (barIndex != -1) {
|
||||
setSystem(theParameter.substring(0, barIndex));
|
||||
setValue(ParameterUtil.unescape(theParameter.substring(barIndex + 1)));
|
||||
} else {
|
||||
setValue(ParameterUtil.unescape(theParameter));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
ToStringBuilder builder = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE);
|
||||
|
@ -170,8 +161,8 @@ public class TokenParam extends BaseParam implements IQueryParameterType {
|
|||
return builder.toString();
|
||||
}
|
||||
|
||||
public InternalCodingDt getValueAsCoding() {
|
||||
return new InternalCodingDt(mySystem, myValue);
|
||||
private static String toSystemValue(UriDt theSystem) {
|
||||
return theSystem.getValueAsString();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -42,21 +42,30 @@ public class UriParam extends BaseParam implements IQueryParameterType {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getQueryParameterQualifier() {
|
||||
if (getMissing() != null) {
|
||||
return super.getQueryParameterQualifier();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
String doGetQueryParameterQualifier() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
String doGetValueAsQueryToken() {
|
||||
return ParameterUtil.escape(myValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
void doSetValueAsQueryToken(String theQualifier, String theValue) {
|
||||
myValue = ParameterUtil.unescape(theValue);
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return myValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValueAsQueryToken() {
|
||||
return ParameterUtil.escape(myValue);
|
||||
public StringDt getValueAsStringDt() {
|
||||
return new StringDt(myValue);
|
||||
}
|
||||
|
||||
public UriDt getValueAsUriDt() {
|
||||
return new UriDt(myValue);
|
||||
}
|
||||
|
||||
public String getValueNotNull() {
|
||||
|
@ -71,11 +80,6 @@ public class UriParam extends BaseParam implements IQueryParameterType {
|
|||
myValue = theValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValueAsQueryToken(String theQualifier, String theValue) {
|
||||
myValue = ParameterUtil.unescape(theValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
ToStringBuilder builder = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE);
|
||||
|
@ -83,12 +87,4 @@ public class UriParam extends BaseParam implements IQueryParameterType {
|
|||
return builder.toString();
|
||||
}
|
||||
|
||||
public StringDt getValueAsStringDt() {
|
||||
return new StringDt(myValue);
|
||||
}
|
||||
|
||||
public UriDt getValueAsUriDt() {
|
||||
return new UriDt(myValue);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -123,6 +123,8 @@ public class Constants {
|
|||
public static final int STATUS_HTTP_501_NOT_IMPLEMENTED = 501;
|
||||
public static final String URL_TOKEN_HISTORY = "_history";
|
||||
public static final String URL_TOKEN_METADATA = "metadata";
|
||||
public static final String PARAMQUALIFIER_MISSING_TRUE = "true";
|
||||
public static final String PARAMQUALIFIER_MISSING_FALSE = "false";
|
||||
|
||||
static {
|
||||
Map<String, EncodingEnum> valToEncoding = new HashMap<String, EncodingEnum>();
|
||||
|
|
|
@ -42,4 +42,5 @@ ca.uhn.fhir.jpa.dao.BaseFhirSystemDao.transactionInvalidUrl=Unable to perform {0
|
|||
ca.uhn.fhir.jpa.dao.BaseFhirResourceDao.duplicateCreateForcedId=Can not create entity with ID[{0}], a resource with this ID already exists
|
||||
ca.uhn.fhir.jpa.dao.BaseFhirResourceDao.failedToCreateWithClientAssignedNumericId=Can not create resource with ID[{0}], no resource with this ID exists and clients may only assign IDs which begin with a non-numeric character on this server
|
||||
ca.uhn.fhir.jpa.dao.BaseFhirResourceDao.failedToCreateWithClientAssignedId=Can not create resource with ID[{0}], ID must not be supplied on a create (POST) operation
|
||||
ca.uhn.fhir.jpa.dao.BaseFhirResourceDao.multipleParamsWithSameNameOneIsMissingTrue=This server does not know how to handle multiple "{0}" parameters where one has a value of :missing=true
|
||||
ca.uhn.fhir.jpa.dao.BaseFhirResourceDao.unableToDeleteNotFound=Unable to find resource matching URL "{0}". Deletion failed.
|
||||
|
|
|
@ -47,6 +47,7 @@ import javax.persistence.criteria.CriteriaBuilder;
|
|||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Expression;
|
||||
import javax.persistence.criteria.From;
|
||||
import javax.persistence.criteria.Join;
|
||||
import javax.persistence.criteria.JoinType;
|
||||
import javax.persistence.criteria.Order;
|
||||
import javax.persistence.criteria.Path;
|
||||
|
@ -72,6 +73,7 @@ import ca.uhn.fhir.context.RuntimeChildResourceDefinition;
|
|||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||
import ca.uhn.fhir.jpa.entity.BaseHasResource;
|
||||
import ca.uhn.fhir.jpa.entity.BaseResourceIndexedSearchParam;
|
||||
import ca.uhn.fhir.jpa.entity.BaseTag;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceHistoryTable;
|
||||
import ca.uhn.fhir.jpa.entity.ResourceIndexedSearchParamDate;
|
||||
|
@ -141,6 +143,8 @@ public abstract class BaseFhirResourceDao<T extends IResource> extends BaseFhirD
|
|||
private String mySecondaryPrimaryKeyParamName;
|
||||
|
||||
private Set<Long> addPredicateComposite(RuntimeSearchParam theParamDef, Set<Long> thePids, List<? extends IQueryParameterType> theNextAnd) {
|
||||
// TODO: fail if missing is set for a composite query
|
||||
|
||||
CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
|
||||
CriteriaQuery<Long> cq = builder.createQuery(Long.class);
|
||||
Root<ResourceTable> from = cq.from(ResourceTable.class);
|
||||
|
@ -178,6 +182,10 @@ public abstract class BaseFhirResourceDao<T extends IResource> extends BaseFhirD
|
|||
return thePids;
|
||||
}
|
||||
|
||||
if (Boolean.TRUE.equals(theList.get(0).getMissing())) {
|
||||
return addPredicateParamMissing(thePids, "myParamsDate");
|
||||
}
|
||||
|
||||
CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
|
||||
CriteriaQuery<Long> cq = builder.createQuery(Long.class);
|
||||
Root<ResourceIndexedSearchParamDate> from = cq.from(ResourceIndexedSearchParamDate.class);
|
||||
|
@ -185,6 +193,10 @@ public abstract class BaseFhirResourceDao<T extends IResource> extends BaseFhirD
|
|||
|
||||
List<Predicate> codePredicates = new ArrayList<Predicate>();
|
||||
for (IQueryParameterType nextOr : theList) {
|
||||
if (addPredicateMissingFalseIfPresent(theParamName, from, codePredicates, nextOr)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
IQueryParameterType params = nextOr;
|
||||
Predicate p = createPredicateDate(builder, from, params);
|
||||
codePredicates.add(p);
|
||||
|
@ -205,50 +217,6 @@ public abstract class BaseFhirResourceDao<T extends IResource> extends BaseFhirD
|
|||
return new HashSet<Long>(q.getResultList());
|
||||
}
|
||||
|
||||
private Predicate addPredicateDateFromRange(CriteriaBuilder theBuilder, From<ResourceIndexedSearchParamDate, ResourceIndexedSearchParamDate> theFrom, DateRangeParam theRange) {
|
||||
Date lowerBound = theRange.getLowerBoundAsInstant();
|
||||
Date upperBound = theRange.getUpperBoundAsInstant();
|
||||
|
||||
Predicate lb = null;
|
||||
if (lowerBound != null) {
|
||||
Predicate gt = theBuilder.greaterThanOrEqualTo(theFrom.<Date> get("myValueLow"), lowerBound);
|
||||
Predicate lt = theBuilder.greaterThanOrEqualTo(theFrom.<Date> get("myValueHigh"), lowerBound);
|
||||
lb = theBuilder.or(gt, lt);
|
||||
|
||||
// Predicate gin = builder.isNull(from.get("myValueLow"));
|
||||
// Predicate lbo = builder.or(gt, gin);
|
||||
// Predicate lin = builder.isNull(from.get("myValueHigh"));
|
||||
// Predicate hbo = builder.or(lt, lin);
|
||||
// lb = builder.and(lbo, hbo);
|
||||
}
|
||||
|
||||
Predicate ub = null;
|
||||
if (upperBound != null) {
|
||||
Predicate gt = theBuilder.lessThanOrEqualTo(theFrom.<Date> get("myValueLow"), upperBound);
|
||||
Predicate lt = theBuilder.lessThanOrEqualTo(theFrom.<Date> get("myValueHigh"), upperBound);
|
||||
ub = theBuilder.or(gt, lt);
|
||||
|
||||
// Predicate gin = builder.isNull(from.get("myValueLow"));
|
||||
// Predicate lbo = builder.or(gt, gin);
|
||||
// Predicate lin = builder.isNull(from.get("myValueHigh"));
|
||||
// Predicate ubo = builder.or(lt, lin);
|
||||
// ub = builder.and(ubo, lbo);
|
||||
|
||||
}
|
||||
|
||||
if (lb != null && ub != null) {
|
||||
return (theBuilder.and(lb, ub));
|
||||
} else if (lb != null) {
|
||||
return (lb);
|
||||
} else {
|
||||
return (ub);
|
||||
}
|
||||
}
|
||||
|
||||
// private Set<Long> addPredicateComposite(String theParamName, Set<Long> thePids, List<? extends
|
||||
// IQueryParameterType> theList) {
|
||||
// }
|
||||
|
||||
private Set<Long> addPredicateId(Set<Long> theExistingPids, Set<Long> thePids) {
|
||||
if (thePids == null || thePids.isEmpty()) {
|
||||
return Collections.emptySet();
|
||||
|
@ -273,6 +241,10 @@ public abstract class BaseFhirResourceDao<T extends IResource> extends BaseFhirD
|
|||
return found;
|
||||
}
|
||||
|
||||
// private Set<Long> addPredicateComposite(String theParamName, Set<Long> thePids, List<? extends
|
||||
// IQueryParameterType> theList) {
|
||||
// }
|
||||
|
||||
private Set<Long> addPredicateLanguage(Set<Long> thePids, List<List<? extends IQueryParameterType>> theList) {
|
||||
if (theList == null || theList.isEmpty()) {
|
||||
return thePids;
|
||||
|
@ -323,6 +295,10 @@ public abstract class BaseFhirResourceDao<T extends IResource> extends BaseFhirD
|
|||
return thePids;
|
||||
}
|
||||
|
||||
if (Boolean.TRUE.equals(theList.get(0).getMissing())) {
|
||||
return addPredicateParamMissing(thePids, "myParamsNumber");
|
||||
}
|
||||
|
||||
CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
|
||||
CriteriaQuery<Long> cq = builder.createQuery(Long.class);
|
||||
Root<ResourceIndexedSearchParamNumber> from = cq.from(ResourceIndexedSearchParamNumber.class);
|
||||
|
@ -332,6 +308,10 @@ public abstract class BaseFhirResourceDao<T extends IResource> extends BaseFhirD
|
|||
for (IQueryParameterType nextOr : theList) {
|
||||
IQueryParameterType params = nextOr;
|
||||
|
||||
if (addPredicateMissingFalseIfPresent(theParamName, from, codePredicates, nextOr)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (params instanceof NumberParam) {
|
||||
NumberParam param = (NumberParam) params;
|
||||
|
||||
|
@ -385,10 +365,30 @@ public abstract class BaseFhirResourceDao<T extends IResource> extends BaseFhirD
|
|||
return new HashSet<Long>(q.getResultList());
|
||||
}
|
||||
|
||||
private Set<Long> addPredicateParamMissing(Set<Long> thePids, String joinName) {
|
||||
CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
|
||||
CriteriaQuery<Long> cq = builder.createQuery(Long.class);
|
||||
Root<ResourceTable> from = cq.from(ResourceTable.class);
|
||||
cq.select(from.get("myId").as(Long.class));
|
||||
Join<Object, Object> join = from.join(joinName, JoinType.LEFT);
|
||||
if (thePids.size() > 0) {
|
||||
Predicate inPids = (from.get("myId").in(thePids));
|
||||
cq.where(builder.and(inPids, join.isNull()));
|
||||
} else {
|
||||
cq.where(join.isNull());
|
||||
}
|
||||
TypedQuery<Long> q = myEntityManager.createQuery(cq);
|
||||
return new HashSet<Long>(q.getResultList());
|
||||
}
|
||||
|
||||
private Set<Long> addPredicateQuantity(String theParamName, Set<Long> thePids, List<? extends IQueryParameterType> theList) {
|
||||
if (theList == null || theList.isEmpty()) {
|
||||
return thePids;
|
||||
}
|
||||
|
||||
if (Boolean.TRUE.equals(theList.get(0).getMissing())) {
|
||||
return addPredicateParamMissing(thePids, "myParamsQuantity");
|
||||
}
|
||||
|
||||
CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
|
||||
CriteriaQuery<Long> cq = builder.createQuery(Long.class);
|
||||
|
@ -399,6 +399,10 @@ public abstract class BaseFhirResourceDao<T extends IResource> extends BaseFhirD
|
|||
for (IQueryParameterType nextOr : theList) {
|
||||
IQueryParameterType params = nextOr;
|
||||
|
||||
if (addPredicateMissingFalseIfPresent(theParamName, from, codePredicates, nextOr)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String systemValue;
|
||||
String unitsValue;
|
||||
QuantityCompararatorEnum cmpValue;
|
||||
|
@ -500,6 +504,10 @@ public abstract class BaseFhirResourceDao<T extends IResource> extends BaseFhirD
|
|||
return pidsToRetain;
|
||||
}
|
||||
|
||||
if (Boolean.TRUE.equals(theList.get(0).getMissing())) {
|
||||
return addPredicateParamMissing(thePids, "myResourceLinks");
|
||||
}
|
||||
|
||||
CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
|
||||
CriteriaQuery<Long> cq = builder.createQuery(Long.class);
|
||||
Root<ResourceLink> from = cq.from(ResourceLink.class);
|
||||
|
@ -510,6 +518,10 @@ public abstract class BaseFhirResourceDao<T extends IResource> extends BaseFhirD
|
|||
for (IQueryParameterType nextOr : theList) {
|
||||
IQueryParameterType params = nextOr;
|
||||
|
||||
if (addPredicateMissingFalseIfPresentForResourceLink(theParamName, from, codePredicates, nextOr)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (params instanceof ReferenceParam) {
|
||||
ReferenceParam ref = (ReferenceParam) params;
|
||||
|
||||
|
@ -594,6 +606,10 @@ public abstract class BaseFhirResourceDao<T extends IResource> extends BaseFhirD
|
|||
return thePids;
|
||||
}
|
||||
|
||||
if (Boolean.TRUE.equals(theList.get(0).getMissing())) {
|
||||
return addPredicateParamMissing(thePids, "myParamsString");
|
||||
}
|
||||
|
||||
CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
|
||||
CriteriaQuery<Long> cq = builder.createQuery(Long.class);
|
||||
Root<ResourceIndexedSearchParamString> from = cq.from(ResourceIndexedSearchParamString.class);
|
||||
|
@ -602,7 +618,10 @@ public abstract class BaseFhirResourceDao<T extends IResource> extends BaseFhirD
|
|||
List<Predicate> codePredicates = new ArrayList<Predicate>();
|
||||
for (IQueryParameterType nextOr : theList) {
|
||||
IQueryParameterType theParameter = nextOr;
|
||||
|
||||
if (addPredicateMissingFalseIfPresent(theParamName, from, codePredicates, nextOr)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Predicate singleCode = createPredicateString(theParameter, theParamName, builder, from);
|
||||
codePredicates.add(singleCode);
|
||||
}
|
||||
|
@ -622,11 +641,41 @@ public abstract class BaseFhirResourceDao<T extends IResource> extends BaseFhirD
|
|||
return new HashSet<Long>(q.getResultList());
|
||||
}
|
||||
|
||||
private boolean addPredicateMissingFalseIfPresent(String theParamName, Root<? extends BaseResourceIndexedSearchParam> from, List<Predicate> codePredicates, IQueryParameterType nextOr) {
|
||||
boolean missingFalse = false;
|
||||
if (nextOr.getMissing() != null) {
|
||||
if (nextOr.getMissing().booleanValue() == true) {
|
||||
throw new InvalidRequestException(getContext().getLocalizer().getMessage(BaseFhirResourceDao.class, "multipleParamsWithSameNameOneIsMissingTrue", theParamName));
|
||||
}
|
||||
Predicate singleCode = from.get("myId").isNotNull();
|
||||
codePredicates.add(singleCode);
|
||||
missingFalse = true;
|
||||
}
|
||||
return missingFalse;
|
||||
}
|
||||
|
||||
private boolean addPredicateMissingFalseIfPresentForResourceLink(String theParamName, Root<? extends ResourceLink> from, List<Predicate> codePredicates, IQueryParameterType nextOr) {
|
||||
boolean missingFalse = false;
|
||||
if (nextOr.getMissing() != null) {
|
||||
if (nextOr.getMissing().booleanValue() == true) {
|
||||
throw new InvalidRequestException(getContext().getLocalizer().getMessage(BaseFhirResourceDao.class, "multipleParamsWithSameNameOneIsMissingTrue", theParamName));
|
||||
}
|
||||
Predicate singleCode = from.get("mySourceResource").isNotNull();
|
||||
codePredicates.add(singleCode);
|
||||
missingFalse = true;
|
||||
}
|
||||
return missingFalse;
|
||||
}
|
||||
|
||||
private Set<Long> addPredicateToken(String theParamName, Set<Long> thePids, List<? extends IQueryParameterType> theList) {
|
||||
if (theList == null || theList.isEmpty()) {
|
||||
return thePids;
|
||||
}
|
||||
|
||||
if (Boolean.TRUE.equals(theList.get(0).getMissing())) {
|
||||
return addPredicateParamMissing(thePids, "myParamsToken");
|
||||
}
|
||||
|
||||
CriteriaBuilder builder = myEntityManager.getCriteriaBuilder();
|
||||
CriteriaQuery<Long> cq = builder.createQuery(Long.class);
|
||||
Root<ResourceIndexedSearchParamToken> from = cq.from(ResourceIndexedSearchParamToken.class);
|
||||
|
@ -641,6 +690,10 @@ public abstract class BaseFhirResourceDao<T extends IResource> extends BaseFhirD
|
|||
}
|
||||
}
|
||||
|
||||
if (addPredicateMissingFalseIfPresent(theParamName, from, codePredicates, nextOr)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Predicate singleCode = createPredicateToken(nextOr, theParamName, builder, from);
|
||||
codePredicates.add(singleCode);
|
||||
}
|
||||
|
@ -759,20 +812,60 @@ public abstract class BaseFhirResourceDao<T extends IResource> extends BaseFhirD
|
|||
DateParam date = (DateParam) theParam;
|
||||
if (!date.isEmpty()) {
|
||||
DateRangeParam range = new DateRangeParam(date);
|
||||
p = addPredicateDateFromRange(theBuilder, theFrom, range);
|
||||
p = createPredicateDateFromRange(theBuilder, theFrom, range);
|
||||
} else {
|
||||
// TODO: handle missing date param?
|
||||
p = null;
|
||||
}
|
||||
} else if (theParam instanceof DateRangeParam) {
|
||||
DateRangeParam range = (DateRangeParam) theParam;
|
||||
p = addPredicateDateFromRange(theBuilder, theFrom, range);
|
||||
p = createPredicateDateFromRange(theBuilder, theFrom, range);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Invalid token type: " + theParam.getClass());
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
private Predicate createPredicateDateFromRange(CriteriaBuilder theBuilder, From<ResourceIndexedSearchParamDate, ResourceIndexedSearchParamDate> theFrom, DateRangeParam theRange) {
|
||||
Date lowerBound = theRange.getLowerBoundAsInstant();
|
||||
Date upperBound = theRange.getUpperBoundAsInstant();
|
||||
|
||||
Predicate lb = null;
|
||||
if (lowerBound != null) {
|
||||
Predicate gt = theBuilder.greaterThanOrEqualTo(theFrom.<Date> get("myValueLow"), lowerBound);
|
||||
Predicate lt = theBuilder.greaterThanOrEqualTo(theFrom.<Date> get("myValueHigh"), lowerBound);
|
||||
lb = theBuilder.or(gt, lt);
|
||||
|
||||
// Predicate gin = builder.isNull(from.get("myValueLow"));
|
||||
// Predicate lbo = builder.or(gt, gin);
|
||||
// Predicate lin = builder.isNull(from.get("myValueHigh"));
|
||||
// Predicate hbo = builder.or(lt, lin);
|
||||
// lb = builder.and(lbo, hbo);
|
||||
}
|
||||
|
||||
Predicate ub = null;
|
||||
if (upperBound != null) {
|
||||
Predicate gt = theBuilder.lessThanOrEqualTo(theFrom.<Date> get("myValueLow"), upperBound);
|
||||
Predicate lt = theBuilder.lessThanOrEqualTo(theFrom.<Date> get("myValueHigh"), upperBound);
|
||||
ub = theBuilder.or(gt, lt);
|
||||
|
||||
// Predicate gin = builder.isNull(from.get("myValueLow"));
|
||||
// Predicate lbo = builder.or(gt, gin);
|
||||
// Predicate lin = builder.isNull(from.get("myValueHigh"));
|
||||
// Predicate ubo = builder.or(lt, lin);
|
||||
// ub = builder.and(ubo, lbo);
|
||||
|
||||
}
|
||||
|
||||
if (lb != null && ub != null) {
|
||||
return (theBuilder.and(lb, ub));
|
||||
} else if (lb != null) {
|
||||
return (lb);
|
||||
} else {
|
||||
return (ub);
|
||||
}
|
||||
}
|
||||
|
||||
private Predicate createPredicateString(IQueryParameterType theParameter, String theParamName, CriteriaBuilder theBuilder,
|
||||
From<ResourceIndexedSearchParamString, ResourceIndexedSearchParamString> theFrom) {
|
||||
String rawSearchTerm;
|
||||
|
@ -1166,7 +1259,7 @@ public abstract class BaseFhirResourceDao<T extends IResource> extends BaseFhirD
|
|||
}
|
||||
|
||||
HashSet<Long> pidsToInclude = new HashSet<Long>();
|
||||
|
||||
|
||||
for (Include nextInclude : theRevIncludes) {
|
||||
boolean matchAll = "*".equals(nextInclude.getValue());
|
||||
if (matchAll) {
|
||||
|
@ -1208,7 +1301,7 @@ public abstract class BaseFhirResourceDao<T extends IResource> extends BaseFhirD
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
theMatches.addAll(pidsToInclude);
|
||||
}
|
||||
|
||||
|
@ -1532,9 +1625,8 @@ public abstract class BaseFhirResourceDao<T extends IResource> extends BaseFhirD
|
|||
loadResourcesByPid(pidsSubList, retVal, BundleEntrySearchModeEnum.MATCH);
|
||||
|
||||
/*
|
||||
* Load _include resources - Note that _revincludes are handled differently
|
||||
* than _include ones, as they are counted towards the total count and paged,
|
||||
* so they are loaded outside the bundle provider
|
||||
* Load _include resources - Note that _revincludes are handled differently than _include ones, as they are counted towards the total count and paged, so they are loaded
|
||||
* outside the bundle provider
|
||||
*/
|
||||
if (theParams.getIncludes() != null && theParams.getIncludes().isEmpty() == false) {
|
||||
Set<IdDt> previouslyLoadedPids = new HashSet<IdDt>();
|
||||
|
|
|
@ -2,6 +2,7 @@ package ca.uhn.fhir.jpa.dao;
|
|||
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
import static org.hamcrest.Matchers.containsInRelativeOrder;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.endsWith;
|
||||
import static org.hamcrest.Matchers.greaterThan;
|
||||
|
@ -866,16 +867,16 @@ public class FhirResourceDaoDstu2Test {
|
|||
public void testReverseIncludes() {
|
||||
String methodName = "testReverseIncludes";
|
||||
Organization org = new Organization();
|
||||
org.setName("X"+methodName+"X");
|
||||
org.setName("X" + methodName + "X");
|
||||
IdDt orgId = ourOrganizationDao.create(org).getId();
|
||||
|
||||
|
||||
Patient pat = new Patient();
|
||||
pat.addName().addFamily("X"+methodName+"X");
|
||||
pat.addName().addFamily("X" + methodName + "X");
|
||||
pat.getManagingOrganization().setReference(orgId.toUnqualifiedVersionless());
|
||||
ourPatientDao.create(pat);
|
||||
|
||||
|
||||
SearchParameterMap map = new SearchParameterMap();
|
||||
map.add(Organization.SP_NAME, new StringParam("X"+methodName+"X"));
|
||||
map.add(Organization.SP_NAME, new StringParam("X" + methodName + "X"));
|
||||
map.setRevIncludes(Collections.singleton(Patient.INCLUDE_ORGANIZATION));
|
||||
IBundleProvider resultsP = ourOrganizationDao.search(map);
|
||||
assertEquals(2, resultsP.size());
|
||||
|
@ -884,11 +885,11 @@ public class FhirResourceDaoDstu2Test {
|
|||
assertEquals(Organization.class, results.get(0).getClass());
|
||||
assertEquals(Patient.class, results.get(1).getClass());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testResourceInstanceMetaOperation() {
|
||||
deleteEverything();
|
||||
|
||||
|
||||
String methodName = "testResourceInstanceMetaOperation";
|
||||
IdDt id1, id2;
|
||||
{
|
||||
|
@ -1521,6 +1522,195 @@ public class FhirResourceDaoDstu2Test {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchWithMissingString() {
|
||||
IdDt orgId = ourOrganizationDao.create(new Organization()).getId();
|
||||
IdDt notMissing;
|
||||
IdDt missing;
|
||||
{
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("001");
|
||||
missing = ourPatientDao.create(patient).getId().toUnqualifiedVersionless();
|
||||
}
|
||||
{
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("002");
|
||||
patient.addName().addFamily("Tester_testSearchStringParam").addGiven("John");
|
||||
patient.setBirthDate(new DateDt("2011-01-01"));
|
||||
patient.getManagingOrganization().setReference(orgId);
|
||||
notMissing = ourPatientDao.create(patient).getId().toUnqualifiedVersionless();
|
||||
}
|
||||
// String Param
|
||||
{
|
||||
HashMap<String, IQueryParameterType> params = new HashMap<String, IQueryParameterType>();
|
||||
StringParam param = new StringParam();
|
||||
param.setMissing(false);
|
||||
params.put(Patient.SP_FAMILY, param);
|
||||
List<IdDt> patients = toUnqualifiedVersionlessIds(ourPatientDao.search(params));
|
||||
assertThat(patients, not(containsInRelativeOrder(missing)));
|
||||
assertThat(patients, containsInRelativeOrder(notMissing));
|
||||
}
|
||||
{
|
||||
Map<String, IQueryParameterType> params = new HashMap<String, IQueryParameterType>();
|
||||
StringParam param = new StringParam();
|
||||
param.setMissing(true);
|
||||
params.put(Patient.SP_FAMILY, param);
|
||||
List<IdDt> patients = toUnqualifiedVersionlessIds(ourPatientDao.search(params));
|
||||
assertThat(patients, containsInRelativeOrder(missing));
|
||||
assertThat(patients, not(containsInRelativeOrder(notMissing)));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchWithMissingQuantity() {
|
||||
IdDt notMissing;
|
||||
IdDt missing;
|
||||
{
|
||||
Observation obs = new Observation();
|
||||
obs.addIdentifier().setSystem("urn:system").setValue("001");
|
||||
missing = ourObservationDao.create(obs).getId().toUnqualifiedVersionless();
|
||||
}
|
||||
{
|
||||
Observation obs = new Observation();
|
||||
obs.addIdentifier().setSystem("urn:system").setValue("002");
|
||||
obs.setValue(new QuantityDt(123));
|
||||
notMissing = ourObservationDao.create(obs).getId().toUnqualifiedVersionless();
|
||||
}
|
||||
// Quantity Param
|
||||
{
|
||||
HashMap<String, IQueryParameterType> params = new HashMap<String, IQueryParameterType>();
|
||||
QuantityParam param = new QuantityParam();
|
||||
param.setMissing(false);
|
||||
params.put(Observation.SP_VALUE_QUANTITY, param);
|
||||
List<IdDt> patients = toUnqualifiedVersionlessIds(ourPatientDao.search(params));
|
||||
assertThat(patients, not(containsInRelativeOrder(missing)));
|
||||
assertThat(patients, containsInRelativeOrder(notMissing));
|
||||
}
|
||||
{
|
||||
Map<String, IQueryParameterType> params = new HashMap<String, IQueryParameterType>();
|
||||
QuantityParam param = new QuantityParam();
|
||||
param.setMissing(true);
|
||||
params.put(Observation.SP_VALUE_QUANTITY, param);
|
||||
List<IdDt> patients = toUnqualifiedVersionlessIds(ourPatientDao.search(params));
|
||||
assertThat(patients, containsInRelativeOrder(missing));
|
||||
assertThat(patients, not(containsInRelativeOrder(notMissing)));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchWithToken() {
|
||||
IdDt notMissing;
|
||||
IdDt missing;
|
||||
{
|
||||
Observation obs = new Observation();
|
||||
obs.addIdentifier().setSystem("urn:system").setValue("001");
|
||||
missing = ourObservationDao.create(obs).getId().toUnqualifiedVersionless();
|
||||
}
|
||||
{
|
||||
Observation obs = new Observation();
|
||||
obs.addIdentifier().setSystem("urn:system").setValue("002");
|
||||
obs.getCode().addCoding().setSystem("urn:system").setCode("002");
|
||||
notMissing = ourObservationDao.create(obs).getId().toUnqualifiedVersionless();
|
||||
}
|
||||
// Token Param
|
||||
{
|
||||
HashMap<String, IQueryParameterType> params = new HashMap<String, IQueryParameterType>();
|
||||
TokenParam param = new TokenParam();
|
||||
param.setMissing(false);
|
||||
params.put(Observation.SP_CODE, param);
|
||||
List<IdDt> patients = toUnqualifiedVersionlessIds(ourPatientDao.search(params));
|
||||
assertThat(patients, not(containsInRelativeOrder(missing)));
|
||||
assertThat(patients, containsInRelativeOrder(notMissing));
|
||||
}
|
||||
{
|
||||
Map<String, IQueryParameterType> params = new HashMap<String, IQueryParameterType>();
|
||||
TokenParam param = new TokenParam();
|
||||
param.setMissing(true);
|
||||
params.put(Observation.SP_CODE, param);
|
||||
List<IdDt> patients = toUnqualifiedVersionlessIds(ourPatientDao.search(params));
|
||||
assertThat(patients, containsInRelativeOrder(missing));
|
||||
assertThat(patients, not(containsInRelativeOrder(notMissing)));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchWithMissingDate() {
|
||||
IdDt orgId = ourOrganizationDao.create(new Organization()).getId();
|
||||
IdDt notMissing;
|
||||
IdDt missing;
|
||||
{
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("001");
|
||||
missing = ourPatientDao.create(patient).getId().toUnqualifiedVersionless();
|
||||
}
|
||||
{
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("002");
|
||||
patient.addName().addFamily("Tester_testSearchStringParam").addGiven("John");
|
||||
patient.setBirthDate(new DateDt("2011-01-01"));
|
||||
patient.getManagingOrganization().setReference(orgId);
|
||||
notMissing = ourPatientDao.create(patient).getId().toUnqualifiedVersionless();
|
||||
}
|
||||
// Date Param
|
||||
{
|
||||
HashMap<String, IQueryParameterType> params = new HashMap<String, IQueryParameterType>();
|
||||
DateParam param = new DateParam();
|
||||
param.setMissing(false);
|
||||
params.put(Patient.SP_BIRTHDATE, param);
|
||||
List<IdDt> patients = toUnqualifiedVersionlessIds(ourPatientDao.search(params));
|
||||
assertThat(patients, not(containsInRelativeOrder(missing)));
|
||||
assertThat(patients, containsInRelativeOrder(notMissing));
|
||||
}
|
||||
{
|
||||
Map<String, IQueryParameterType> params = new HashMap<String, IQueryParameterType>();
|
||||
DateParam param = new DateParam();
|
||||
param.setMissing(true);
|
||||
params.put(Patient.SP_BIRTHDATE, param);
|
||||
List<IdDt> patients = toUnqualifiedVersionlessIds(ourPatientDao.search(params));
|
||||
assertThat(patients, containsInRelativeOrder(missing));
|
||||
assertThat(patients, not(containsInRelativeOrder(notMissing)));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchWithMissingReference() {
|
||||
IdDt orgId = ourOrganizationDao.create(new Organization()).getId();
|
||||
IdDt notMissing;
|
||||
IdDt missing;
|
||||
{
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("001");
|
||||
missing = ourPatientDao.create(patient).getId().toUnqualifiedVersionless();
|
||||
}
|
||||
{
|
||||
Patient patient = new Patient();
|
||||
patient.addIdentifier().setSystem("urn:system").setValue("002");
|
||||
patient.addName().addFamily("Tester_testSearchStringParam").addGiven("John");
|
||||
patient.setBirthDate(new DateDt("2011-01-01"));
|
||||
patient.getManagingOrganization().setReference(orgId);
|
||||
notMissing = ourPatientDao.create(patient).getId().toUnqualifiedVersionless();
|
||||
}
|
||||
// Reference Param
|
||||
{
|
||||
HashMap<String, IQueryParameterType> params = new HashMap<String, IQueryParameterType>();
|
||||
ReferenceParam param = new ReferenceParam();
|
||||
param.setMissing(false);
|
||||
params.put(Patient.SP_ORGANIZATION, param);
|
||||
List<IdDt> patients = toUnqualifiedVersionlessIds(ourPatientDao.search(params));
|
||||
assertThat(patients, not(containsInRelativeOrder(missing)));
|
||||
assertThat(patients, containsInRelativeOrder(notMissing));
|
||||
}
|
||||
{
|
||||
Map<String, IQueryParameterType> params = new HashMap<String, IQueryParameterType>();
|
||||
ReferenceParam param = new ReferenceParam();
|
||||
param.setMissing(true);
|
||||
params.put(Patient.SP_ORGANIZATION, param);
|
||||
List<IdDt> patients = toUnqualifiedVersionlessIds(ourPatientDao.search(params));
|
||||
assertThat(patients, containsInRelativeOrder(missing));
|
||||
assertThat(patients, not(containsInRelativeOrder(notMissing)));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchStringParamWithNonNormalized() {
|
||||
{
|
||||
|
@ -2343,14 +2533,12 @@ public class FhirResourceDaoDstu2Test {
|
|||
FhirSystemDaoDstu2Test.doDeleteEverything(ourSystemDao);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSearchWithNoResults() {
|
||||
Device dev = new Device();
|
||||
dev.addIdentifier().setSystem("Foo");
|
||||
ourDeviceDao.create(dev);
|
||||
|
||||
|
||||
|
||||
IBundleProvider value = ourDeviceDao.search(new SearchParameterMap());
|
||||
ourLog.info("Initial size: " + value.size());
|
||||
for (IResource next : value.getResources(0, value.size())) {
|
||||
|
|
|
@ -36,6 +36,7 @@ import ca.uhn.fhir.jpa.dao.DaoConfig;
|
|||
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
|
||||
import ca.uhn.fhir.jpa.testutil.RandomServerPortProvider;
|
||||
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.api.ResourceMetadataKeyEnum;
|
||||
import ca.uhn.fhir.model.dstu.resource.Device;
|
||||
|
@ -286,7 +287,7 @@ public class ResourceProviderDstu2Test {
|
|||
response.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSearchWithInclude() throws Exception {
|
||||
Organization org = new Organization();
|
||||
|
@ -317,6 +318,59 @@ public class ResourceProviderDstu2Test {
|
|||
assertEquals(BundleEntrySearchModeEnum.INCLUDE, found.getEntries().get(1).getResource().getResourceMetadata().get(ResourceMetadataKeyEnum.ENTRY_SEARCH_MODE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchWithMissing() throws Exception {
|
||||
String methodName = "testSearchWithMissing";
|
||||
|
||||
Organization org = new Organization();
|
||||
org.addIdentifier().setSystem("urn:system:rpdstu2").setValue(methodName + "01");
|
||||
org.setName(methodName + "name");
|
||||
IdDt orgNotMissing = ourClient.create().resource(org).prettyPrint().encodedXml().execute().getId().toUnqualifiedVersionless();
|
||||
|
||||
org = new Organization();
|
||||
org.addIdentifier().setSystem("urn:system:rpdstu2").setValue(methodName + "01");
|
||||
IdDt orgMissing = ourClient.create().resource(org).prettyPrint().encodedXml().execute().getId().toUnqualifiedVersionless();
|
||||
|
||||
{
|
||||
//@formatter:off
|
||||
Bundle found = ourClient
|
||||
.search()
|
||||
.forResource(Organization.class)
|
||||
.where(Organization.NAME.isMissing(false))
|
||||
.prettyPrint()
|
||||
.execute();
|
||||
//@formatter:on
|
||||
|
||||
List<IdDt> list = toIdListUnqualifiedVersionless(found);
|
||||
ourLog.info(list.toString());
|
||||
assertThat(list, containsInRelativeOrder(orgNotMissing));
|
||||
assertThat(list, not(containsInRelativeOrder(orgMissing)));
|
||||
}
|
||||
{
|
||||
//@formatter:off
|
||||
Bundle found = ourClient
|
||||
.search()
|
||||
.forResource(Organization.class)
|
||||
.where(Organization.NAME.isMissing(true))
|
||||
.prettyPrint()
|
||||
.execute();
|
||||
//@formatter:on
|
||||
|
||||
List<IdDt> list = toIdListUnqualifiedVersionless(found);
|
||||
ourLog.info(list.toString());
|
||||
assertThat(list, not(containsInRelativeOrder(orgNotMissing)));
|
||||
assertThat(list, containsInRelativeOrder(orgMissing));
|
||||
}
|
||||
}
|
||||
|
||||
private List<IdDt> toIdListUnqualifiedVersionless(Bundle found) {
|
||||
List<IdDt> list = new ArrayList<IdDt>();
|
||||
for (BundleEntry next : found.getEntries()) {
|
||||
list.add(next.getResource().getId().toUnqualifiedVersionless());
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEverythingOperation() throws Exception {
|
||||
String methodName = "testEverythingOperation";
|
||||
|
@ -692,7 +746,8 @@ public class ResourceProviderDstu2Test {
|
|||
p1.addIdentifier().setValue("testSearchByIdentifierWithoutSystem01");
|
||||
IdDt p1Id = ourClient.create().resource(p1).execute().getId();
|
||||
|
||||
Bundle actual = ourClient.search().forResource(Patient.class).where(Patient.IDENTIFIER.exactly().systemAndCode(null, "testSearchByIdentifierWithoutSystem01")).encodedJson().prettyPrint().execute();
|
||||
Bundle actual = ourClient.search().forResource(Patient.class).where(Patient.IDENTIFIER.exactly().systemAndCode(null, "testSearchByIdentifierWithoutSystem01")).encodedJson().prettyPrint()
|
||||
.execute();
|
||||
assertEquals(1, actual.size());
|
||||
assertEquals(p1Id.getIdPart(), actual.getEntries().get(0).getResource().getId().getIdPart());
|
||||
|
||||
|
@ -790,7 +845,8 @@ public class ResourceProviderDstu2Test {
|
|||
|
||||
assertThat(p1Id.getValue(), containsString("Patient/testUpdateWithClientSuppliedIdWhichDoesntExistRpDstu2/_history"));
|
||||
|
||||
Bundle actual = ourClient.search().forResource(Patient.class).where(Patient.IDENTIFIER.exactly().systemAndCode("urn:system", "testUpdateWithClientSuppliedIdWhichDoesntExistRpDstu2")).encodedJson().prettyPrint().execute();
|
||||
Bundle actual = ourClient.search().forResource(Patient.class).where(Patient.IDENTIFIER.exactly().systemAndCode("urn:system", "testUpdateWithClientSuppliedIdWhichDoesntExistRpDstu2"))
|
||||
.encodedJson().prettyPrint().execute();
|
||||
assertEquals(1, actual.size());
|
||||
assertEquals(p1Id.getIdPart(), actual.getEntries().get(0).getResource().getId().getIdPart());
|
||||
|
||||
|
|
|
@ -147,7 +147,30 @@ public class GenericClientTest {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMissing() throws Exception {
|
||||
|
||||
ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
|
||||
when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);
|
||||
when(myHttpResponse.getAllHeaders()).thenReturn(new Header[]{new BasicHeader(Constants.HEADER_LOCATION, "/Patient/44/_history/22")});
|
||||
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
|
||||
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<InputStream>() {
|
||||
@Override
|
||||
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
return (new ReaderInputStream(new StringReader(getPatientFeedWithOneResult()), Charset.forName("UTF-8")));
|
||||
}});
|
||||
|
||||
IGenericClient client = ourCtx.newRestfulGenericClient("http://example.com/fhir");
|
||||
|
||||
when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 201, "OK"));
|
||||
|
||||
client.search().forResource("Patient").where(Patient.NAME.isMissing(true)).execute();
|
||||
assertEquals("http://example.com/fhir/Patient?name%3Amissing=true", capt.getValue().getRequestLine().getUri());
|
||||
|
||||
client.search().forResource("Patient").where(Patient.NAME.isMissing(false)).execute();
|
||||
assertEquals("http://example.com/fhir/Patient?name%3Amissing=false", capt.getValue().getRequestLine().getUri());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateWithStringAutoDetectsEncoding() throws Exception {
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ import ca.uhn.fhir.model.primitive.BoundCodeDt;
|
|||
import ca.uhn.fhir.model.primitive.CodeDt;
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.model.primitive.UriDt;
|
||||
import ca.uhn.fhir.rest.param.StringParam;
|
||||
|
||||
/**
|
||||
* HAPI/FHIR <b>Identifier</b> Datatype
|
||||
|
@ -402,5 +403,29 @@ public class IdentifierDt
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>Not supported!</b>
|
||||
*
|
||||
* @deprecated get/setMissing is not supported in StringDt. Use {@link StringParam} instead if you
|
||||
* need this functionality
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
public Boolean getMissing() {
|
||||
throw new UnsupportedOperationException("get/setMissing is not supported in StringDt. Use {@link StringParam} instead if you need this functionality");
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>Not supported!</b>
|
||||
*
|
||||
* @deprecated get/setMissing is not supported in StringDt. Use {@link StringParam} instead if you
|
||||
* need this functionality
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
public void setMissing(Boolean theMissing) {
|
||||
throw new UnsupportedOperationException("get/setMissing is not supported in StringDt. Use {@link StringParam} instead if you need this functionality");
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -185,9 +185,17 @@
|
|||
</action>
|
||||
<action type="add" issue="164">
|
||||
Improve error message when a user tries to perform a create/update with an invalid
|
||||
or missing Content-Type header. Thanks to wanghaisheng for reporting!
|
||||
or missing Content-Type header. Thanks to wanghaisheng for reporting! (This was
|
||||
actually a three part bug, so the following two fixes also reference this
|
||||
bug number)
|
||||
</action>
|
||||
</release>
|
||||
<action type="add" issue="164">
|
||||
Add support for :missing qualifier in generic/fluent client.
|
||||
</action>
|
||||
<action type="add" issue="164">
|
||||
Add support for :missing qualifier in JPA server.
|
||||
</action>
|
||||
</release>
|
||||
<release version="0.9" date="2015-Mar-14">
|
||||
<action type="add">
|
||||
Support for DSTU2 features introduced: New resource definitions, Bundle resource,
|
||||
|
|
Loading…
Reference in New Issue