/** * Copyright 2015 Santhosh Kumar Tekuri * * The JLibs authors license this file to you 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 jlibs.jdbc.annotations.processor; import jlibs.core.annotation.processing.AnnotationError; import jlibs.core.annotation.processing.Printer; import jlibs.core.lang.model.ModelUtil; import jlibs.core.util.CollectionUtil; import jlibs.jdbc.IncorrectResultSizeException; import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.ExecutableElement; import javax.lang.model.type.DeclaredType; import javax.lang.model.type.TypeMirror; import java.util.ArrayList; import java.util.List; import static jlibs.core.annotation.processing.Printer.MINUS; import static jlibs.core.annotation.processing.Printer.PLUS; /** * @author Santhosh Kumar T */ // @enhancement allow to return single/listOf column values public class SelectColumnMethod extends WhereMethod{ protected SelectColumnMethod(Printer printer, ExecutableElement method, AnnotationMirror mirror, Columns columns){ super(printer, method, mirror, columns); } protected void validateParamCount(){} private ColumnProperty getColumn(){ String columnProp = ModelUtil.getAnnotationValue(method, mirror, "column"); if(columnProp.length()>0){ ColumnProperty column = columns.findByProperty(columnProp); if(column==null) throw new AnnotationError(method, "invalid column property: "+columnProp); return column; }else{ ColumnProperty column = new ColumnProperty<ExecutableElement>(method, mirror){ @Override public String columnName(){ String value = ModelUtil.getAnnotationValue(method, mirror, "expression"); return replacePropertiesWithColumns(value); } @Override public String columnName(boolean quoted){ return '"'+columnName()+'"'; } @Override public String propertyName(){ return "__value"; } @Override public TypeMirror propertyType(){ TypeMirror returnType = method.getReturnType(); String s = ModelUtil.toString(returnType, false); if(s.startsWith("java.util.List<")) return ((List<? extends TypeMirror>)((DeclaredType)returnType).getTypeArguments()).get(0); else if(s.equals("java.util.List")) throw new AnnotationError(method, "the type of elements in returning List must be specified using Generics."); return returnType; } @Override public String getPropertyCode(String object){ throw new UnsupportedOperationException(); } @Override public String setPropertyCode(String object, String value){ throw new UnsupportedOperationException(); } @Override protected AnnotationMirror typeMapperMirror(){ return null; } }; column.validateType(); return column; } } @Override protected String[] code(){ ColumnProperty column = getColumn(); int assertMinmumCount = (Integer)ModelUtil.getAnnotationValue(method, mirror, "assertMinimumCount"); String columnType = ModelUtil.toString(column.propertyType(), true); CharSequence[] sequences = sql(); String sql = String.format("SELECT \"+%s+\" FROM \"+%s+\" %s", column.columnName(true), columns.tableName(true), sequences[0]); List<String> code = new ArrayList<String>(); String methodName = methodName(); CollectionUtil.addAll(code, String.format("jdbc.select%s(\"%s\", new RowMapper<%s>(){", methodName, sql, columnType), PLUS, String.format("public %s newRecord(ResultSet rs) throws SQLException{", columnType), PLUS ); if(methodName.equals("First") && assertMinmumCount!=-1) code.add("__found[0] = true;"); String rowMapperCode[] = column.getValueFromResultSet(1); if(rowMapperCode.length>1) code.add(rowMapperCode[0]); code.add("return "+column.toUserTypeCode(rowMapperCode[rowMapperCode.length-1])+';'); CollectionUtil.addAll(code, MINUS, "}", MINUS, '}'+ (sequences[1].length()>0 ? String.format(", %s", sequences[1]) : "") + ");" ); if(assertMinmumCount!=-1){ String pojoName = ((DeclaredType)printer.clazz.asType()).asElement().getSimpleName().toString(); if(methodName.equals("First")){ code.set(0, columnType+" __result = "+code.get(0)); code.add(0, "final boolean __found[] = { false };"); CollectionUtil.addAll(code, "if(!__found[0])", PLUS, "throw new "+ IncorrectResultSizeException.class.getSimpleName()+"(\""+pojoName+"\", 1, 0);", MINUS, "return __result;" ); }else{ code.set(0, "java.util.List<"+columnType+"> __result = "+code.get(0)); CollectionUtil.addAll(code, "if(__result.size()<"+assertMinmumCount+")", PLUS, "throw new "+ IncorrectResultSizeException.class.getSimpleName()+"(\""+pojoName+"\", "+assertMinmumCount+", __result.size());", MINUS, "return __result;" ); } }else code.set(0, "return "+code.get(0)); return code.toArray(new String[code.size()]); } protected String methodName(){ String returnType = ModelUtil.toString(method.getReturnType(), true); ColumnProperty column = getColumn(); String singleType = ModelUtil.toString(column.propertyType(), true); String listType = "java.util.List<"+singleType+">"; if(singleType.equals(returnType)) return "First"; else if(listType.equals(returnType)) return "All"; else throw new AnnotationError(method, "return value must be of type "+singleType+" or "+listType); } }