package ca.uhn.fhir.rest.method;
/*
* #%L
* HAPI FHIR - Core Library
* %%
* Copyright (C) 2014 - 2017 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.lang.reflect.Method;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.hl7.fhir.instance.model.api.IBaseResource;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.RuntimeSearchParam;
import ca.uhn.fhir.model.api.IQueryParameterType;
import ca.uhn.fhir.rest.param.CompositeOrListParam;
import ca.uhn.fhir.rest.param.DateOrListParam;
import ca.uhn.fhir.rest.param.DateParam;
import ca.uhn.fhir.rest.param.NumberOrListParam;
import ca.uhn.fhir.rest.param.NumberParam;
import ca.uhn.fhir.rest.param.QuantityOrListParam;
import ca.uhn.fhir.rest.param.QuantityParam;
import ca.uhn.fhir.rest.param.ReferenceOrListParam;
import ca.uhn.fhir.rest.param.ReferenceParam;
import ca.uhn.fhir.rest.param.StringOrListParam;
import ca.uhn.fhir.rest.param.StringParam;
import ca.uhn.fhir.rest.param.TokenOrListParam;
import ca.uhn.fhir.rest.param.TokenParam;
import ca.uhn.fhir.rest.param.UriOrListParam;
import ca.uhn.fhir.rest.server.IDynamicSearchResourceProvider;
import ca.uhn.fhir.rest.server.SearchParameterMap;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
public class DynamicSearchParameter implements IParameter {
private Map<String, RuntimeSearchParam> myNameToParam = new HashMap<String, RuntimeSearchParam>();
public DynamicSearchParameter(IDynamicSearchResourceProvider theProvider) {
for (RuntimeSearchParam next : theProvider.getSearchParameters()) {
myNameToParam.put(next.getName(), next);
}
}
@Override
public void translateClientArgumentIntoQueryArgument(FhirContext theContext, Object theSourceClientArgument, Map<String, List<String>> theTargetQueryArguments, IBaseResource theTargetResource) throws InternalErrorException {
throw new UnsupportedOperationException("Dynamic search is not supported in client mode (use fluent client for dynamic-like searches)");
}
@SuppressWarnings("unchecked")
@Override
public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
SearchParameterMap retVal = new SearchParameterMap();
for (String next : theRequest.getParameters().keySet()) {
String qualifier = null;
String qualifiedParamName = next;
String unqualifiedParamName = next;
RuntimeSearchParam param = myNameToParam.get(next);
if (param == null) {
int colonIndex = next.indexOf(':');
int dotIndex = next.indexOf('.');
if (colonIndex != -1 || dotIndex != -1) {
int index;
if (colonIndex != -1 && dotIndex != -1) {
index = Math.min(colonIndex, dotIndex);
} else {
index = (colonIndex != -1) ? colonIndex : dotIndex;
}
qualifier = next.substring(index);
next = next.substring(0, index);
unqualifiedParamName = next;
param = myNameToParam.get(next);
}
}
if (param != null) {
for (String nextValue : theRequest.getParameters().get(qualifiedParamName)) {
QualifiedParamList paramList = QualifiedParamList.splitQueryStringByCommasIgnoreEscape(qualifier, nextValue);
FhirContext ctx = theRequest.getServer().getFhirContext();
switch (param.getParamType()) {
case COMPOSITE:
Class<? extends IQueryParameterType> left = toParamType(param.getCompositeOf().get(0));
Class<? extends IQueryParameterType> right = toParamType(param.getCompositeOf().get(0));
@SuppressWarnings({ "rawtypes" })
CompositeOrListParam compositeOrListParam = new CompositeOrListParam(left, right);
compositeOrListParam.setValuesAsQueryTokens(ctx, unqualifiedParamName, paramList);
retVal.add(next, compositeOrListParam);
break;
case DATE:
DateOrListParam dateOrListParam = new DateOrListParam();
dateOrListParam.setValuesAsQueryTokens(ctx, unqualifiedParamName, paramList);
retVal.add(next, dateOrListParam);
break;
case NUMBER:
NumberOrListParam numberOrListParam = new NumberOrListParam();
numberOrListParam.setValuesAsQueryTokens(ctx, unqualifiedParamName, paramList);
retVal.add(next, numberOrListParam);
break;
case QUANTITY:
QuantityOrListParam quantityOrListParam = new QuantityOrListParam();
quantityOrListParam.setValuesAsQueryTokens(ctx, unqualifiedParamName, paramList);
retVal.add(next, quantityOrListParam);
break;
case REFERENCE:
ReferenceOrListParam referenceOrListParam = new ReferenceOrListParam();
referenceOrListParam.setValuesAsQueryTokens(ctx, unqualifiedParamName, paramList);
retVal.add(next, referenceOrListParam);
break;
case STRING:
StringOrListParam stringOrListParam = new StringOrListParam();
stringOrListParam.setValuesAsQueryTokens(ctx, unqualifiedParamName, paramList);
retVal.add(next, stringOrListParam);
break;
case TOKEN:
TokenOrListParam tokenOrListParam = new TokenOrListParam();
tokenOrListParam.setValuesAsQueryTokens(ctx, unqualifiedParamName, paramList);
retVal.add(next, tokenOrListParam);
break;
case URI:
UriOrListParam uriOrListParam = new UriOrListParam();
uriOrListParam.setValuesAsQueryTokens(ctx, unqualifiedParamName, paramList);
retVal.add(next, uriOrListParam);
break;
case HAS:
// Should not happen
break;
}
}
}
}
return retVal;
}
private Class<? extends IQueryParameterType> toParamType(RuntimeSearchParam theRuntimeSearchParam) {
switch (theRuntimeSearchParam.getParamType()) {
case COMPOSITE:
throw new IllegalStateException("Composite subtype");
case DATE:
return DateParam.class;
case NUMBER:
return NumberParam.class;
case QUANTITY:
return QuantityParam.class;
case REFERENCE:
return ReferenceParam.class;
case STRING:
return StringParam.class;
case TOKEN:
return TokenParam.class;
default:
throw new IllegalStateException("null type");
}
}
@Override
public void initializeTypes(Method theMethod, Class<? extends Collection<?>> theOuterCollectionType, Class<? extends Collection<?>> theInnerCollectionType, Class<?> theParameterType) {
// nothing
}
}