/** * 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.NotImplementedException; import jlibs.core.lang.StringUtil; import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.VariableElement; import javax.lang.model.type.TypeKind; 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 */ public class UpsertMethod extends UpdateMethod{ protected UpsertMethod(Printer printer, ExecutableElement method, AnnotationMirror mirror, Columns columns){ super(printer, method, mirror, columns); // @enhancement allow to return pojo if(method.getReturnType().getKind()!= TypeKind.VOID) throw new AnnotationError("method with @Upsert annotation should return void"); } @Override protected String[] code(){ if(method.getParameters().size()==0) throw new AnnotationError(method, "method with @Upsert annotation should take atleast one argument"); String updateCode = queryMethod("update", defaultSQL()); String insertCode = queryMethod("insert", insertSQL()); List<String> code = new ArrayList<String>(); code.add("int count = "+updateCode+';'); code.add("if(count==0)"); code.add(PLUS); code.add(insertCode+';'); code.add(MINUS); TypeMirror returnType = method.getReturnType(); if(returnType==printer.clazz.asType()){ throw new NotImplementedException("Upsert Method returning Model Object"); }else{ switch(returnType.getKind()){ case INT: code.add("return count;"); break; case VOID: break; default: throw new AnnotationError(method, "unsupported return type"); } } return code.toArray(new String[code.size()]); } private CharSequence[] insertSQL(){ List<String> columnNames = new ArrayList<String>(); List<String> columnValues = new ArrayList<String>(); List<String> params = new ArrayList<String>(); for(VariableElement param : method.getParameters()){ String paramName = param.getSimpleName().toString(); if(paramName.indexOf('_')==-1){ ColumnProperty column = getColumn(param); columnNames.add("\"+"+column.columnName(true)+"+\""); columnValues.add("?"); params.add(column.toNativeTypeCode(paramName)); }else{ int underscore = paramName.indexOf('_'); String hint = paramName.substring(0, underscore); String propertyName = paramName.substring(underscore+1); ColumnProperty column = getColumn(param, propertyName); if("where".equals(hint) || "is".equals(hint)){ columnNames.add("\"+"+column.columnName(true)+"+\""); columnValues.add("?"); params.add(column.toNativeTypeCode(paramName)); }else throw new AnnotationError(param, "invalid hint: "+hint); } } StringBuilder query = new StringBuilder("(") .append(StringUtil.join(columnNames.iterator(), ", ")) .append(") VALUES(") .append(StringUtil.join(columnValues.iterator(), ", ")) .append(')'); return new CharSequence[]{ query, StringUtil.join(params.iterator(), ", ") }; } }