com.abubusoft.kripton.processor.sqlite.AbstractSelectCodeGenerator Maven / Gradle / Ivy
/*******************************************************************************
* Copyright 2015, 2017 Francesco Benincasa ([email protected]).
*
* 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.abubusoft.kripton.processor.sqlite;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.lang.model.element.Modifier;
import com.abubusoft.kripton.android.Logger;
import com.abubusoft.kripton.android.annotation.BindSqlSelect;
import com.abubusoft.kripton.android.sqlite.KriptonContentValues;
import com.abubusoft.kripton.android.sqlite.OnReadBeanListener;
import com.abubusoft.kripton.android.sqlite.OnReadCursorListener;
import com.abubusoft.kripton.common.CaseFormat;
import com.abubusoft.kripton.common.One;
import com.abubusoft.kripton.common.Pair;
import com.abubusoft.kripton.common.Triple;
import com.abubusoft.kripton.processor.BaseProcessor;
import com.abubusoft.kripton.processor.KriptonLiveDataManager;
import com.abubusoft.kripton.processor.core.AssertKripton;
import com.abubusoft.kripton.processor.core.ImmutableUtility;
import com.abubusoft.kripton.processor.core.ModelAnnotation;
import com.abubusoft.kripton.processor.core.reflect.PropertyUtility;
import com.abubusoft.kripton.processor.core.reflect.TypeUtility;
import com.abubusoft.kripton.processor.exceptions.InvalidMethodSignException;
import com.abubusoft.kripton.processor.sqlite.SelectBuilderUtility.SelectCodeGenerator;
import com.abubusoft.kripton.processor.sqlite.SelectBuilderUtility.SelectType;
import com.abubusoft.kripton.processor.sqlite.SqlSelectBuilder.SplittedSql;
import com.abubusoft.kripton.processor.sqlite.core.JavadocUtility;
import com.abubusoft.kripton.processor.sqlite.grammars.jql.JQLChecker;
import com.abubusoft.kripton.processor.sqlite.grammars.jql.JQLProjection;
import com.abubusoft.kripton.processor.sqlite.grammars.jql.JQLReplaceVariableStatementListenerImpl;
import com.abubusoft.kripton.processor.sqlite.model.SQLProperty;
import com.abubusoft.kripton.processor.sqlite.model.SQLiteDaoDefinition;
import com.abubusoft.kripton.processor.sqlite.model.SQLiteEntity;
import com.abubusoft.kripton.processor.sqlite.model.SQLiteModelMethod;
import com.abubusoft.kripton.processor.sqlite.transform.SQLTransformer;
import com.squareup.javapoet.ArrayTypeName;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.FieldSpec;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.MethodSpec.Builder;
import com.squareup.javapoet.ParameterSpec;
import com.squareup.javapoet.ParameterizedTypeName;
import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec;
import android.database.Cursor;
/**
* The Class AbstractSelectCodeGenerator.
*/
public abstract class AbstractSelectCodeGenerator implements SelectCodeGenerator {
/** The Constant LIVE_DATA_PREFIX. */
public static final String LIVE_DATA_PREFIX = "ForLiveData";
/**
* The Enum JavadocPartType.
*/
public enum JavadocPartType {
/** The add parameter. */
ADD_PARAMETER,
/** The return. */
RETURN
}
/**
* generate code for sub queries
*
* @param methodBuilder
* @param method
*/
protected void generateSubQueries(Builder methodBuilder, SQLiteModelMethod method) {
SQLiteDaoDefinition daoDefinition = method.getParent();
SQLiteEntity entity = daoDefinition.getEntity();
for (Triple item : method.childrenSelects) {
TypeName entityTypeName = TypeUtility.typeName(entity.getElement());
String setter;
if (entity.isImmutablePojo()) {
String idGetter = ImmutableUtility.IMMUTABLE_PREFIX + entity.getPrimaryKey().getName();
setter=ImmutableUtility.IMMUTABLE_PREFIX+entity.findRelationByParentProperty(item.value0).value0.getName()+"="+String.format("this.daoFactory.get%s().%s(%s)", item.value2.getParent().getName(),
item.value2.getName(), idGetter);
} else {
String idGetter = PropertyUtility.getter("resultBean", entityTypeName, entity.getPrimaryKey());
setter = PropertyUtility.setter(entityTypeName, "resultBean",
entity.findRelationByParentProperty(item.value0).value0,
String.format("this.daoFactory.get%s().%s(%s)", item.value2.getParent().getName(),
item.value2.getName(), idGetter));
}
methodBuilder.addComment("sub query: $L", setter);
methodBuilder.addStatement("$L", setter);
}
}
/**
* The Class JavadocPart.
*/
public static class JavadocPart {
/** The javadoc part type. */
public final JavadocPartType javadocPartType;
/** The name. */
public final String name;
/** The description. */
public final String description;
/**
* Instantiates a new javadoc part.
*
* @param javadocPartType
* the javadoc part type
* @param name
* the name
* @param description
* the description
*/
JavadocPart(JavadocPartType javadocPartType, String name, String description) {
this.javadocPartType = javadocPartType;
this.name = name;
this.description = description;
}
/**
* Builds the.
*
* @param javadocPartType
* the javadoc part type
* @param name
* the name
* @param description
* the description
* @return the javadoc part
*/
public static JavadocPart build(JavadocPartType javadocPartType, String name, String description) {
return new JavadocPart(javadocPartType, name, description);
}
}
/**
* The Enum GenerationType.
*/
public enum GenerationType {
/** The all. */
ALL(true, true, true),
/** The no close cursor. */
NO_CLOSE_CURSOR(true, true, false),
/** The no method sign. */
NO_METHOD_SIGN(false, true, true),
/** The no content. */
NO_CONTENT(true, false, true);
/**
* Instantiates a new generation type.
*
* @param generateMethodSign
* the generate method sign
* @param generateMethodContent
* the generate method content
* @param generateCloseableCursor
* the generate closeable cursor
*/
GenerationType(boolean generateMethodSign, boolean generateMethodContent, boolean generateCloseableCursor) {
this.generateMethodSign = generateMethodSign;
this.generateMethodContent = generateMethodContent;
this.generateCloseableCursor = generateCloseableCursor;
}
/** The generate method sign. */
public final boolean generateMethodSign;
/** The generate method content. */
public final boolean generateMethodContent;
/** The generate closeable cursor. */
public final boolean generateCloseableCursor;
}
/** The select type. */
SelectType selectType;
/*
* (non-Javadoc)
*
* @see com.abubusoft.kripton.processor.sqlite.SelectBuilderUtility. SelectCodeGenerator#generate(com.squareup.javapoet.TypeSpec.Builder, boolean,
* com.abubusoft.kripton.processor.sqlite.model.SQLiteModelMethod)
*/
@Override
public void generate(TypeSpec.Builder classBuilder, boolean mapFields, SQLiteModelMethod method) {
SQLiteDaoDefinition daoDefinition = method.getParent();
Set fieldList = JQLChecker.getInstance().extractProjections(method, method.jql.value,
daoDefinition.getEntity());
// generate method code
MethodSpec.Builder methodBuilder = generateMethodBuilder(method);
generateCommonPart(method, classBuilder, methodBuilder, fieldList, selectType.isMapFields());
methodBuilder.addComment("Specialized part - $L - BEGIN", this.getClass().getSimpleName());
generateSpecializedPart(method, classBuilder, methodBuilder, fieldList, selectType.isMapFields());
methodBuilder.addComment("Specialized part - $L - END", this.getClass().getSimpleName());
classBuilder.addMethod(methodBuilder.build());
}
/**
* generate live data method.
*
* @param classBuilder
* the class builder
* @param method
* the method
*/
@Override
public void generateLiveData(TypeSpec.Builder classBuilder, SQLiteModelMethod method) {
SQLiteDaoDefinition daoDefinition = method.getParent();
Set fieldList = JQLChecker.getInstance().extractProjections(method, method.jql.value,
daoDefinition.getEntity());
// generate method code
MethodSpec.Builder methodBuilder = MethodSpec.methodBuilder(method.getName().replaceAll(LIVE_DATA_PREFIX, ""))
.addAnnotation(Override.class).addModifiers(Modifier.PUBLIC);
methodBuilder.addJavadoc("Live data
\n");
methodBuilder.addJavadoc("This method open a connection internally.
\n\n");
generateCommonPart(method, classBuilder, methodBuilder, fieldList, selectType.isMapFields(),
GenerationType.NO_CONTENT, method.liveDataReturnClass);
ClassName dataSourceClazz = BindDataSourceBuilder.generateDataSourceName(daoDefinition.getParent());
ClassName daoFactoryClazz = TypeUtility
.className(BindDaoFactoryBuilder.generateDaoFactoryName(daoDefinition.getParent()));
ClassName batchClazz = TypeUtility.mergeTypeNameWithSuffix(dataSourceClazz, ".Batch");
List> methodParameters = method.getParameters();
StringBuilder buffer = new StringBuilder();
String separator = "";
for (Pair item : methodParameters) {
buffer.append(separator + item.value0);
separator = ", ";
}
TypeSpec batchBuilder = TypeSpec.anonymousClassBuilder("")
.addSuperinterface(ParameterizedTypeName.get(batchClazz, method.getReturnClass()))
.addMethod(MethodSpec.methodBuilder("onExecute").addAnnotation(Override.class)
.addModifiers(Modifier.PUBLIC)
.addParameter(ParameterSpec.builder(daoFactoryClazz, "daoFactory").build())
.returns(method.getReturnClass()).addStatement("return daoFactory.get$L().$L($L)",
daoDefinition.getName(), method.getName() + LIVE_DATA_PREFIX, buffer.toString())
.build())
.build();
TypeSpec liveDataBuilder = TypeSpec.anonymousClassBuilder("")
.addSuperinterface(ParameterizedTypeName.get(
ClassName.get(KriptonLiveDataManager.getInstance().getComputableLiveDataClazz()),
method.getReturnClass()))
.addMethod(MethodSpec.methodBuilder("compute").addAnnotation(Override.class)
.addModifiers(Modifier.PROTECTED).returns(method.getReturnClass())
.addStatement("return $T.getInstance().executeBatch($L)", dataSourceClazz, batchBuilder)
.build())
.build();
methodBuilder.addStatement("final $T builder=$L",
ParameterizedTypeName.get(
ClassName.get(KriptonLiveDataManager.getInstance().getComputableLiveDataClazz()),
method.getReturnClass()),
liveDataBuilder);
methodBuilder.addStatement("registryLiveData(builder)");
methodBuilder.addStatement("return builder.getLiveData()");
classBuilder.addMethod(methodBuilder.build());
}
/**
* Generate common part.
*
* @param method
* the method
* @param classBuilder
* the class builder
* @param methodBuilder
* the method builder
* @param fieldList
* the field list
* @param mapFields
* the map fields
*/
public void generateCommonPart(SQLiteModelMethod method, TypeSpec.Builder classBuilder,
MethodSpec.Builder methodBuilder, Set fieldList, boolean mapFields) {
generateCommonPart(method, classBuilder, methodBuilder, fieldList, mapFields, GenerationType.ALL, null);
}
/**
* Generate common part.
*
* @param method
* the method
* @param classBuilder
* the class builder
* @param methodBuilder
* the method builder
* @param fieldList
* the field list
* @param mapFields
* the map fields
* @param generationType
* the generation type
* @param forcedReturnType
* the forced return type
* @param javadocParts
* the javadoc parts
*/
public void generateCommonPart(SQLiteModelMethod method, TypeSpec.Builder classBuilder,
MethodSpec.Builder methodBuilder, Set fieldList, boolean mapFields,
GenerationType generationType, TypeName forcedReturnType, JavadocPart... javadocParts) {
SQLiteDaoDefinition daoDefinition = method.getParent();
SQLiteEntity entity = daoDefinition.getEntity();
// if true, field must be associate to ben attributes
// TypeName returnType = method.getReturnClass();
TypeName returnTypeName = forcedReturnType;
if (returnTypeName == null) {
returnTypeName = method.getReturnClass();
}
ModelAnnotation annotation = method.getAnnotation(BindSqlSelect.class);
// parameters
List paramNames = new ArrayList();
List paramGetters = new ArrayList();
List paramTypeNames = new ArrayList();
List usedBeanPropertyNames = new ArrayList<>();
// used method parameters
Set usedMethodParameters = new HashSet();
final One whereJQL = new One<>("");
final One havingJQL = new One<>("");
final One groupJQL = new One<>("");
final One orderJQL = new One<>("");
// extract parts of jql statement
JQLChecker.getInstance().replaceVariableStatements(method, method.jql.value,
new JQLReplaceVariableStatementListenerImpl() {
@Override
public String onWhere(String statement) {
whereJQL.value0 = statement;
return null;
}
@Override
public String onOrderBy(String statement) {
orderJQL.value0 = statement;
return null;
}
@Override
public String onHaving(String statement) {
havingJQL.value0 = statement;
return null;
}
@Override
public String onGroup(String statement) {
groupJQL.value0 = statement;
return null;
}
});
SqlAnalyzer analyzer = new SqlAnalyzer();
// String whereSQL =
// annotation.getAttribute(AnnotationAttributeType.WHERE);
analyzer.execute(BaseProcessor.elementUtils, method, whereJQL.value0);
paramGetters.addAll(analyzer.getParamGetters());
paramNames.addAll(analyzer.getParamNames());
paramTypeNames.addAll(analyzer.getParamTypeNames());
usedBeanPropertyNames.addAll(analyzer.getUsedBeanPropertyNames());
usedMethodParameters.addAll(analyzer.getUsedMethodParameters());
// String havingSQL =
// annotation.getAttribute(AnnotationAttributeType.HAVING);
analyzer.execute(BaseProcessor.elementUtils, method, havingJQL.value0);
paramGetters.addAll(analyzer.getParamGetters());
paramNames.addAll(analyzer.getParamNames());
paramTypeNames.addAll(analyzer.getParamTypeNames());
usedBeanPropertyNames.addAll(analyzer.getUsedBeanPropertyNames());
usedMethodParameters.addAll(analyzer.getUsedMethodParameters());
// String groupBySQL =
// annotation.getAttribute(AnnotationAttributeType.GROUP_BY);
analyzer.execute(BaseProcessor.elementUtils, method, groupJQL.value0);
paramGetters.addAll(analyzer.getParamGetters());
paramNames.addAll(analyzer.getParamNames());
paramTypeNames.addAll(analyzer.getParamTypeNames());
usedBeanPropertyNames.addAll(analyzer.getUsedBeanPropertyNames());
usedMethodParameters.addAll(analyzer.getUsedMethodParameters());
// String orderBySQL =
// annotation.getAttribute(AnnotationAttributeType.ORDER_BY);
analyzer.execute(BaseProcessor.elementUtils, method, orderJQL.value0);
paramGetters.addAll(analyzer.getParamGetters());
paramNames.addAll(analyzer.getParamNames());
paramTypeNames.addAll(analyzer.getParamTypeNames());
usedBeanPropertyNames.addAll(analyzer.getUsedBeanPropertyNames());
usedMethodParameters.addAll(analyzer.getUsedMethodParameters());
// add as used parameter dynamic components too
if (method.hasDynamicWhereConditions()) {
AssertKripton.assertTrueOrInvalidMethodSignException(
!usedMethodParameters.contains(method.dynamicWhereParameterName), method,
" parameter %s is used like SQL parameter and dynamic WHERE condition.",
method.dynamicOrderByParameterName);
usedMethodParameters.add(method.dynamicWhereParameterName);
if (method.hasDynamicWhereArgs()) {
AssertKripton.assertTrueOrInvalidMethodSignException(
!usedMethodParameters.contains(method.dynamicWhereArgsParameterName), method,
" parameter %s is used like SQL parameter and dynamic WHERE ARGS condition.",
method.dynamicWhereArgsParameterName);
usedMethodParameters.add(method.dynamicWhereArgsParameterName);
}
}
if (method.hasDynamicOrderByConditions()) {
AssertKripton.assertTrueOrInvalidMethodSignException(
!usedMethodParameters.contains(method.dynamicOrderByParameterName), method,
" parameter %s is used like SQL parameter and dynamic ORDER BY condition.",
method.dynamicOrderByParameterName);
usedMethodParameters.add(method.dynamicOrderByParameterName);
}
if (method.hasDynamicPageSizeConditions()) {
AssertKripton.assertTrueOrInvalidMethodSignException(
!usedMethodParameters.contains(method.dynamicPageSizeName), method,
" parameter %s is used like SQL parameter and dynamic page size of LIMIT condition.",
method.dynamicPageSizeName);
usedMethodParameters.add(method.dynamicPageSizeName);
}
// generate method signature
if (generationType.generateMethodSign) {
generateMethodSignature(method, methodBuilder, returnTypeName);
}
// generate javadoc
JavadocUtility.generateJavaDocForSelect(methodBuilder, paramNames, method, annotation, fieldList, selectType,
javadocParts);
methodBuilder.addComment("common part generation - BEGIN");
if (generationType.generateMethodContent) {
SplittedSql splittedSql = SqlSelectBuilder.generateSQL(method, methodBuilder, false);
// retrieve content values
methodBuilder.addStatement("$T _contentValues=contentValues()", KriptonContentValues.class);
if (method.hasDynamicParts()) {
generateSQLBuild(method, methodBuilder, splittedSql);
methodBuilder.addStatement("String _sql=_sqlBuilder.toString()");
} else {
String sqlName = CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, method.buildSQLName());
String sql = SqlSelectBuilder.convertJQL2SQL(method, true);
classBuilder.addField(
FieldSpec.builder(String.class, sqlName, Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL)
.initializer("$S", sql).build());
methodBuilder.addComment("query SQL is statically defined");
methodBuilder.addStatement("String _sql=$L", sqlName);
}
// build where condition (common for every type of select)
StringBuilder logArgsBuffer = new StringBuilder();
methodBuilder.addComment("add where arguments");
{
String separator = "";
TypeName paramTypeName;
// String paramName;
boolean nullable;
int i = 0;
boolean rawParameters;
String beanName = null;
beanName = method.findEntityProperty();
for (String methodParam : paramGetters) {
rawParameters = paramNames.get(i).indexOf(".") == -1;
if (method.jql.spreadParams.contains(method.findParameterAliasByName(methodParam))) {
// paramTypeName = paramTypeNames.get(i);
String sizeMethod = "";
String elementMethod = "";
TypeName paramCollTypeName = paramTypeNames.get(i);
if (paramCollTypeName instanceof ArrayTypeName) {
sizeMethod = "length";
elementMethod = "[_i]";
paramTypeName = ((ArrayTypeName) paramCollTypeName).componentType;
} else if (paramCollTypeName instanceof ParameterizedTypeName) {
sizeMethod = "size()";
elementMethod = ".get(_i)";
paramTypeName = ((ParameterizedTypeName) paramCollTypeName).typeArguments.get(0);
} else {
paramTypeName = TypeName.get(String.class);
}
methodBuilder.beginControlFlow("if ($L!=null)", methodParam);
methodBuilder.addComment("$L is managed as spread param", methodParam);
methodBuilder.beginControlFlow("for (int _i=0; _i<$L.$L;_i++)", methodParam, sizeMethod);
methodBuilder.addCode(" _contentValues.addWhereArgs(");
generateRawWhereArg(method, methodBuilder, paramTypeName, TypeUtility.isNullable(paramTypeName),
methodParam, methodParam + elementMethod);
methodBuilder.addCode(");\n");
methodBuilder.endControlFlow();
methodBuilder.endControlFlow();
} else {
paramTypeName = paramTypeNames.get(i);
methodBuilder.addCode("_contentValues.addWhereArgs(");
logArgsBuffer.append(separator + "%s");
// code for query arguments
nullable = TypeUtility.isNullable(paramTypeName);
if (rawParameters) {
generateRawWhereArg(method, methodBuilder, paramTypeName, nullable, methodParam);
} else {
// eventually we take associated property
SQLProperty property = usedBeanPropertyNames.get(i) == null ? null
: entity.get(usedBeanPropertyNames.get(i));
if (nullable && !(property != null) && !method.hasAdapterForParam(methodParam)) {
methodBuilder.addCode("($L==null?\"\":", methodParam);
}
// check for string conversion
TypeUtility.beginStringConversion(methodBuilder, paramTypeName);
// if (property != null) {
// SQLTransformer.javaProperty2WhereCondition(methodBuilder,
// method, item, paramTypeName, property);
// } else {
SQLTransformer.javaProperty2WhereCondition(methodBuilder, method, beanName, paramTypeName,
property);
// }
// check for string conversion
TypeUtility.endStringConversion(methodBuilder, paramTypeName);
if (nullable && !(property != null) && !method.hasAdapterForParam(methodParam)) {
methodBuilder.addCode(")");
}
}
methodBuilder.addCode(");\n");
}
separator = ", ";
i++;
}
}
methodBuilder.addStatement("String[] _sqlArgs=_contentValues.whereArgsAsArray()");
if (daoDefinition.isLogEnabled()) {
// generate log section - BEGIN
methodBuilder.addComment("log section for select BEGIN");
methodBuilder.beginControlFlow("if (_context.isLogEnabled())");
// manage log
methodBuilder.addComment("manage log");
methodBuilder.addStatement("$T.info(_sql)", Logger.class);
// log for where parames
SqlBuilderHelper.generateLogForWhereParameters(method, methodBuilder);
// generate log section - END
methodBuilder.endControlFlow();
methodBuilder.addComment("log section for select END");
}
if (generationType.generateCloseableCursor) {
methodBuilder.beginControlFlow("try ($T _cursor = database().rawQuery(_sql, _sqlArgs))", Cursor.class);
} else {
methodBuilder.addStatement("$T _cursor = database().rawQuery(_sql, _sqlArgs)", Cursor.class);
}
if (daoDefinition.isLogEnabled()) {
// generate log section - BEGIN
methodBuilder.addComment("log section BEGIN");
methodBuilder.beginControlFlow("if (_context.isLogEnabled())");
methodBuilder.addCode("$T.info(\"Rows found: %s\",_cursor.getCount());\n", Logger.class);
// generate log section - END
methodBuilder.endControlFlow();
methodBuilder.addComment("log section END");
}
switch (selectType) {
case LISTENER_CURSOR: {
ClassName readCursorListenerToExclude = ClassName.get(OnReadCursorListener.class);
checkUnusedParameters(method, usedMethodParameters, readCursorListenerToExclude);
}
break;
case LISTENER_BEAN: {
ParameterizedTypeName readBeanListenerToExclude = ParameterizedTypeName
.get(ClassName.get(OnReadBeanListener.class), TypeName.get(entity.getElement().asType()));
checkUnusedParameters(method, usedMethodParameters, readBeanListenerToExclude);
}
break;
default:
checkUnusedParameters(method, usedMethodParameters, null);
break;
}
}
methodBuilder.addComment("common part generation - END");
}
private void generateRawWhereArg(SQLiteModelMethod method, MethodSpec.Builder methodBuilder, TypeName paramTypeName,
boolean nullable, String item) {
generateRawWhereArg(method, methodBuilder, paramTypeName, nullable, item, item);
}
/**
* @param method
* @param methodBuilder
* @param paramTypeName
* @param nullable
* @param methodItem
* is the name of method's parameter
* @param item
* is the name of used parameter
*/
private void generateRawWhereArg(SQLiteModelMethod method, MethodSpec.Builder methodBuilder, TypeName paramTypeName,
boolean nullable, String methodItem, String item) {
if (nullable && !method.hasAdapterForParam(methodItem)) {
methodBuilder.addCode("($L==null?\"\":", item);
}
// check for string conversion
TypeUtility.beginStringConversion(methodBuilder, paramTypeName);
SQLTransformer.javaMethodParam2WhereConditions(methodBuilder, method, methodItem, item, paramTypeName);
// check for string conversion
TypeUtility.endStringConversion(methodBuilder, paramTypeName);
if (nullable && !method.hasAdapterForParam(methodItem)) {
methodBuilder.addCode(")");
}
}
/**
* Generate method builder.
*
* @param method
* the method
* @return the method spec. builder
*/
protected MethodSpec.Builder generateMethodBuilder(SQLiteModelMethod method) {
MethodSpec.Builder methodBuilder;
if (method.hasLiveData()) {
methodBuilder = MethodSpec.methodBuilder(method.getName() + LIVE_DATA_PREFIX)
.addModifiers(Modifier.PROTECTED);
} else {
methodBuilder = MethodSpec.methodBuilder(method.getName()).addAnnotation(Override.class)
.addModifiers(Modifier.PUBLIC);
}
return methodBuilder;
}
/**
* Generate method signature.
*
* @param method
* the method
* @param methodBuilder
* the method builder
* @param returnTypeName
* the return type name
* @param additionalParameterSpec
* the additional parameter spec
*/
protected void generateMethodSignature(SQLiteModelMethod method, MethodSpec.Builder methodBuilder,
TypeName returnTypeName, ParameterSpec... additionalParameterSpec) {
boolean finalParameter = false;
if (method.hasLiveData() && returnTypeName.equals(method.liveDataReturnClass)) {
finalParameter = true;
}
// add parameter for method
for (Pair item : method.getParameters()) {
ParameterSpec.Builder builder = ParameterSpec.builder(item.value1, item.value0);
if (finalParameter) {
builder.addModifiers(Modifier.FINAL);
}
methodBuilder.addParameter(builder.build());
}
// add additional params
for (ParameterSpec item : additionalParameterSpec) {
methodBuilder.addParameter(item);
}
// add return type
methodBuilder.returns(returnTypeName);
}
/**
* Generate specialized part.
*
* @param method
* the method
* @param classBuilder
* the class builder
* @param methodBuilder
* the method builder
* @param fieldList
* the field list
* @param mapFields
* the map fields
*/
public abstract void generateSpecializedPart(SQLiteModelMethod method, TypeSpec.Builder classBuilder,
MethodSpec.Builder methodBuilder, Set fieldList, boolean mapFields);
/*
* (non-Javadoc)
*
* @see com.abubusoft.kripton.processor.sqlite.SelectBuilderUtility. SelectCodeGenerator#setSelectResultTye(com.abubusoft.kripton.processor.
* sqlite.SelectBuilderUtility.SelectType)
*/
@Override
public void setSelectResultTye(SelectType value) {
this.selectType = value;
}
/**
* Check if there are unused method parameters. In this case an exception was throws.
*
* @param method
* the method
* @param usedMethodParameters
* the used method parameters
* @param excludedClasses
* the excluded classes
*/
public static void checkUnusedParameters(SQLiteModelMethod method, Set usedMethodParameters,
TypeName excludedClasses) {
int paramsCount = method.getParameters().size();
int usedCount = usedMethodParameters.size();
if (paramsCount > usedCount) {
StringBuilder sb = new StringBuilder();
String separator = "";
for (Pair item : method.getParameters()) {
if (excludedClasses != null && item.value1.equals(excludedClasses)) {
usedCount++;
} else {
if (!usedMethodParameters.contains(item.value0)) {
sb.append(separator + "'" + item.value0 + "'");
separator = ", ";
}
}
}
if (paramsCount > usedCount) {
throw (new InvalidMethodSignException(method, "unused parameter(s) " + sb.toString()));
}
}
}
/**
* Generate SQL build.
*
* @param method
* the method
* @param methodBuilder
* the method builder
* @param splittedSql
* the splitted sql
*/
private static void generateSQLBuild(SQLiteModelMethod method, MethodSpec.Builder methodBuilder,
SplittedSql splittedSql) {
methodBuilder.addStatement("$T _sqlBuilder=sqlBuilder()", StringBuilder.class);
methodBuilder.addStatement("_sqlBuilder.append($S)", splittedSql.sqlBasic.trim());
SqlModifyBuilder.generateInitForDynamicWhereVariables(method, methodBuilder, method.dynamicWhereParameterName,
method.dynamicWhereArgsParameterName);
if (method.jql.isOrderBy()) {
methodBuilder.addStatement("String _sortOrder=$L", method.jql.paramOrderBy);
}
SqlBuilderHelper.generateWhereCondition(methodBuilder, method, false);
SqlSelectBuilder.generateDynamicPartOfQuery(method, methodBuilder, splittedSql);
}
}