Introduce the ability for search parameters to have qualifiers, and add StringParameter to allow exact string matches

This commit is contained in:
jamesagnew 2014-05-16 08:34:31 -04:00
parent 54ab77d51a
commit 610bb542ca
30 changed files with 252 additions and 155 deletions

View File

@ -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>

View File

@ -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;
/**
*

View File

@ -23,25 +23,32 @@ 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>
* <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>
* <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();
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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);
}
/**

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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) {

View File

@ -84,14 +84,14 @@ public class SearchMethodBinding extends BaseResourceReturningMethodBinding {
if (myQueryName != null) {
queryStringArgs.put(Constants.PARAM_QUERY, Collections.singletonList(myQueryName));
}
String resourceName = getResourceName();
GetClientInvocation retVal = createSearchInvocation(resourceName, queryStringArgs);
if (theArgs != null) {
for (int idx = 0; idx < theArgs.length; idx++) {
IParameter nextParam = getParameters().get(idx);
nextParam.translateClientArgumentIntoQueryArgument(theArgs[idx], queryStringArgs,retVal);
nextParam.translateClientArgumentIntoQueryArgument(theArgs[idx], queryStringArgs, retVal);
}
}
@ -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());
return false;
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) {

View File

@ -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();
@ -76,31 +75,46 @@ 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));
}else {
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));
}
}
}
return parse(paramList);
}
@Override
public void initializeTypes(Method theMethod, Class<? extends Collection<?>> theOuterCollectionType, Class<? extends Collection<?>> theInnerCollectionType, Class<?> theParameterType) {
// ignore for now

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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 {

View File

@ -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);
}

View File

@ -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();

View File

@ -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();

View File

@ -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) {

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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>();

View File

@ -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;
}
}

View File

@ -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));

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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: