/**
* 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(), ", ")
};
}
}