ca.uhn.fhir.rest.method.BaseOutcomeReturningMethodBindingWithResourceParam.java Source code

Java tutorial

Introduction

Here is the source code for ca.uhn.fhir.rest.method.BaseOutcomeReturningMethodBindingWithResourceParam.java

Source

package ca.uhn.fhir.rest.method;

import static org.apache.commons.lang3.StringUtils.defaultIfBlank;

/*
 * #%L
 * HAPI FHIR - Core Library
 * %%
 * Copyright (C) 2014 - 2016 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.lang.reflect.Modifier;

import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;

import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.rest.annotation.ResourceParam;
import ca.uhn.fhir.rest.client.BaseHttpClientInvocation;
import ca.uhn.fhir.rest.param.ResourceParameter;
import ca.uhn.fhir.rest.server.IResourceProvider;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;

abstract class BaseOutcomeReturningMethodBindingWithResourceParam extends BaseOutcomeReturningMethodBinding {
    private Integer myIdParamIndex;
    private String myResourceName;
    private int myResourceParameterIndex = -1;
    private Class<? extends IBaseResource> myResourceType;
    private Class<? extends IIdType> myIdParamType;
    private int myConditionalUrlIndex = -1;

    @SuppressWarnings("unchecked")
    public BaseOutcomeReturningMethodBindingWithResourceParam(Method theMethod, FhirContext theContext,
            Class<?> theMethodAnnotation, Object theProvider) {
        super(theMethod, theContext, theMethodAnnotation, theProvider);

        ResourceParameter resourceParameter = null;

        int index = 0;
        for (IParameter next : getParameters()) {
            if (next instanceof ResourceParameter) {
                resourceParameter = (ResourceParameter) next;
                if (resourceParameter.getMode() != ResourceParameter.Mode.RESOURCE) {
                    continue;
                }
                if (myResourceType != null) {
                    throw new ConfigurationException(
                            "Method " + theMethod.getName() + " on type " + theMethod.getDeclaringClass()
                                    + " has more than one @ResourceParam. Only one is allowed.");
                }

                myResourceType = resourceParameter.getResourceType();

                myResourceParameterIndex = index;
            } else if (next instanceof ConditionalParamBinder) {
                myConditionalUrlIndex = index;
            }
            index++;
        }

        if ((myResourceType == null || Modifier.isAbstract(myResourceType.getModifiers()))
                && (theProvider instanceof IResourceProvider)) {
            myResourceType = ((IResourceProvider) theProvider).getResourceType();
        }
        if (myResourceType == null) {
            throw new ConfigurationException("Unable to determine resource type for method: " + theMethod);
        }

        myResourceName = theContext.getResourceDefinition(myResourceType).getName();
        myIdParamIndex = MethodUtil.findIdParameterIndex(theMethod, getContext());
        if (myIdParamIndex != null) {
            myIdParamType = (Class<? extends IIdType>) theMethod.getParameterTypes()[myIdParamIndex];
        }

        if (resourceParameter == null) {
            throw new ConfigurationException("Method " + theMethod.getName() + " in type "
                    + theMethod.getDeclaringClass().getCanonicalName()
                    + " does not have a resource parameter annotated with @" + ResourceParam.class.getSimpleName());
        }

    }

    @Override
    protected void addParametersForServerRequest(RequestDetails theRequest, Object[] theParams) {
        if (myIdParamIndex != null) {
            theParams[myIdParamIndex] = MethodUtil.convertIdToType(theRequest.getId(), myIdParamType);
        }
        if (myResourceParameterIndex != -1) {
            IBaseResource resource = ((IBaseResource) theParams[myResourceParameterIndex]);
            String resourceId = resource.getIdElement().getIdPart();
            String urlId = theRequest.getId() != null ? theRequest.getId().getIdPart() : null;
            if (getContext().getVersion().getVersion() == FhirVersionEnum.DSTU1) {
                resource.setId(urlId);
            } else {
                if (getContext().getVersion().getVersion().isOlderThan(FhirVersionEnum.DSTU3) == false) {
                    resource.setId(theRequest.getId());
                }

                String matchUrl = null;
                if (myConditionalUrlIndex != -1) {
                    matchUrl = (String) theParams[myConditionalUrlIndex];
                    matchUrl = defaultIfBlank(matchUrl, null);
                }
                validateResourceIdAndUrlIdForNonConditionalOperation(resource, resourceId, urlId, matchUrl);
            }
        }
    }

    @Override
    public String getResourceName() {
        return myResourceName;
    }

    @Override
    public BaseHttpClientInvocation invokeClient(Object[] theArgs) throws InternalErrorException {
        IResource resource = (IResource) theArgs[myResourceParameterIndex]; // TODO: use IBaseResource
        if (resource == null) {
            throw new NullPointerException("Resource can not be null");
        }

        BaseHttpClientInvocation retVal = createClientInvocation(theArgs, resource);
        return retVal;
    }

    @Override
    protected void populateActionRequestDetailsForInterceptor(RequestDetails theRequestDetails,
            ActionRequestDetails theDetails, Object[] theMethodParams) {
        super.populateActionRequestDetailsForInterceptor(theRequestDetails, theDetails, theMethodParams);

        /*
         * If the method has no parsed resource parameter, we parse here in order to have something for the interceptor.
         */
        if (myResourceParameterIndex != -1) {
            theDetails.setResource((IBaseResource) theMethodParams[myResourceParameterIndex]);
        } else {
            theDetails.setResource(
                    ResourceParameter.parseResourceFromRequest(theRequestDetails, this, myResourceType));
        }

    }

    /**
     * Subclasses may override
     */
    @SuppressWarnings("unused")
    protected void validateResourceIdAndUrlIdForNonConditionalOperation(IBaseResource theResource,
            String theResourceId, String theUrlId, String theMatchUrl) {
        // nothing by default
    }

}