Package ca.uhn.fhir.rest.method

Source Code of ca.uhn.fhir.rest.method.BaseMethodBinding

package ca.uhn.fhir.rest.method;

import java.io.IOException;
import java.io.Reader;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;

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

import org.apache.commons.io.IOUtils;

import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.dstu.valueset.RestfulOperationSystemEnum;
import ca.uhn.fhir.model.dstu.valueset.RestfulOperationTypeEnum;
import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.rest.annotation.Create;
import ca.uhn.fhir.rest.annotation.Delete;
import ca.uhn.fhir.rest.annotation.History;
import ca.uhn.fhir.rest.annotation.Metadata;
import ca.uhn.fhir.rest.annotation.Read;
import ca.uhn.fhir.rest.annotation.Search;
import ca.uhn.fhir.rest.annotation.Update;
import ca.uhn.fhir.rest.client.BaseClientInvocation;
import ca.uhn.fhir.rest.client.exceptions.NonFhirResponseException;
import ca.uhn.fhir.rest.server.Constants;
import ca.uhn.fhir.rest.server.EncodingUtil;
import ca.uhn.fhir.rest.server.IResourceProvider;
import ca.uhn.fhir.rest.server.RestfulServer;
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;

public abstract class BaseMethodBinding {

  private Method myMethod;
  private FhirContext myContext;

  public BaseMethodBinding(Method theMethod, FhirContext theConetxt) {
    assert theMethod != null;
    assert theConetxt != null;

    myMethod = theMethod;
    myContext = theConetxt;
  }

  public FhirContext getContext() {
    return myContext;
  }

  public Method getMethod() {
    return myMethod;
  }

  public abstract BaseClientInvocation invokeClient(Object[] theArgs) throws InternalErrorException;

  public abstract RestfulOperationTypeEnum getResourceOperationType();

  public abstract RestfulOperationSystemEnum getSystemOperationType();

  public abstract boolean matches(Request theRequest);

  protected IParser createAppropriateParser(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode) throws IOException {
    IParser parser;
    if (Constants.CT_ATOM_XML.equals(theResponseMimeType)) {
      parser = getContext().newXmlParser();
    } else if (Constants.CT_FHIR_XML.equals(theResponseMimeType)) {
      parser = getContext().newXmlParser();
    } else {
      throw new NonFhirResponseException("Response contains non-FHIR content-type: " + theResponseMimeType, theResponseMimeType, theResponseStatusCode, IOUtils.toString(theResponseReader));
    }
    return parser;
  }

  public static BaseMethodBinding bindMethod(Class<? extends IResource> theReturnType, Method theMethod, FhirContext theContext, IResourceProvider theProvider) {
    Read read = theMethod.getAnnotation(Read.class);
    Search search = theMethod.getAnnotation(Search.class);
    Metadata conformance = theMethod.getAnnotation(Metadata.class);
    Create create = theMethod.getAnnotation(Create.class);
    Update update = theMethod.getAnnotation(Update.class);
    Delete delete = theMethod.getAnnotation(Delete.class);
    History history = theMethod.getAnnotation(History.class);
    // ** if you add another annotation above, also add it to the next line:
    if (!verifyMethodHasZeroOrOneOperationAnnotation(theMethod, read, search, conformance,create,update,delete,history)) {
      return null;
    }

    Class<? extends IResource> returnType = theReturnType;
    if (returnType == null) {
      if (read != null) {
        returnType = read.type();
      } else if (search != null) {
        returnType = search.type();
      }

      if (returnType == IResource.class) {
        throw new ConfigurationException("Could not determine return type for method '" + theMethod.getName() + "'. Try explicitly specifying one in the operation annotation.");
      }
    }

    if (read != null) {
      return new ReadMethodBinding(returnType, theMethod, theContext);
    } else if (search != null) {
      String queryName = search.queryName();
      return new SearchMethodBinding(returnType, theMethod, queryName, theContext);
    } else if (conformance != null) {
      return new ConformanceMethodBinding(theMethod, theContext);
    } else if (create != null) {
      return new CreateMethodBinding(theMethod, theContext);
    } else if (update != null) {
      return new UpdateMethodBinding(theMethod, theContext);
    } else if (delete != null) {
      return new DeleteMethodBinding(theMethod, theContext, theProvider);
    } else if (history != null) {
      return new HistoryMethodBinding(theMethod, theContext, theProvider);
    } else {
      throw new ConfigurationException("Did not detect any FHIR annotations on method '" + theMethod.getName() + "' on type: " + theMethod.getDeclaringClass().getCanonicalName());
    }

    // // each operation name must have a request type annotation and be
    // unique
    // if (null != read) {
    // return rm;
    // }
    //
    // SearchMethodBinding sm = new SearchMethodBinding();
    // if (null != search) {
    // sm.setRequestType(SearchMethodBinding.RequestType.GET);
    // } else if (null != theMethod.getAnnotation(PUT.class)) {
    // sm.setRequestType(SearchMethodBinding.RequestType.PUT);
    // } else if (null != theMethod.getAnnotation(POST.class)) {
    // sm.setRequestType(SearchMethodBinding.RequestType.POST);
    // } else if (null != theMethod.getAnnotation(DELETE.class)) {
    // sm.setRequestType(SearchMethodBinding.RequestType.DELETE);
    // } else {
    // return null;
    // }
    //
    // return sm;
  }

  public static boolean verifyMethodHasZeroOrOneOperationAnnotation(Method theNextMethod, Object... theAnnotations) {
    Object obj1 = null;
    for (Object object : theAnnotations) {
      if (object != null) {
        if (obj1 == null) {
          obj1 = object;
        } else {
          throw new ConfigurationException("Method " + theNextMethod.getName() + " on type '" + theNextMethod.getDeclaringClass().getSimpleName() + " has annotations @"
              + obj1.getClass().getSimpleName() + " and @" + object.getClass().getSimpleName() + ". Can not have both.");
        }

      }
    }
    if (obj1 == null) {
      return false;
      // throw new ConfigurationException("Method '" +
      // theNextMethod.getName() + "' on type '" +
      // theNextMethod.getDeclaringClass().getSimpleName() +
      // " has no FHIR method annotations.");
    }
    return true;
  }

  protected static List<IResource> toResourceList(Object response) throws InternalErrorException {
    if (response == null) {
      return Collections.emptyList();
    } else if (response instanceof IResource) {
      return Collections.singletonList((IResource) response);
    } else if (response instanceof Collection) {
      List<IResource> retVal = new ArrayList<IResource>();
      for (Object next : ((Collection<?>) response)) {
        retVal.add((IResource) next);
      }
      return retVal;
    } else {
      throw new InternalErrorException("Unexpected return type: " + response.getClass().getCanonicalName());
    }
  }

  public static EncodingUtil determineResponseEncoding(HttpServletRequest theRequest, Map<String, String[]> theParams) {
    String[] format = theParams.remove(Constants.PARAM_FORMAT);
    if (format != null) {
      for (String nextFormat : format) {
        EncodingUtil retVal = Constants.FORMAT_VAL_TO_ENCODING.get(nextFormat);
        if (retVal != null) {
          return retVal;
        }
      }
    }

    Enumeration<String> acceptValues = theRequest.getHeaders("Accept");
    if (acceptValues != null) {
      while (acceptValues.hasMoreElements()) {
        EncodingUtil retVal = Constants.FORMAT_VAL_TO_ENCODING.get(acceptValues.nextElement());
        if (retVal != null) {
          return retVal;
        }
      }
    }
    return EncodingUtil.XML;
  }

  public abstract void invokeServer(RestfulServer theServer, Request theRequest, HttpServletResponse theResponse) throws BaseServerResponseException, IOException;

  public abstract Object invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) throws IOException, BaseServerResponseException;

  public static BaseMethodBinding bindSystemMethod(Method theMethod, FhirContext theContext) {
    return bindMethod(null, theMethod, theContext, null);
  }

}
TOP

Related Classes of ca.uhn.fhir.rest.method.BaseMethodBinding

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.