com.wesleyhome.dao.processor.CodeGenerationHelper.java Source code

Java tutorial

Introduction

Here is the source code for com.wesleyhome.dao.processor.CodeGenerationHelper.java

Source

/*
 * Copyright 2014 Justin Wesley
 *
 * 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 com.wesleyhome.dao.processor;

import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.lang.model.element.Element;
import javax.lang.model.type.TypeMirror;
import javax.persistence.criteria.Predicate;
import org.apache.commons.lang3.StringUtils;
import com.sun.codemodel.JArray;
import com.sun.codemodel.JBlock;
import com.sun.codemodel.JClass;
import com.sun.codemodel.JCodeModel;
import com.sun.codemodel.JExpr;
import com.sun.codemodel.JInvocation;
import com.sun.codemodel.JMethod;
import com.sun.codemodel.JMod;
import com.sun.codemodel.JType;
import com.sun.codemodel.JTypeVar;
import com.sun.codemodel.JVar;
import com.wesleyhome.dao.annotations.ReturnType;
import com.wesleyhome.dao.api.FilterMetadata;
import com.wesleyhome.dao.processor.model.EntityInfo;
import com.wesleyhome.dao.processor.model.MappingType;
import com.wesleyhome.dao.processor.model.ParamInfo;
import com.wesleyhome.dao.processor.model.ReturnInfo;
import com.wesleyhome.dao.processor.model.TypeVarInfo;

public class CodeGenerationHelper {
    public static final String APPLY_FILTERS_METHOD = "applyFilters";
    private static final String PREDICATE_LIST = "predicateList";
    public static final String FILTER_METADATA_PARAM = "filterMetadata";
    public static final String SORT_ORDER_PAGINATE_PARAM = "sortOrder";
    public static final String SORT_FIELD_PAGINATE_PARAM = "sortField";
    public static final String PAGE_SIZE_PAGINATE_PARAM = "pageSize";
    public static final String FIRST_RESULT_PAGINATE_PARAM = "first";

    public static void applyParameters(final JCodeModel model, final List<ParamInfo> paramInfoList,
            final JMethod method) {
        for (ParamInfo paramInfo : paramInfoList) {
            String parameterClassName = paramInfo.parameterClassName;
            Map<String, JTypeVar> typeParams = getTypeParamMap(method.typeParams());
            if (Void.class.getName().equals(parameterClassName)) {
                String typeVarName = paramInfo.paramClassTypeVar;
                JTypeVar jTypeVar = typeParams.get(typeVarName);
                method.param(jTypeVar, paramInfo.parameterName);
            } else {
                JClass parameterClassRef = getClassRef(model, parameterClassName);
                if (paramInfo.parameterClassVarList != null) {
                    List<String> list = paramInfo.parameterClassVarList;
                    for (String paramVar : list) {
                        JTypeVar typeParam = typeParams.get(paramVar);
                        parameterClassRef = parameterClassRef.narrow(typeParam);
                    }
                }
                if (paramInfo.isCollection) {
                    parameterClassRef = model.ref(Collection.class).narrow(parameterClassRef);
                }
                method.param(parameterClassRef, paramInfo.parameterName);
            }
        }
    }

    private static Map<String, JTypeVar> getTypeParamMap(final JTypeVar[] typeParams) {
        Map<String, JTypeVar> map = new HashMap<>();
        for (JTypeVar jTypeVar : typeParams) {
            String fullName = jTypeVar.fullName();
            map.put(fullName, jTypeVar);
        }
        return map;
    }

    /**
     * @param model
     * @param method
     * @param returnInfo
     * @return
     */
    public static JType getReturnType(final JCodeModel model, final JMethod method, final ReturnInfo returnInfo) {
        String returnClassString = returnInfo.returnClassString;
        if (Void.class.getName().equals(returnClassString)) {
            return model.VOID;
        }
        JType returnClass = null;
        String returnClassTypeVar = returnInfo.returnClassVar;
        Map<String, JTypeVar> typeParamMap = getTypeParamMap(method.typeParams());
        if (returnClassTypeVar != null) {
            returnClass = typeParamMap.get(returnClassTypeVar);
        } else {
            returnClass = getClassRef(model, returnClassString);
        }
        ReturnType returnType = returnInfo.returnType;
        String keyClassTypeVar = returnInfo.keyClassVar;
        switch (returnType) {
        case LIST:
            return model.ref(List.class).narrow(returnClass);
        case SET:
            return model.ref(Set.class).narrow(returnClass);
        case MAP_TO_SINGLE:
            JType keyClassRef = null;
            if (keyClassTypeVar != null) {
                keyClassRef = typeParamMap.get(keyClassTypeVar);
            } else {
                keyClassRef = getClassRef(model, returnInfo.keyClassString);
            }
            return model.ref(Map.class).narrow(keyClassRef).narrow(returnClass);
        case MAP_TO_LIST:
            keyClassRef = null;
            if (keyClassTypeVar != null) {
                keyClassRef = typeParamMap.get(keyClassTypeVar);
            } else {
                keyClassRef = getClassRef(model, returnInfo.keyClassString);
            }
            return model.ref(Map.class).narrow(keyClassRef).narrow(model.ref(List.class).narrow(returnClass));
        case SINGLE:
        default:
            return returnClass;
        }
    }

    public static void addTypeVars(final JCodeModel model, final JMethod method,
            final List<TypeVarInfo> typeVarList) {
        if (typeVarList != null) {
            for (TypeVarInfo typeVarInfo : typeVarList) {
                String varName = typeVarInfo.varName;
                String boundClass = typeVarInfo.boundClassName;
                if (StringUtils.isNotBlank(boundClass)) {
                    method.generify(varName, getClassRef(model, boundClass));
                } else {
                    method.generify(varName);
                }
            }
        }
    }

    /**
     * @param model
     * @param returnClassString
     * @return
     * @throws ClassNotFoundException
     */
    public static JClass getClassRef(final JCodeModel model, final String returnClassString) {
        // first see if we created it
        JClass returnClass = model._getClass(returnClassString);
        if (returnClass == null) {
            try {
                // lets see if the class is in the class path
                Class<?> returnClazz = Class.forName(returnClassString);
                returnClass = model.ref(returnClazz);
            } catch (ClassNotFoundException e1) {
                returnClass = model.ref(returnClassString);
            }
        }
        return returnClass;
    }

    public static JClass getDAOImplementation(final JCodeModel model, final EntityInfo info) {
        String packageName = getPackageName(info);
        String daoImplClassName = String.format("%s.%s", packageName, defineImplementationName(info));
        JClass daoImpl = getClassRef(model, daoImplClassName);
        return daoImpl;
    }

    public static JClass getDAOInterface(final JCodeModel model, final EntityInfo info) {
        String packageName = getPackageName(info);
        String daoInterfaceClassName = String.format("%s.%s", packageName, defineInterfaceName(info));
        JClass daoInterface = getClassRef(model, daoInterfaceClassName);
        return daoInterface;
    }

    public static String defineImplementationName(final EntityInfo entityInfo) {
        return String.format("%s%sDAOImpl", entityInfo.isAbstract() ? "Abstract" : "", entityInfo.getEntityName());
    }

    public static String defineInterfaceName(final EntityInfo entityInfo) {
        return String.format("%sDAO", entityInfo.getEntityName());
    }

    public static String getPackageName(final EntityInfo entityInfo) {
        String basePackage = entityInfo.packageName();
        String subPackageName = entityInfo.getSubPackageName();
        return String.format("%s%s.dao", basePackage, subPackageName);
    }

    public static void addMethodParameters(final JCodeModel model, final JMethod method, final JClass fieldType,
            final String parameterName, final EntityInformationMap entityInfoMap, final MappingType mappingType) {
        String fullName = fieldType.fullName();
        switch (mappingType) {
        case UNIQUE_OBJECT:
        case OBJECT:
            addMethodParameters(method, fieldType, parameterName);
            break;
        case ONE_TO_ONE:
        case MANY_TO_ONE:
        default:
            addPrimaryKeyParameters(method, fieldType, parameterName, entityInfoMap.get(fullName), model);
            break;
        }
    }

    public static void addMethodParameters(final JMethod method, final JClass fieldType,
            final String parameterName) {
        method.param(JMod.FINAL, fieldType, parameterName);
    }

    public static void addPrimaryKeyParameters(final JMethod method, final JClass fieldType,
            final String parameterName, final EntityInfo foreignKeyInfo, final JCodeModel model) {
        List<Element> idElements = foreignKeyInfo.getIdElements();
        for (Element element : idElements) {
            addMethodParameter(model, method, element);
        }
    }

    /**
     * @param model
     * @param method
     * @param element
     */
    public static void addMethodParameter(final JCodeModel model, final JMethod method, final Element element) {
        TypeMirror fieldTypeMirror = element.asType();
        String fieldTypeString = fieldTypeMirror.toString();
        JClass fieldType = model.ref(fieldTypeString);
        addMethodParameters(method, fieldType, element.getSimpleName().toString());
    }

    /**
     * final int first, final int pageSize, final String sortField, final String sortOrder
     * @param model
     * @param method
     */
    public static void applyPaginateParameters(final JCodeModel model, final JMethod method) {
        method.param(JMod.FINAL, int.class, FIRST_RESULT_PAGINATE_PARAM);
        method.param(JMod.FINAL, int.class, PAGE_SIZE_PAGINATE_PARAM);
        method.param(JMod.FINAL, String.class, SORT_FIELD_PAGINATE_PARAM);
        method.param(JMod.FINAL, String.class, SORT_ORDER_PAGINATE_PARAM);
    }

    public static void applyFilterParameters(final JCodeModel model, final JMethod method,
            final JClass entityTypeClass) {
        method.param(JMod.FINAL, model.ref(FilterMetadata.class), FILTER_METADATA_PARAM);
    }

    public static JVar findParam(final List<JVar> params, final String variableName) {
        for (JVar jVar : params) {
            if (jVar.name().endsWith(variableName)) {
                return jVar;
            }
        }
        return null;
    }

    public static void applyFilters(final JMethod method, final JCodeModel model, final JBlock body,
            final JVar cqVar, final JVar rootVar) {
        JVar filterParam = findParam(method.params(), FILTER_METADATA_PARAM);
        JClass predicateListType = model.ref(List.class).narrow(Predicate.class);
        JVar predicateListVar = body.decl(predicateListType, PREDICATE_LIST,
                JExpr._this().invoke(APPLY_FILTERS_METHOD).arg(rootVar).arg(filterParam));
        JArray newArray = JExpr.newArray(model.ref(Predicate.class), 0);
        JInvocation predicateArrInvoke = predicateListVar.invoke("toArray").arg(newArray);
        body.add(cqVar.invoke("where").arg(predicateArrInvoke));
    }
}