org.codehaus.grepo.procedure.compile.ProcedureCompilationStrategyImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.codehaus.grepo.procedure.compile.ProcedureCompilationStrategyImpl.java

Source

/*
 * Copyright 2009 Grepo Committers.
 *
 * 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.
 */

package org.codehaus.grepo.procedure.compile;

import java.util.Collections;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.codehaus.grepo.core.annotation.Param;
import org.codehaus.grepo.core.exception.ConfigurationException;
import org.codehaus.grepo.procedure.annotation.GenericProcedure;
import org.codehaus.grepo.procedure.aop.ProcedureMethodParameterInfo;
import org.codehaus.grepo.procedure.context.ProcedureExecutionContext;
import org.codehaus.grepo.procedure.context.StoredProcedureImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.object.StoredProcedure;

/**
 * Default implementation of {@link ProcedureCompilationStrategy}.
 *
 * @author dguggi
 */
public class ProcedureCompilationStrategyImpl implements ProcedureCompilationStrategy {

    private static final Logger logger = LoggerFactory.getLogger(ProcedureCompilationStrategyImpl.class);

    /**
     * {@inheritDoc}
     */
    public StoredProcedure compile(ProcedureMethodParameterInfo pmpi, ProcedureExecutionContext context) {
        GenericProcedure annotation = pmpi.getMethodAnnotation(GenericProcedure.class);
        List<ProcedureParamDescriptor> params = ProcedureCompilationUtils.collectParams(pmpi, context);

        validateParamNames(annotation, pmpi, params);

        StoredProcedure storedProcedure = new StoredProcedureImpl(context.getDataSource(), annotation.sql());
        storedProcedure.setFunction(annotation.function());

        if (ProcedureCompilationUtils.allParamsHaveValidIndex(params)) {
            // all parameters have valid index defined...
            declareParameters(storedProcedure, params, true);
        } else if (storedProcedure.isFunction()) {
            declareParametersForFunction(storedProcedure, params);
        } else {
            declareParametersForProcedure(storedProcedure, params);
        }

        storedProcedure.compile();
        logger.debug("Compiled stored procedure: {}", storedProcedure);

        return storedProcedure;
    }

    /**
     * Validates procedure parameters.
     *
     * @param genericProcedure The annotation.
     * @param pmpi The method parameter info.
     * @param params The collected procedure param descriptors.
     * @throws ConfigurationException if configuration is invalid.
     */
    protected void validateParamNames(GenericProcedure genericProcedure, ProcedureMethodParameterInfo pmpi,
            List<ProcedureParamDescriptor> params) throws ConfigurationException {
        if (StringUtils.isNotEmpty(genericProcedure.returnParamName())) {
            ProcedureParamDescriptor desc = ProcedureCompilationUtils.getParamWithName(params,
                    genericProcedure.returnParamName());
            if (desc == null || desc.getType() == ProcedureParamType.IN) {
                String msg = String.format("Attribute returnParamName set to '%s' but no "
                        + "appropriate Out/InOut-Parameter is defined", genericProcedure.returnParamName());
                throw new ConfigurationException(msg);
            }
        }

        // validate names for method-parameters annotated with @Param
        List<Param> list = pmpi.getParameterAnnotations(Param.class);
        for (Param param : list) {
            ProcedureParamDescriptor desc = ProcedureCompilationUtils.getParamWithName(params, param.value());
            if (desc == null) {
                String msg = String.format("Procedure parameter '%s' is invalid", param.value());
                throw new ConfigurationException(msg);
            }
        }
    }

    /**
     * Used to declare procedure parameters for a function. Parameters are defined in the following order:<br>
     * <br>
     * <ul>
     * <li>OUT Params</li>
     * <li>INOUT Params</li>
     * <li>IN Params</li>
     * </ul>
     *
     * @param storedProcedure The procedure.
     * @param params The params.
     */
    protected void declareParametersForFunction(StoredProcedure storedProcedure,
            List<ProcedureParamDescriptor> params) {
        // declare out, in-out, in prameters in that order...
        List<ProcedureParamDescriptor> outParams = ProcedureCompilationUtils.getParamsWithType(params,
                ProcedureParamType.OUT);
        declareParameters(storedProcedure, outParams, false);

        List<ProcedureParamDescriptor> inoutParams = ProcedureCompilationUtils.getParamsWithType(params,
                ProcedureParamType.INOUT);
        declareParameters(storedProcedure, inoutParams, false);

        List<ProcedureParamDescriptor> inParams = ProcedureCompilationUtils.getParamsWithType(params,
                ProcedureParamType.IN);
        declareParameters(storedProcedure, inParams, false);
    }

    /**
     * Used to declare procedure parameters for a procedure. Parameters are defined in the following order:<br>
     * <br>
     * <ul>
     * <li>IN Params</li>
     * <li>INOUT Params</li>
     * <li>OUT Params</li>
     * </ul>
     *
     * @param storedProcedure The procedure.
     * @param params The params.
     */
    protected void declareParametersForProcedure(StoredProcedure storedProcedure,
            List<ProcedureParamDescriptor> params) {
        // declare in, in-out, out prameters in that order...
        List<ProcedureParamDescriptor> inParams = ProcedureCompilationUtils.getParamsWithType(params,
                ProcedureParamType.IN);
        declareParameters(storedProcedure, inParams, false);

        List<ProcedureParamDescriptor> inoutParams = ProcedureCompilationUtils.getParamsWithType(params,
                ProcedureParamType.INOUT);
        declareParameters(storedProcedure, inoutParams, false);

        List<ProcedureParamDescriptor> outParams = ProcedureCompilationUtils.getParamsWithType(params,
                ProcedureParamType.OUT);
        declareParameters(storedProcedure, outParams, false);
    }

    /**
     * Declares all procedure-parameters.
     *
     * @param storedProcedure The procedure.
     * @param list A list of procedure parameters.
     * @param forceSort If set to {@code true}, the {@code list} will definitely be sorted.
     */
    protected void declareParameters(StoredProcedure storedProcedure, List<ProcedureParamDescriptor> list,
            boolean forceSort) {
        if (forceSort || ProcedureCompilationUtils.allParamsHaveValidIndex(list)) {
            Collections.sort(list, new ProcedureParamDescriptorComparator());
        }
        for (ProcedureParamDescriptor desc : list) {
            storedProcedure.declareParameter(desc.getSqlParameter());
            logger.debug("Declared procedure param name={}, type={}", desc.getName(), desc.getSqlParameter());
        }
    }

}