Introduce the ability for search parameters to have qualifiers, and add StringParameter to allow exact string matches
This commit is contained in:
parent
54ab77d51a
commit
610bb542ca
|
@ -14,6 +14,10 @@
|
|||
QuantityDt did not implement IQueryParameterType so it was not valid, and there was no way to
|
||||
support quantity search parameters on the server (e.g. Observation.value-quantity)
|
||||
</action>
|
||||
<action type="add">
|
||||
Introduce StringParameter type which can be used as a RESTful operation search parameter
|
||||
type. StringParameter allows ":exact" matches to be specified in clients, and handled in servers.
|
||||
</action>
|
||||
</release>
|
||||
</body>
|
||||
</document>
|
||||
|
|
|
@ -22,6 +22,7 @@ package ca.uhn.fhir.model.api;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import ca.uhn.fhir.rest.method.QualifiedParamList;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
|
||||
public interface IQueryParameterAnd {
|
||||
|
@ -34,7 +35,7 @@ public interface IQueryParameterAnd {
|
|||
* for information on the <b>token</b> format
|
||||
* </p>
|
||||
*/
|
||||
public void setValuesAsQueryTokens(List<List<String>> theParameters) throws InvalidRequestException;
|
||||
public void setValuesAsQueryTokens(List<QualifiedParamList> theParameters) throws InvalidRequestException;
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
|
@ -23,23 +23,30 @@ package ca.uhn.fhir.model.api;
|
|||
public interface IQueryParameterType {
|
||||
|
||||
/**
|
||||
* Sets the value of this type using the <b>token</b> format. This
|
||||
* format is used in HTTP queries as a parameter format.
|
||||
* Sets the value of this type using the <b>token</b> format. This format is used in HTTP queries as a parameter
|
||||
* format.
|
||||
*
|
||||
* <p>See FHIR specification
|
||||
* <a href="http://www.hl7.org/implement/standards/fhir/search.html#ptypes">2.2.2 Search SearchParameter Types</a>
|
||||
* for information on the <b>token</b> format
|
||||
* <p>
|
||||
* See FHIR specification <a href="http://www.hl7.org/implement/standards/fhir/search.html#ptypes">2.2.2 Search
|
||||
* SearchParameter Types</a> for information on the <b>token</b> format
|
||||
* </p>
|
||||
*
|
||||
* @param theQualifier
|
||||
* The parameter name qualifier that accompanied this value. For example, if the complete query was
|
||||
* <code>http://foo?name:exact=John</code>, qualifier would be ":exact"
|
||||
* @param theValue
|
||||
* The actual parameter value. For example, if the complete query was
|
||||
* <code>http://foo?name:exact=John</code>, the value would be "John"
|
||||
*/
|
||||
public void setValueAsQueryToken(String theParameter);
|
||||
public void setValueAsQueryToken(String theQualifier, String theValue);
|
||||
|
||||
/**
|
||||
* Returns the value of this type using the <b>token</b> format. This
|
||||
* format is used in HTTP queries as a parameter format.
|
||||
* Returns the value of this type using the <b>token</b> format. This format is used in HTTP queries as a parameter
|
||||
* format.
|
||||
*
|
||||
* <p>See FHIR specification
|
||||
* <a href="http://www.hl7.org/implement/standards/fhir/search.html#ptypes">2.2.2 Search SearchParameter Types</a>
|
||||
* for information on the <b>token</b> format
|
||||
* <p>
|
||||
* See FHIR specification <a href="http://www.hl7.org/implement/standards/fhir/search.html#ptypes">2.2.2 Search
|
||||
* SearchParameter Types</a> for information on the <b>token</b> format
|
||||
* </p>
|
||||
*/
|
||||
public String getValueAsQueryToken();
|
||||
|
|
|
@ -417,13 +417,13 @@ public class CodingDt
|
|||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setValueAsQueryToken(String theParameter) {
|
||||
int barIndex = theParameter.indexOf('|');
|
||||
public void setValueAsQueryToken(String theQualifier, String theValue) {
|
||||
int barIndex = theValue.indexOf('|');
|
||||
if (barIndex != -1) {
|
||||
setSystem(new UriDt(theParameter.substring(0, barIndex)));
|
||||
setCode(theParameter.substring(barIndex + 1));
|
||||
setSystem(new UriDt(theValue.substring(0, barIndex)));
|
||||
setCode(theValue.substring(barIndex + 1));
|
||||
} else {
|
||||
setCode(theParameter);
|
||||
setCode(theValue);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -423,13 +423,13 @@ public class IdentifierDt
|
|||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setValueAsQueryToken(String theParameter) {
|
||||
int barIndex = theParameter.indexOf('|');
|
||||
public void setValueAsQueryToken(String theQualifier, String theValue) {
|
||||
int barIndex = theValue.indexOf('|');
|
||||
if (barIndex != -1) {
|
||||
setSystem(new UriDt(theParameter.substring(0, barIndex)));
|
||||
setValue(theParameter.substring(barIndex + 1));
|
||||
setSystem(new UriDt(theValue.substring(0, barIndex)));
|
||||
setValue(theValue.substring(barIndex + 1));
|
||||
} else {
|
||||
setValue(theParameter);
|
||||
setValue(theValue);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -373,17 +373,17 @@ public class QuantityDt extends BaseElement implements ICompositeDatatype, IQuer
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setValueAsQueryToken(String theParameter) {
|
||||
public void setValueAsQueryToken(String theQualifier, String theValue) {
|
||||
setComparator((BoundCodeDt<QuantityCompararatorEnum>) null);
|
||||
setCode((CodeDt) null);
|
||||
setSystem((UriDt) null);
|
||||
setUnits((StringDt) null);
|
||||
setValue((DecimalDt) null);
|
||||
|
||||
if (theParameter == null) {
|
||||
if (theValue == null) {
|
||||
return;
|
||||
}
|
||||
String[] parts = theParameter.split("\\|");
|
||||
String[] parts = theValue.split("\\|");
|
||||
if (parts.length > 0 && StringUtils.isNotBlank(parts[0])) {
|
||||
if (parts[0].startsWith("<=")) {
|
||||
setComparator(QuantityCompararatorEnum.LESSTHAN_OR_EQUALS);
|
||||
|
|
|
@ -109,8 +109,8 @@ public class StringDt extends BasePrimitive<String> implements IQueryParameterTy
|
|||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setValueAsQueryToken(String theParameter) {
|
||||
setValue(theParameter);
|
||||
public void setValueAsQueryToken(String theQualifier, String theValue) {
|
||||
setValue(theValue);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -59,7 +59,7 @@ public class StringParam implements IParam {
|
|||
private class StringExactly implements IStringMatch {
|
||||
@Override
|
||||
public ICriterion value(String theValue) {
|
||||
return new StringCriterion(getParamName() + Constants.PARAMNAME_SUFFIX_EXACT, theValue);
|
||||
return new StringCriterion(getParamName() + Constants.PARAMQUALIFIER_STRING_EXACT, theValue);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
package ca.uhn.fhir.rest.method;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
public class QualifiedParamList extends ArrayList<String> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String myQualifier;
|
||||
|
||||
public QualifiedParamList() {
|
||||
super();
|
||||
}
|
||||
|
||||
public QualifiedParamList(int theCapacity) {
|
||||
super(theCapacity);
|
||||
}
|
||||
|
||||
public String getQualifier() {
|
||||
return myQualifier;
|
||||
}
|
||||
|
||||
public void setQualifier(String theQualifier) {
|
||||
myQualifier = theQualifier;
|
||||
}
|
||||
|
||||
public static QualifiedParamList singleton(String theQualifier, String theNextParam) {
|
||||
QualifiedParamList retVal = new QualifiedParamList(1);
|
||||
retVal.setQualifier(theQualifier);
|
||||
retVal.add(theNextParam);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
public static QualifiedParamList splitQueryStringByCommasIgnoreEscape(String theQualifier, String theParams){
|
||||
QualifiedParamList retVal = new QualifiedParamList();
|
||||
retVal.setQualifier(theQualifier);
|
||||
|
||||
StringTokenizer tok = new StringTokenizer(theParams,",");
|
||||
String prev=null;
|
||||
while (tok.hasMoreElements()) {
|
||||
String str = tok.nextToken();
|
||||
if (prev!=null&&prev.endsWith("\\")) {
|
||||
int idx = retVal.size()-1;
|
||||
String existing = retVal.get(idx);
|
||||
retVal.set(idx, existing.substring(0, existing.length()-1) + "," + str);
|
||||
}else {
|
||||
retVal.add(str);
|
||||
}
|
||||
|
||||
prev=str;
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -21,7 +21,10 @@ package ca.uhn.fhir.rest.method;
|
|||
*/
|
||||
|
||||
import java.io.Reader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -45,6 +48,7 @@ public class Request {
|
|||
private HttpServletRequest myServletRequest;
|
||||
private HttpServletResponse myServletResponse;
|
||||
private IdDt myVersion;
|
||||
private Map<String,List<String>> myUnqualifiedToQualifiedNames;
|
||||
|
||||
public String getCompleteUrl() {
|
||||
return myCompleteUrl;
|
||||
|
@ -117,6 +121,33 @@ public class Request {
|
|||
|
||||
public void setParameters(Map<String, String[]> theParams) {
|
||||
myParameters = theParams;
|
||||
|
||||
for (String next : myParameters.keySet()) {
|
||||
for (int i = 0; i < next.length();i++) {
|
||||
char nextChar = next.charAt(i);
|
||||
if(nextChar == ':' || nextChar == '.') {
|
||||
if (myUnqualifiedToQualifiedNames==null) {
|
||||
myUnqualifiedToQualifiedNames = new HashMap<String, List<String>>();
|
||||
}
|
||||
String unqualified = next.substring(0,i);
|
||||
List<String> list = myUnqualifiedToQualifiedNames.get(unqualified);
|
||||
if (list==null) {
|
||||
list=new ArrayList<String>(4);
|
||||
myUnqualifiedToQualifiedNames.put(unqualified, list);
|
||||
}
|
||||
list.add(next);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (myUnqualifiedToQualifiedNames==null) {
|
||||
myUnqualifiedToQualifiedNames=Collections.emptyMap();
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, List<String>> getUnqualifiedToQualifiedNames() {
|
||||
return myUnqualifiedToQualifiedNames;
|
||||
}
|
||||
|
||||
public void setRequestType(RequestType theRequestType) {
|
||||
|
|
|
@ -136,16 +136,29 @@ public class SearchMethodBinding extends BaseResourceReturningMethodBinding {
|
|||
return false;
|
||||
}
|
||||
|
||||
// This is used to track all the parameters so we can reject queries that
|
||||
// have additional params we don't understand
|
||||
Set<String> methodParamsTemp = new HashSet<String>();
|
||||
|
||||
Set<String> unqualifiedNames = theRequest.getUnqualifiedToQualifiedNames().keySet();
|
||||
Set<String> qualifiedParamNames = theRequest.getParameters().keySet();
|
||||
for (int i = 0; i < this.getParameters().size(); i++) {
|
||||
if (!(getParameters().get(i) instanceof BaseQueryParameter)) {
|
||||
continue;
|
||||
}
|
||||
BaseQueryParameter temp = (BaseQueryParameter) getParameters().get(i);
|
||||
methodParamsTemp.add(temp.getName());
|
||||
if (temp.isRequired() && !theRequest.getParameters().containsKey(temp.getName())) {eee
|
||||
ourLog.trace("Method {} doesn't match param '{}' is not present", getMethod().getName(), temp.getName());
|
||||
String name = temp.getName();
|
||||
if (temp.isRequired()) {
|
||||
|
||||
if (qualifiedParamNames.contains(name)) {
|
||||
methodParamsTemp.add(name);
|
||||
} else if (unqualifiedNames.contains(name)) {
|
||||
methodParamsTemp.addAll(theRequest.getUnqualifiedToQualifiedNames().get(name));
|
||||
} else {
|
||||
ourLog.trace("Method {} doesn't match param '{}' is not present", getMethod().getName(), name);
|
||||
return false;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
if (myQueryName != null) {
|
||||
|
|
|
@ -23,16 +23,15 @@ package ca.uhn.fhir.rest.param;
|
|||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import ca.uhn.fhir.model.dstu.valueset.SearchParamTypeEnum;
|
||||
import ca.uhn.fhir.rest.client.BaseClientInvocation;
|
||||
import ca.uhn.fhir.rest.method.QualifiedParamList;
|
||||
import ca.uhn.fhir.rest.method.Request;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.util.QueryUtil;
|
||||
|
||||
public abstract class BaseQueryParameter implements IParameter {
|
||||
|
||||
|
@ -40,13 +39,13 @@ public abstract class BaseQueryParameter implements IParameter {
|
|||
|
||||
public abstract String getName();
|
||||
|
||||
public abstract Object parse(List<List<String>> theString) throws InternalErrorException, InvalidRequestException;
|
||||
public abstract Object parse(List<QualifiedParamList> theString) throws InternalErrorException, InvalidRequestException;
|
||||
|
||||
public abstract boolean isRequired();
|
||||
|
||||
/**
|
||||
* Parameter should return true if {@link #parse(List)} should be called even
|
||||
* if the query string contained no values for the given parameter
|
||||
* Parameter should return true if {@link #parse(List)} should be called even if the query string contained no
|
||||
* values for the given parameter
|
||||
*/
|
||||
public abstract boolean handlesMissing();
|
||||
|
||||
|
@ -79,28 +78,43 @@ public abstract class BaseQueryParameter implements IParameter {
|
|||
|
||||
@Override
|
||||
public Object translateQueryParametersIntoServerArgument(Request theRequest, Object theRequestContents) throws InternalErrorException, InvalidRequestException {
|
||||
String[] value = theRequest.getParameters().get(getName());
|
||||
if (value == null || value.length == 0) {
|
||||
|
||||
List<QualifiedParamList> paramList = new ArrayList<QualifiedParamList>();
|
||||
String name = getName();
|
||||
parseParams(theRequest, paramList, name, null);
|
||||
|
||||
List<String> qualified = theRequest.getUnqualifiedToQualifiedNames().get(name);
|
||||
if (qualified != null) {
|
||||
for (String nextQualified : qualified) {
|
||||
parseParams(theRequest, paramList, nextQualified, nextQualified.substring(name.length()));
|
||||
}
|
||||
}
|
||||
|
||||
if (paramList.isEmpty()) {
|
||||
if (handlesMissing()) {
|
||||
return parse(new ArrayList<List<String>>(0));
|
||||
return paramList;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
List<List<String>> paramList = new ArrayList<List<String>>(value.length);
|
||||
for (String nextParam : value) {
|
||||
if (nextParam.contains(",") == false) {
|
||||
paramList.add(Collections.singletonList(nextParam));
|
||||
} else {
|
||||
paramList.add(QueryUtil.splitQueryStringByCommasIgnoreEscape(nextParam));
|
||||
}
|
||||
}
|
||||
|
||||
return parse(paramList);
|
||||
|
||||
}
|
||||
|
||||
private void parseParams(Request theRequest, List<QualifiedParamList> paramList, String theQualifiedParamName, String theQualifier) {
|
||||
String[] value = theRequest.getParameters().get(theQualifiedParamName);
|
||||
if (value != null) {
|
||||
for (String nextParam : value) {
|
||||
if (nextParam.contains(",") == false) {
|
||||
paramList.add(QualifiedParamList.singleton(theQualifier, nextParam));
|
||||
} else {
|
||||
paramList.add(QualifiedParamList.splitQueryStringByCommasIgnoreEscape(theQualifier, nextParam));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initializeTypes(Method theMethod, Class<? extends Collection<?>> theOuterCollectionType, Class<? extends Collection<?>> theInnerCollectionType, Class<?> theParameterType) {
|
||||
// ignore for now
|
||||
|
|
|
@ -116,7 +116,7 @@ public class CodingListParam implements IQueryParameterOr, Iterable<CodingDt> {
|
|||
getCodings().clear();
|
||||
for (String string : theParameters) {
|
||||
CodingDt dt = new CodingDt();
|
||||
dt.setValueAsQueryToken(string);
|
||||
dt.setValueAsQueryToken(null, string);
|
||||
myCodings.add(dt);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ import java.util.List;
|
|||
import ca.uhn.fhir.model.api.IQueryParameterAnd;
|
||||
import ca.uhn.fhir.model.dstu.valueset.QuantityCompararatorEnum;
|
||||
import ca.uhn.fhir.parser.DataFormatException;
|
||||
import ca.uhn.fhir.rest.method.QualifiedParamList;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
|
||||
public class DateRangeParam implements IQueryParameterAnd {
|
||||
|
@ -210,7 +211,7 @@ public class DateRangeParam implements IQueryParameterAnd {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setValuesAsQueryTokens(List<List<String>> theParameters) throws InvalidRequestException {
|
||||
public void setValuesAsQueryTokens(List<QualifiedParamList> theParameters) throws InvalidRequestException {
|
||||
for (List<String> paramList : theParameters) {
|
||||
if (paramList.size() == 0) {
|
||||
continue;
|
||||
|
@ -220,7 +221,7 @@ public class DateRangeParam implements IQueryParameterAnd {
|
|||
}
|
||||
String param = paramList.get(0);
|
||||
QualifiedDateParam parsed = new QualifiedDateParam();
|
||||
parsed.setValueAsQueryToken(param);
|
||||
parsed.setValueAsQueryToken(null, param);
|
||||
addParam(parsed);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ package ca.uhn.fhir.rest.param;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import ca.uhn.fhir.rest.method.QualifiedParamList;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
|
||||
|
@ -29,6 +30,6 @@ interface IParamBinder {
|
|||
|
||||
List<List<String>> encode(Object theString) throws InternalErrorException;
|
||||
|
||||
Object parse(List<List<String>> theString) throws InternalErrorException, InvalidRequestException;
|
||||
Object parse(List<QualifiedParamList> theList) throws InternalErrorException, InvalidRequestException;
|
||||
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ public class IdentifierListParam implements IQueryParameterOr {
|
|||
public void setValuesAsQueryTokens(List<String> theParameters) {
|
||||
for (String string : theParameters) {
|
||||
IdentifierDt dt = new IdentifierDt();
|
||||
dt.setValueAsQueryToken(string);
|
||||
dt.setValueAsQueryToken(null, string);
|
||||
myIdentifiers.add(dt);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ import ca.uhn.fhir.context.ConfigurationException;
|
|||
import ca.uhn.fhir.model.api.PathSpecification;
|
||||
import ca.uhn.fhir.model.dstu.valueset.SearchParamTypeEnum;
|
||||
import ca.uhn.fhir.rest.annotation.IncludeParam;
|
||||
import ca.uhn.fhir.rest.method.QualifiedParamList;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
|
||||
|
@ -83,7 +84,7 @@ public class IncludeParameter extends BaseQueryParameter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object parse(List<List<String>> theString) throws InternalErrorException, InvalidRequestException {
|
||||
public Object parse(List<QualifiedParamList> theString) throws InternalErrorException, InvalidRequestException {
|
||||
Collection<PathSpecification> retValCollection = null;
|
||||
if (myInstantiableCollectionType!=null) {
|
||||
try {
|
||||
|
|
|
@ -59,7 +59,7 @@ public class QualifiedDateParam extends DateTimeDt implements IQueryParameterTyp
|
|||
* @param theString The string
|
||||
*/
|
||||
public QualifiedDateParam(String theString) {
|
||||
setValueAsQueryToken(theString);
|
||||
setValueAsQueryToken(null, theString);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -95,28 +95,28 @@ public class QualifiedDateParam extends DateTimeDt implements IQueryParameterTyp
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setValueAsQueryToken(String theParameter) {
|
||||
if (theParameter.length() < 2) {
|
||||
throw new DataFormatException("Invalid qualified date parameter: "+theParameter);
|
||||
public void setValueAsQueryToken(String theQualifier, String theValue) {
|
||||
if (theValue.length() < 2) {
|
||||
throw new DataFormatException("Invalid qualified date parameter: "+theValue);
|
||||
}
|
||||
|
||||
char char0 = theParameter.charAt(0);
|
||||
char char1 = theParameter.charAt(1);
|
||||
char char0 = theValue.charAt(0);
|
||||
char char1 = theValue.charAt(1);
|
||||
if (Character.isDigit(char0)) {
|
||||
setValueAsString(theParameter);
|
||||
setValueAsString(theValue);
|
||||
} else {
|
||||
int dateStart = 2;
|
||||
if (Character.isDigit(char1)) {
|
||||
dateStart = 1;
|
||||
}
|
||||
|
||||
String comparatorString = theParameter.substring(0, dateStart);
|
||||
String comparatorString = theValue.substring(0, dateStart);
|
||||
QuantityCompararatorEnum comparator = QuantityCompararatorEnum.VALUESET_BINDER.fromCodeString(comparatorString);
|
||||
if (comparator==null) {
|
||||
throw new DataFormatException("Invalid date qualifier: "+comparatorString);
|
||||
}
|
||||
|
||||
String dateString = theParameter.substring(dateStart);
|
||||
String dateString = theValue.substring(dateStart);
|
||||
setValueAsString(dateString);
|
||||
setComparator(comparator);
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ package ca.uhn.fhir.rest.param;
|
|||
import java.util.List;
|
||||
|
||||
import ca.uhn.fhir.model.api.IQueryParameterAnd;
|
||||
import ca.uhn.fhir.rest.method.QualifiedParamList;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
|
||||
|
@ -40,7 +41,7 @@ final class QueryParameterAndBinder implements IParamBinder {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object parse(List<List<String>> theString) throws InternalErrorException, InvalidRequestException {
|
||||
public Object parse(List<QualifiedParamList> theString) throws InternalErrorException, InvalidRequestException {
|
||||
IQueryParameterAnd dt;
|
||||
try {
|
||||
dt = myType.newInstance();
|
||||
|
|
|
@ -24,6 +24,7 @@ import java.util.Collections;
|
|||
import java.util.List;
|
||||
|
||||
import ca.uhn.fhir.model.api.IQueryParameterOr;
|
||||
import ca.uhn.fhir.rest.method.QualifiedParamList;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
|
||||
|
@ -41,7 +42,7 @@ final class QueryParameterOrBinder implements IParamBinder {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object parse(List<List<String>> theString) throws InternalErrorException, InvalidRequestException {
|
||||
public Object parse(List<QualifiedParamList> theString) throws InternalErrorException, InvalidRequestException {
|
||||
IQueryParameterOr dt;
|
||||
try {
|
||||
dt = myType.newInstance();
|
||||
|
|
|
@ -24,6 +24,7 @@ import java.util.Collections;
|
|||
import java.util.List;
|
||||
|
||||
import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||
import ca.uhn.fhir.rest.method.QualifiedParamList;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
|
||||
|
@ -41,18 +42,18 @@ final class QueryParameterTypeBinder implements IParamBinder {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object parse(List<List<String>> theString) throws InternalErrorException, InvalidRequestException {
|
||||
public Object parse(List<QualifiedParamList> theParams) throws InternalErrorException, InvalidRequestException {
|
||||
IQueryParameterType dt;
|
||||
try {
|
||||
dt = myType.newInstance();
|
||||
if (theString.size() == 0 || theString.get(0).size() == 0) {
|
||||
if (theParams.size() == 0 || theParams.get(0).size() == 0) {
|
||||
return dt;
|
||||
}
|
||||
if (theString.size() > 1 || theString.get(0).size() > 1) {
|
||||
if (theParams.size() > 1 || theParams.get(0).size() > 1) {
|
||||
throw new InvalidRequestException("Multiple values detected");
|
||||
}
|
||||
|
||||
dt.setValueAsQueryToken(theString.get(0).get(0));
|
||||
dt.setValueAsQueryToken(theParams.get(0).getQualifier(), theParams.get(0).get(0));
|
||||
} catch (InstantiationException e) {
|
||||
throw new InternalErrorException(e);
|
||||
} catch (IllegalAccessException e) {
|
||||
|
|
|
@ -13,17 +13,17 @@ public class ReferenceParam implements IQueryParameterType {
|
|||
}
|
||||
|
||||
public ReferenceParam(String theValue) {
|
||||
setValueAsQueryToken(theValue);
|
||||
setValueAsQueryToken(null, theValue);
|
||||
}
|
||||
|
||||
public ReferenceParam(String theChain, String theValue) {
|
||||
setValueAsQueryToken(theValue);
|
||||
setValueAsQueryToken(null, theValue);
|
||||
setChain(theChain);
|
||||
}
|
||||
|
||||
public ReferenceParam(Class<? extends IResource> theType, String theChain, String theValue) {
|
||||
setType(theType);
|
||||
setValueAsQueryToken(theValue);
|
||||
setValueAsQueryToken(null, theValue);
|
||||
setChain(theChain);
|
||||
}
|
||||
|
||||
|
@ -49,8 +49,8 @@ public class ReferenceParam implements IQueryParameterType {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setValueAsQueryToken(String theParameter) {
|
||||
myValue=theParameter;
|
||||
public void setValueAsQueryToken(String theQualifier, String theValue) {
|
||||
myValue=theValue;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
|
|||
import ca.uhn.fhir.model.dstu.composite.QuantityDt;
|
||||
import ca.uhn.fhir.model.dstu.valueset.SearchParamTypeEnum;
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.rest.method.QualifiedParamList;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
|
||||
|
@ -97,7 +98,7 @@ public class SearchParameter extends BaseQueryParameter {
|
|||
* @see ca.uhn.fhir.rest.param.IParameter#parse(java.util.List)
|
||||
*/
|
||||
@Override
|
||||
public Object parse(List<List<String>> theString) throws InternalErrorException, InvalidRequestException {
|
||||
public Object parse(List<QualifiedParamList> theString) throws InternalErrorException, InvalidRequestException {
|
||||
return myParamBinder.parse(theString);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package ca.uhn.fhir.rest.param;
|
||||
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.rest.server.Constants;
|
||||
|
||||
public class StringParameter extends StringDt {
|
||||
|
||||
|
@ -13,6 +14,16 @@ public class StringParameter extends StringDt {
|
|||
setValue(theValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValueAsQueryToken(String theQualifier, String theValue) {
|
||||
if (Constants.PARAMQUALIFIER_STRING_EXACT.equals(theQualifier)) {
|
||||
setExact(true);
|
||||
}else {
|
||||
setExact(false);
|
||||
}
|
||||
super.setValueAsQueryToken(theQualifier, theValue);
|
||||
}
|
||||
|
||||
public boolean isExact() {
|
||||
return myExact;
|
||||
}
|
||||
|
|
|
@ -74,7 +74,7 @@ public class Constants {
|
|||
public static final String FORMAT_XML = "xml";
|
||||
public static final String FORMAT_JSON = "json";
|
||||
public static final String PARAM_INCLUDE = "_include";
|
||||
public static final String PARAMNAME_SUFFIX_EXACT = ":exact";
|
||||
public static final String PARAMQUALIFIER_STRING_EXACT = ":exact";
|
||||
|
||||
static {
|
||||
Map<String, EncodingEnum> valToEncoding = new HashMap<String, EncodingEnum>();
|
||||
|
|
|
@ -1,50 +0,0 @@
|
|||
package ca.uhn.fhir.util;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR Library
|
||||
* %%
|
||||
* Copyright (C) 2014 University Health Network
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
public class QueryUtil {
|
||||
|
||||
public static List<String> splitQueryStringByCommasIgnoreEscape(String theInput){
|
||||
ArrayList<String> retVal = new ArrayList<String>();
|
||||
|
||||
StringTokenizer tok = new StringTokenizer(theInput,",");
|
||||
String prev=null;
|
||||
while (tok.hasMoreElements()) {
|
||||
String str = tok.nextToken();
|
||||
if (prev!=null&&prev.endsWith("\\")) {
|
||||
int idx = retVal.size()-1;
|
||||
String existing = retVal.get(idx);
|
||||
retVal.set(idx, existing.substring(0, existing.length()-1) + "," + str);
|
||||
}else {
|
||||
retVal.add(str);
|
||||
}
|
||||
|
||||
prev=str;
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package ca.uhn.fhir.testutil;
|
||||
package ca.uhn.fhir.rest.method;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
|
@ -6,20 +6,20 @@ import java.util.List;
|
|||
|
||||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.util.QueryUtil;
|
||||
import ca.uhn.fhir.rest.method.QualifiedParamList;
|
||||
|
||||
public class QueryUtilTest {
|
||||
public class QualifiedParamListTest {
|
||||
|
||||
@Test
|
||||
public void testSplit1() {
|
||||
List<String> actual = QueryUtil.splitQueryStringByCommasIgnoreEscape("aaa");
|
||||
List<String> actual = QualifiedParamList.splitQueryStringByCommasIgnoreEscape(null,"aaa");
|
||||
assertEquals(1, actual.size());
|
||||
assertEquals("aaa", actual.get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSplit2() {
|
||||
List<String> actual = QueryUtil.splitQueryStringByCommasIgnoreEscape("aaa,bbb");
|
||||
List<String> actual = QualifiedParamList.splitQueryStringByCommasIgnoreEscape(null,"aaa,bbb");
|
||||
assertEquals(2, actual.size());
|
||||
assertEquals("aaa", actual.get(0));
|
||||
assertEquals("bbb", actual.get(1));
|
||||
|
@ -27,7 +27,7 @@ public class QueryUtilTest {
|
|||
|
||||
@Test
|
||||
public void testSplit3() {
|
||||
List<String> actual = QueryUtil.splitQueryStringByCommasIgnoreEscape("aaa,b\\,bb");
|
||||
List<String> actual = QualifiedParamList.splitQueryStringByCommasIgnoreEscape(null,"aaa,b\\,bb");
|
||||
System.out.println(actual);
|
||||
assertEquals(2, actual.size());
|
||||
assertEquals("aaa", actual.get(0));
|
|
@ -5,13 +5,13 @@ import static org.junit.Assert.*;
|
|||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.rest.method.QualifiedParamList;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
|
||||
public class DateRangeParamTest {
|
||||
|
@ -90,9 +90,9 @@ public class DateRangeParamTest {
|
|||
|
||||
private static DateRangeParam create(String theLower, String theUpper) throws InvalidRequestException {
|
||||
DateRangeParam p = new DateRangeParam();
|
||||
List<List<String>> tokens=new ArrayList<List<String>>();
|
||||
tokens.add(Collections.singletonList(theLower));
|
||||
tokens.add(Collections.singletonList(theUpper));
|
||||
List<QualifiedParamList> tokens=new ArrayList<QualifiedParamList>();
|
||||
tokens.add(QualifiedParamList.singleton(null,theLower));
|
||||
tokens.add(QualifiedParamList.singleton(null,theUpper));
|
||||
p.setValuesAsQueryTokens(tokens);
|
||||
return p;
|
||||
}
|
||||
|
|
|
@ -387,13 +387,13 @@ public class IdentifierDt
|
|||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void setValueAsQueryToken(String theParameter) {
|
||||
int barIndex = theParameter.indexOf('|');
|
||||
public void setValueAsQueryToken(String theQualifier, String theValue) {
|
||||
int barIndex = theValue.indexOf('|');
|
||||
if (barIndex != -1) {
|
||||
setSystem(new UriDt(theParameter.substring(0, barIndex)));
|
||||
setValue(theParameter.substring(barIndex + 1));
|
||||
setSystem(new UriDt(theValue.substring(0, barIndex)));
|
||||
setValue(theValue.substring(barIndex + 1));
|
||||
} else {
|
||||
setValue(theParameter);
|
||||
setValue(theValue);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -996,19 +996,19 @@ public class FhirResourceDao<T extends IResource, X extends BaseResourceTable<T>
|
|||
return new QualifiedDateParam(theValueAsQueryToken);
|
||||
case NUMBER:
|
||||
QuantityDt qt = new QuantityDt();
|
||||
qt.setValueAsQueryToken(theValueAsQueryToken);
|
||||
qt.setValueAsQueryToken(null, theValueAsQueryToken);
|
||||
return qt;
|
||||
case QUANTITY:
|
||||
qt = new QuantityDt();
|
||||
qt.setValueAsQueryToken(theValueAsQueryToken);
|
||||
qt.setValueAsQueryToken(null, theValueAsQueryToken);
|
||||
return qt;
|
||||
case STRING:
|
||||
StringDt st = new StringDt();
|
||||
st.setValueAsQueryToken(theValueAsQueryToken);
|
||||
st.setValueAsQueryToken(null, theValueAsQueryToken);
|
||||
return st;
|
||||
case TOKEN:
|
||||
IdentifierDt id = new IdentifierDt();
|
||||
id.setValueAsQueryToken(theValueAsQueryToken);
|
||||
id.setValueAsQueryToken(null, theValueAsQueryToken);
|
||||
return id;
|
||||
case COMPOSITE:
|
||||
case REFERENCE:
|
||||
|
|
Loading…
Reference in New Issue