Package ca.uhn.fhir.rest.param

Source Code of ca.uhn.fhir.rest.param.ParameterUtil

package ca.uhn.fhir.rest.param;

/*
* #%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 static org.apache.commons.lang3.StringUtils.*;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.time.DateUtils;

import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.model.api.IQueryParameterOr;
import ca.uhn.fhir.model.api.IQueryParameterType;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.Include;
import ca.uhn.fhir.model.api.PathSpecification;
import ca.uhn.fhir.model.api.TagList;
import ca.uhn.fhir.model.api.annotation.Description;
import ca.uhn.fhir.model.api.annotation.TagListParam;
import ca.uhn.fhir.model.primitive.InstantDt;
import ca.uhn.fhir.model.primitive.IntegerDt;
import ca.uhn.fhir.rest.annotation.Count;
import ca.uhn.fhir.rest.annotation.IdParam;
import ca.uhn.fhir.rest.annotation.IncludeParam;
import ca.uhn.fhir.rest.annotation.OptionalParam;
import ca.uhn.fhir.rest.annotation.RequiredParam;
import ca.uhn.fhir.rest.annotation.ResourceParam;
import ca.uhn.fhir.rest.annotation.ServerBase;
import ca.uhn.fhir.rest.annotation.Since;
import ca.uhn.fhir.rest.annotation.Sort;
import ca.uhn.fhir.rest.annotation.TransactionParam;
import ca.uhn.fhir.rest.annotation.VersionIdParam;
import ca.uhn.fhir.rest.method.QualifiedParamList;
import ca.uhn.fhir.util.ReflectionUtil;

public class ParameterUtil {

  private static final Set<Class<?>> BINDABLE_INTEGER_TYPES;
  private static final Set<Class<?>> BINDABLE_TIME_TYPES;

  static {
    HashSet<Class<?>> intTypes = new HashSet<Class<?>>();
    intTypes.add(IntegerDt.class);
    intTypes.add(Integer.class);
    BINDABLE_INTEGER_TYPES = Collections.unmodifiableSet(intTypes);

    HashSet<Class<?>> timeTypes = new HashSet<Class<?>>();
    timeTypes.add(InstantDt.class);
    timeTypes.add(Date.class);
    timeTypes.add(Calendar.class);
    BINDABLE_TIME_TYPES = Collections.unmodifiableSet(timeTypes);

  }

  public static Integer findIdParameterIndex(Method theMethod) {
    return findParamAnnotationIndex(theMethod, IdParam.class);
  }

  // public static Integer findSinceParameterIndex(Method theMethod) {
  // return findParamIndex(theMethod, Since.class);
  // }

  public static Integer findTagListParameterIndex(Method theMethod) {
    return findParamAnnotationIndex(theMethod, TagListParam.class);
  }

  public static Integer findVersionIdParameterIndex(Method theMethod) {
    return findParamAnnotationIndex(theMethod, VersionIdParam.class);
  }

  public static Object fromInstant(Class<?> theType, InstantDt theArgument) {
    if (theType.equals(InstantDt.class)) {
      if (theArgument == null) {
        return new InstantDt();
      }
      return theArgument;
    }
    if (theType.equals(Date.class)) {
      if (theArgument == null) {
        return null;
      }
      return theArgument.getValue();
    }
    if (theType.equals(Calendar.class)) {
      if (theArgument == null) {
        return null;
      }
      return DateUtils.toCalendar(theArgument.getValue());
    }
    throw new IllegalArgumentException("Invalid instant type:" + theType);
  }

  public static Object fromInteger(Class<?> theType, IntegerDt theArgument) {
    if (theType.equals(IntegerDt.class)) {
      if (theArgument == null) {
        return new IntegerDt();
      }
      return theArgument;
    }
    if (theType.equals(Integer.class)) {
      if (theArgument == null) {
        return null;
      }
      return theArgument.getValue();
    }
    throw new IllegalArgumentException("Invalid Integer type:" + theType);
  }

  public static Set<Class<?>> getBindableInstantTypes() {
    return BINDABLE_TIME_TYPES;
  }

  public static Set<Class<?>> getBindableIntegerTypes() {
    return BINDABLE_INTEGER_TYPES;
  }

  @SuppressWarnings("unchecked")
  public static List<IParameter> getResourceParameters(Method theMethod) {
    List<IParameter> parameters = new ArrayList<IParameter>();

    Class<?>[] parameterTypes = theMethod.getParameterTypes();
    int paramIndex = 0;
    for (Annotation[] annotations : theMethod.getParameterAnnotations()) {

      IParameter param = null;
      Class<?> parameterType = parameterTypes[paramIndex];
      Class<? extends java.util.Collection<?>> outerCollectionType = null;
      Class<? extends java.util.Collection<?>> innerCollectionType = null;
      if (TagList.class.isAssignableFrom(parameterType)) {
        // TagList is handled directly within the method bindings
        param = new NullParameter();
      } else {
        if (Collection.class.isAssignableFrom(parameterType)) {
          innerCollectionType = (Class<? extends java.util.Collection<?>>) parameterType;
          parameterType = ReflectionUtil.getGenericCollectionTypeOfMethodParameter(theMethod, paramIndex);
        }
        if (Collection.class.isAssignableFrom(parameterType)) {
          outerCollectionType = innerCollectionType;
          innerCollectionType = (Class<? extends java.util.Collection<?>>) parameterType;
          parameterType = ReflectionUtil.getGenericCollectionTypeOfMethodParameter(theMethod, paramIndex);
        }
        if (Collection.class.isAssignableFrom(parameterType)) {
          throw new ConfigurationException("Argument #" + paramIndex + " of Method '" + theMethod.getName() + "' in type '" + theMethod.getDeclaringClass().getCanonicalName() + "' is of an invalid generic type (can not be a collection of a collection of a collection)");
        }
      }
      if (parameterType.equals(HttpServletRequest.class) || parameterType.equals(ServletRequest.class)) {
        param = new ServletRequestParameter();
      } else if (parameterType.equals(HttpServletResponse.class) || parameterType.equals(ServletResponse.class)) {
        param = new ServletResponseParameter();
      } else {
        for (int i = 0; i < annotations.length && param == null; i++) {
          Annotation nextAnnotation = annotations[i];

          if (nextAnnotation instanceof RequiredParam) {
            SearchParameter parameter = new SearchParameter();
            parameter.setName(((RequiredParam) nextAnnotation).name());
            parameter.setRequired(true);
            parameter.setType(parameterType, innerCollectionType, outerCollectionType);
            extractDescription(parameter, annotations);
            param = parameter;
          } else if (nextAnnotation instanceof OptionalParam) {
            SearchParameter parameter = new SearchParameter();
            parameter.setName(((OptionalParam) nextAnnotation).name());
            parameter.setRequired(false);
            parameter.setType(parameterType, innerCollectionType, outerCollectionType);
            extractDescription(parameter, annotations);
            param = parameter;
          } else if (nextAnnotation instanceof IncludeParam) {
            Class<? extends Collection<Include>> instantiableCollectionType;
            Class<?> specType;

            if (parameterType == String.class) {
              instantiableCollectionType = null;
              specType = String.class;
            } else if ((parameterType != Include.class && parameterType != PathSpecification.class) || innerCollectionType == null || outerCollectionType != null) {
              throw new ConfigurationException("Method '" + theMethod.getName() + "' is annotated with @" + IncludeParam.class.getSimpleName() + " but has a type other than Collection<" + Include.class.getSimpleName() + ">");
            } else {
              instantiableCollectionType = (Class<? extends Collection<Include>>) CollectionBinder.getInstantiableCollectionType(innerCollectionType, "Method '" + theMethod.getName() + "'");
              specType = parameterType;
            }

            param = new IncludeParameter((IncludeParam) nextAnnotation, instantiableCollectionType, specType);
          } else if (nextAnnotation instanceof ResourceParam) {
            if (!IResource.class.isAssignableFrom(parameterType)) {
              throw new ConfigurationException("Method '" + theMethod.getName() + "' is annotated with @" + ResourceParam.class.getSimpleName() + " but has a type that is not an implemtation of " + IResource.class.getCanonicalName());
            }
            param = new ResourceParameter((Class<? extends IResource>) parameterType);
          } else if (nextAnnotation instanceof IdParam || nextAnnotation instanceof VersionIdParam) {
            param = new NullParameter();
          } else if (nextAnnotation instanceof ServerBase) {
            param = new ServerBaseParameter();
          } else if (nextAnnotation instanceof Since) {
            param = new SinceParameter();
          } else if (nextAnnotation instanceof Count) {
            param = new CountParameter();
          } else if (nextAnnotation instanceof Sort) {
            param = new SortParameter();
          } else if (nextAnnotation instanceof TransactionParam) {
            param = new TransactionParameter();
          } else {
            continue;
          }

        }

      }

      if (param == null) {
        throw new ConfigurationException("Parameter #" + ((paramIndex+1))+"/" + (parameterTypes.length) + " of method '" + theMethod.getName() + "' on type '" + theMethod.getDeclaringClass().getCanonicalName()
            + "' has no recognized FHIR interface parameter annotations. Don't know how to handle this parameter");
      }

      param.initializeTypes(theMethod, outerCollectionType, innerCollectionType, parameterType);
      parameters.add(param);

      paramIndex++;
    }
    return parameters;
  }

  public static InstantDt toInstant(Object theArgument) {
    if (theArgument instanceof InstantDt) {
      return (InstantDt) theArgument;
    }
    if (theArgument instanceof Date) {
      return new InstantDt((Date) theArgument);
    }
    if (theArgument instanceof Calendar) {
      return new InstantDt((Calendar) theArgument);
    }
    return null;
  }

  public static IntegerDt toInteger(Object theArgument) {
    if (theArgument instanceof IntegerDt) {
      return (IntegerDt) theArgument;
    }
    if (theArgument instanceof Integer) {
      return new IntegerDt((Integer) theArgument);
    }
    return null;
  }

  private static void extractDescription(SearchParameter theParameter, Annotation[] theAnnotations) {
    for (Annotation annotation : theAnnotations) {
      if (annotation instanceof Description) {
        Description desc = (Description) annotation;
        if (isNotBlank(desc.formalDefinition())) {
          theParameter.setDescription(desc.formalDefinition());
        } else {
          theParameter.setDescription(desc.shortDefinition());
        }
      }
    }
  }

  private static Integer findParamAnnotationIndex(Method theMethod, Class<?> toFind) {
    int paramIndex = 0;
    for (Annotation[] annotations : theMethod.getParameterAnnotations()) {
      for (int annotationIndex = 0; annotationIndex < annotations.length; annotationIndex++) {
        Annotation nextAnnotation = annotations[annotationIndex];
        Class<? extends Annotation> class1 = nextAnnotation.getClass();
        if (toFind.isAssignableFrom(class1)) {
          return paramIndex;
        }
      }
      paramIndex++;
    }
    return null;
  }

  public static IQueryParameterOr singleton(final IQueryParameterType theParam) {
    return new IQueryParameterOr() {

      @Override
      public void setValuesAsQueryTokens(QualifiedParamList theParameters) {
        if (theParameters.isEmpty()) {
          return;
        }
        if (theParameters.size() > 1) {
          throw new IllegalArgumentException("Type " + theParam.getClass().getCanonicalName() + " does not support multiple values");
        }
        theParam.setValueAsQueryToken(theParameters.getQualifier(), theParameters.get(0));
      }

      @Override
      public List<IQueryParameterType> getValuesAsQueryTokens() {
        return Collections.singletonList(theParam);
      }
    };
  }

}
TOP

Related Classes of ca.uhn.fhir.rest.param.ParameterUtil

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.