Java tutorial
/* * 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)); } }