Search in sources :

Example 6 with JQLPlaceHolder

use of com.abubusoft.kripton.processor.sqlite.grammars.jql.JQLPlaceHolder in project kripton by xcesco.

the class SqlSelectBuilder method generateSelectForContentProvider.

/**
 * <p>
 * Generate select used in content provider class.
 * </p>
 *
 * @param elementUtils
 * @param builder
 * @param method
 * @param selectResultType
 */
private static void generateSelectForContentProvider(Builder builder, final SQLiteModelMethod method, SelectType selectResultType) {
    final SQLiteDaoDefinition daoDefinition = method.getParent();
    final SQLiteEntity entity = daoDefinition.getEntity();
    final Set<String> columns = new LinkedHashSet<>();
    MethodSpec.Builder methodBuilder = MethodSpec.methodBuilder(method.contentProviderMethodName);
    // params
    methodBuilder.addParameter(ParameterSpec.builder(Uri.class, "uri").build());
    methodBuilder.addParameter(ParameterSpec.builder(ArrayTypeName.of(String.class), "projection").build());
    methodBuilder.addParameter(ParameterSpec.builder(String.class, "selection").build());
    methodBuilder.addParameter(ParameterSpec.builder(ArrayTypeName.of(String.class), "selectionArgs").build());
    methodBuilder.addParameter(ParameterSpec.builder(String.class, "sortOrder").build());
    methodBuilder.returns(Cursor.class);
    SqlBuilderHelper.generateLogForContentProviderBeginning(method, methodBuilder);
    JQLChecker jqlChecker = JQLChecker.getInstance();
    SplittedSql splittedSql = generateSQL(method, methodBuilder, true);
    List<JQLPlaceHolder> placeHolders = jqlChecker.extractFromVariableStatement(method, splittedSql.sqlWhereStatement);
    // remove placeholder for dynamic where, we are not interested here
    placeHolders = SqlBuilderHelper.removeDynamicPlaceHolder(placeHolders);
    AssertKripton.assertTrue(placeHolders.size() == method.contentProviderUriVariables.size(), "In '%s.%s' content provider URI path variables and variables in where conditions are different. If SQL uses parameters, they must be defined in URI path.", daoDefinition.getName(), method.getName());
    Set<JQLProjection> projectedColumns = jqlChecker.extractProjections(method, method.jql.value, entity);
    for (JQLProjection item : projectedColumns) {
        if (item.type == ProjectionType.COLUMN) {
            columns.add(entity.get(item.column.trim()).columnName);
        } else {
            columns.add(item.expression.trim());
        }
    }
    methodBuilder.addStatement("$T _contentValues=contentValues()", KriptonContentValues.class);
    methodBuilder.addStatement("$T _sqlBuilder=sqlBuilder()", StringBuilder.class);
    SqlModifyBuilder.generateInitForDynamicWhereVariables(method, methodBuilder, "selection", "selectionArgs");
    methodBuilder.addStatement("$T _projectionBuffer=new $T()", StringBuilder.class, StringBuilder.class);
    if (method.jql.isOrderBy()) {
        methodBuilder.addStatement("String _sortOrder=sortOrder");
    }
    methodBuilder.addStatement("_sqlBuilder.append($S)", splittedSql.sqlBasic);
    SqlBuilderHelper.generateWhereCondition(methodBuilder, method, false);
    generateDynamicPartOfQuery(method, methodBuilder, splittedSql);
    // generate and check columns
    {
        methodBuilder.addCode("\n// manage projected columns\n");
        methodBuilder.addStatement("String _columnSeparator=\"\"");
        methodBuilder.beginControlFlow("if (projection!=null && projection.length>0)");
        // generate projected column check
        String columnCheckSetName = SqlBuilderHelper.generateColumnCheckSet(builder, method, columns);
        SqlBuilderHelper.forEachColumnInContentValue(methodBuilder, method, "projection", true, new OnColumnListener() {

            @Override
            public void onColumnCheck(MethodSpec.Builder methodBuilder, String projectedColumnVariable) {
                methodBuilder.addStatement("_projectionBuffer.append(_columnSeparator + $L)", projectedColumnVariable);
                methodBuilder.addStatement("_columnSeparator=\", \"");
            }
        });
        methodBuilder.nextControlFlow("else");
        methodBuilder.beginControlFlow("for (String column: $L)", columnCheckSetName);
        methodBuilder.addStatement("_projectionBuffer.append(_columnSeparator + column)");
        methodBuilder.addStatement("_columnSeparator=\", \"");
        methodBuilder.endControlFlow();
        methodBuilder.endControlFlow();
        int i = 0;
        // every controls was done in constructor of SQLiteModelMethod
        for (ContentUriPlaceHolder variable : method.contentProviderUriVariables) {
            AssertKripton.assertTrue(SqlBuilderHelper.validate(variable.value, placeHolders, i), "In '%s.%s' content provider URI path and where conditions must use same set of variables", daoDefinition.getName(), method.getName());
            SQLProperty entityProperty = entity.get(variable.value);
            TypeName methodParameterType = method.findParameterTypeByAliasOrName(variable.value);
            methodBuilder.addCode("// Add parameter $L at path segment $L\n", variable.value, variable.pathSegmentIndex);
            // methodBuilder.addStatement("_sqlWhereParams.add(uri.getPathSegments().get($L))",
            // variable.pathSegmentIndex);
            methodBuilder.addStatement("_contentValues.addWhereArgs(uri.getPathSegments().get($L))", variable.pathSegmentIndex);
            if (entityProperty != null) {
                AssertKripton.assertTrue(TypeUtility.isTypeIncludedIn(entityProperty.getPropertyType().getTypeName(), String.class, Long.class, Long.TYPE), "In '%s.%s' content provider URI path variables %s must be String of Long type", daoDefinition.getName(), method.getName(), entityProperty.getName());
            } else if (methodParameterType != null) {
                AssertKripton.assertTrue(TypeUtility.isTypeIncludedIn(methodParameterType, String.class, Long.class, Long.TYPE), "In '%s.%s' content provider URI path variables %s must be String of Long type", daoDefinition.getName(), method.getName(), method.findParameterNameByAlias(variable.value));
            }
            i++;
        }
    }
    // _sql must be always defined
    methodBuilder.addStatement("String _sql=String.format(_sqlBuilder.toString(), _projectionBuffer.toString())");
    SqlBuilderHelper.generateLogForSQL(method, methodBuilder);
    SqlBuilderHelper.generateLogForWhereParameters(method, methodBuilder);
    methodBuilder.addCode("\n// execute query\n");
    // methodBuilder.addStatement("Cursor _result =
    // database().rawQuery(_sql, _sqlWhereParams.toArray(new
    // String[_sqlWhereParams.size()]))");
    methodBuilder.addStatement("Cursor _result = database().rawQuery(_sql, _contentValues.whereArgsAsArray())");
    methodBuilder.addStatement("return _result");
    // we add at last javadoc, because need info is built at last.
    SqlBuilderHelper.generateJavaDocForContentProvider(method, methodBuilder);
    methodBuilder.addJavadoc("@param uri $S\n", method.contentProviderUriTemplate.replace("*", "[*]"));
    methodBuilder.addJavadoc("@param selection dynamic part of <code>where</code> statement $L\n", method.hasDynamicWhereConditions() ? "" : "<b>NOT USED</b>");
    methodBuilder.addJavadoc("@param selectionArgs arguments of dynamic part of <code>where</code> statement $L\n", method.hasDynamicWhereConditions() ? "" : "<b>NOT USED</b>");
    methodBuilder.addJavadoc("@return number of effected rows\n");
    builder.addMethod(methodBuilder.build());
}
Also used : LinkedHashSet(java.util.LinkedHashSet) JQLChecker(com.abubusoft.kripton.processor.sqlite.grammars.jql.JQLChecker) ParameterizedTypeName(com.squareup.javapoet.ParameterizedTypeName) TypeName(com.squareup.javapoet.TypeName) ArrayTypeName(com.squareup.javapoet.ArrayTypeName) MethodSpec(com.squareup.javapoet.MethodSpec) Builder(com.squareup.javapoet.TypeSpec.Builder) JQLPlaceHolder(com.abubusoft.kripton.processor.sqlite.grammars.jql.JQLPlaceHolder) SQLiteDaoDefinition(com.abubusoft.kripton.processor.sqlite.model.SQLiteDaoDefinition) ContentUriPlaceHolder(com.abubusoft.kripton.processor.sqlite.grammars.uri.ContentUriPlaceHolder) JQLProjection(com.abubusoft.kripton.processor.sqlite.grammars.jql.JQLProjection) SQLProperty(com.abubusoft.kripton.processor.sqlite.model.SQLProperty) SQLiteEntity(com.abubusoft.kripton.processor.sqlite.model.SQLiteEntity)

Example 7 with JQLPlaceHolder

use of com.abubusoft.kripton.processor.sqlite.grammars.jql.JQLPlaceHolder in project kripton by xcesco.

the class SqlModifyBuilder method generateModifierForContentProvider.

/**
 * <p>
 * Generate update and delete used in content provider class.
 * </p>
 *
 * @param elementUtils
 * @param builder
 * @param method
 * @param updateResultType
 */
private static void generateModifierForContentProvider(Elements elementUtils, Builder builder, final SQLiteModelMethod method, ModifyType updateResultType) {
    final SQLiteDaoDefinition daoDefinition = method.getParent();
    final SQLiteEntity entity = daoDefinition.getEntity();
    final Set<String> columns = new LinkedHashSet<>();
    JQLChecker jqlChecker = JQLChecker.getInstance();
    // parameters extracted from query
    final One<String> whereStatement = new One<>();
    if (method.jql.isWhereConditions()) {
        // parameters extracted from query
        final One<Boolean> alreadyFoundWhereStatement = new One<>(false);
        // put in whereStatement value of where statement.
        jqlChecker.replaceVariableStatements(method, method.jql.value, new JQLReplaceVariableStatementListenerImpl() {

            @Override
            public String onWhere(String statement) {
                if (alreadyFoundWhereStatement.value0 == false) {
                    whereStatement.value0 = statement;
                    alreadyFoundWhereStatement.value0 = true;
                    return "";
                } else {
                    // DO NOTHING
                    return null;
                }
            }
        });
    }
    List<JQLPlaceHolder> placeHolders = jqlChecker.extractFromVariableStatement(method, whereStatement.value0);
    // remove placeholder for dynamic where, we are not interested here
    placeHolders = SqlBuilderHelper.removeDynamicPlaceHolder(placeHolders);
    checkContentProviderVarsAndArguments(method, placeHolders);
    // detect column used for content value
    jqlChecker.replace(method, method.jql, new JQLReplacerListenerImpl(method) {

        @Override
        public String onColumnNameToUpdate(String columnName) {
            SQLProperty tempProperty = entity.get(columnName);
            AssertKripton.assertTrueOrUnknownPropertyInJQLException(tempProperty != null, method, columnName);
            columns.add(tempProperty.columnName);
            return null;
        }
    });
    MethodSpec.Builder methodBuilder = MethodSpec.methodBuilder(method.contentProviderMethodName);
    // params
    methodBuilder.addParameter(ParameterSpec.builder(Uri.class, "uri").build());
    if (updateResultType == ModifyType.UPDATE_BEAN || updateResultType == ModifyType.UPDATE_RAW) {
        methodBuilder.addParameter(ParameterSpec.builder(ContentValues.class, "contentValues").build());
    }
    methodBuilder.addParameter(ParameterSpec.builder(String.class, "selection").build());
    methodBuilder.addParameter(ParameterSpec.builder(ArrayTypeName.of(String.class), "selectionArgs").build());
    methodBuilder.returns(Integer.TYPE);
    // retrieve content values
    if (updateResultType == ModifyType.UPDATE_BEAN || updateResultType == ModifyType.UPDATE_RAW) {
        methodBuilder.addStatement("$T _contentValues=contentValuesForContentProvider(contentValues)", KriptonContentValues.class);
    } else {
        methodBuilder.addStatement("$T _contentValues=contentValues()", KriptonContentValues.class);
    }
    SqlBuilderHelper.generateLogForContentProviderBeginning(method, methodBuilder);
    // query builder
    methodBuilder.addStatement("$T _sqlBuilder=sqlBuilder()", StringBuilder.class);
    generateInitForDynamicWhereVariables(method, methodBuilder, "selection", "selectionArgs");
    SqlBuilderHelper.generateWhereCondition(methodBuilder, method, false);
    int i = 0;
    // every controls was done in constructor of SQLiteModelMethod
    for (ContentUriPlaceHolder variable : method.contentProviderUriVariables) {
        AssertKripton.assertTrue(SqlBuilderHelper.validate(variable.value, placeHolders, i), "In '%s.%s' content provider URI path variables and variables in where conditions are different. If SQL uses parameters, they must be defined in URI path.", daoDefinition.getName(), method.getName());
        JQLParameterName paramName = JQLParameterName.parse(variable.value);
        SQLProperty entityProperty = entity.get(paramName.getValue());
        if (entityProperty != null) {
            methodBuilder.addCode("// Add parameter $L at path segment $L\n", variable.value, variable.pathSegmentIndex);
            // methodBuilder.addStatement("_sqlWhereParams.add(uri.getPathSegments().get($L))",
            // variable.pathSegmentIndex);
            methodBuilder.addStatement("_contentValues.addWhereArgs(uri.getPathSegments().get($L))", variable.pathSegmentIndex);
            AssertKripton.assertTrue(TypeUtility.isTypeIncludedIn(entityProperty.getPropertyType().getTypeName(), String.class, Long.class, Long.TYPE), "In '%s.%s' content provider URI path variables %s must be String of Long type", daoDefinition.getName(), method.getName(), entityProperty.getName());
        }
        i++;
    }
    if (method.hasDynamicWhereConditions() && method.hasDynamicWhereArgs()) {
        // ASSERT: only with dynamic where conditions
        methodBuilder.beginControlFlow("if ($T.hasText(_sqlDynamicWhere) && _sqlDynamicWhereArgs!=null)", StringUtils.class);
        if (method.hasDynamicWhereConditions()) {
            methodBuilder.beginControlFlow("for (String _arg: _sqlDynamicWhereArgs)");
            // methodBuilder.addStatement("_sqlWhereParams.add(_arg)");
            methodBuilder.addStatement("_contentValues.addWhereArgs(_arg)");
            methodBuilder.endControlFlow();
        }
        methodBuilder.endControlFlow();
    }
    // column checj
    switch(updateResultType) {
        case UPDATE_BEAN:
        case UPDATE_RAW:
            SqlBuilderHelper.generateColumnCheckSet(builder, method, columns);
            SqlBuilderHelper.forEachColumnInContentValue(methodBuilder, method, "_contentValues.values().keySet()", true, null);
            break;
        default:
            break;
    }
    // generate log section - BEGIN
    methodBuilder.addComment("log section BEGIN");
    methodBuilder.beginControlFlow("if (_context.isLogEnabled())");
    generateLogForModifiers(method, methodBuilder);
    if (method.jql.operationType == JQLType.UPDATE) {
        // generate log for content values
        SqlBuilderHelper.generateLogForContentValues(method, methodBuilder);
    }
    // log for where parames
    SqlBuilderHelper.generateLogForWhereParameters(method, methodBuilder);
    // generate log section - END
    methodBuilder.endControlFlow();
    methodBuilder.addComment("log section END");
    methodBuilder.addCode("\n// execute SQL\n");
    switch(updateResultType) {
        case DELETE_BEAN:
        case DELETE_RAW:
            methodBuilder.addStatement("int result = database().delete($S, _sqlWhereStatement, _contentValues.whereArgsAsArray())", daoDefinition.getEntity().getTableName());
            if (method.getParent().getParent().generateRx) {
                GenericSQLHelper.generateSubjectNext(methodBuilder, SubjectType.DELETE);
            }
            break;
        case UPDATE_BEAN:
        case UPDATE_RAW:
            if (method.jql.conflictAlgorithmType == ConflictAlgorithmType.NONE) {
                methodBuilder.addStatement("int result = database().update($S, _contentValues.values(), _sqlWhereStatement, _contentValues.whereArgsAsArray())", daoDefinition.getEntity().getTableName());
            } else {
                methodBuilder.addCode("// conflict algorithm $L\n", method.jql.conflictAlgorithmType);
                methodBuilder.addStatement("int result = database().updateWithOnConflict($S, _contentValues.values(), _sqlWhereStatement, _contentValues.whereArgsAsArray()), $L)", daoDefinition.getEntity().getTableName(), method.jql.conflictAlgorithmType.getConflictAlgorithm());
            }
            if (method.getParent().getParent().generateRx) {
                GenericSQLHelper.generateSubjectNext(methodBuilder, SubjectType.UPDATE);
            }
            break;
    }
    // support for livedata
    if (daoDefinition.hasLiveData()) {
        methodBuilder.addComment("support for livedata");
        methodBuilder.addStatement(BindDaoBuilder.METHOD_NAME_REGISTRY_EVENT + "(result)");
    }
    methodBuilder.addStatement("return result");
    // we add at last javadoc, because need info is built at last.
    SqlBuilderHelper.generateJavaDocForContentProvider(method, methodBuilder);
    methodBuilder.addJavadoc("@param uri $S\n", method.contentProviderUriTemplate.replace("*", "[*]"));
    switch(updateResultType) {
        case UPDATE_BEAN:
        case UPDATE_RAW:
            methodBuilder.addJavadoc("@param contentValues content values\n");
            break;
        default:
            break;
    }
    methodBuilder.addJavadoc("@param selection dynamic part of <code>where</code> statement $L\n", method.hasDynamicWhereConditions() ? "" : "<b>NOT USED</b>");
    methodBuilder.addJavadoc("@param selectionArgs arguments of dynamic part of <code>where</code> statement $L\n", method.hasDynamicWhereConditions() ? "" : "<b>NOT USED</b>");
    methodBuilder.addJavadoc("@return number of effected rows\n");
    builder.addMethod(methodBuilder.build());
}
Also used : LinkedHashSet(java.util.LinkedHashSet) JQLReplaceVariableStatementListenerImpl(com.abubusoft.kripton.processor.sqlite.grammars.jql.JQLReplaceVariableStatementListenerImpl) JQLChecker(com.abubusoft.kripton.processor.sqlite.grammars.jql.JQLChecker) JQLParameterName(com.abubusoft.kripton.processor.sqlite.grammars.jql.JQLChecker.JQLParameterName) MethodSpec(com.squareup.javapoet.MethodSpec) One(com.abubusoft.kripton.common.One) JQLPlaceHolder(com.abubusoft.kripton.processor.sqlite.grammars.jql.JQLPlaceHolder) SQLiteDaoDefinition(com.abubusoft.kripton.processor.sqlite.model.SQLiteDaoDefinition) JQLReplacerListenerImpl(com.abubusoft.kripton.processor.sqlite.grammars.jql.JQLReplacerListenerImpl) ContentUriPlaceHolder(com.abubusoft.kripton.processor.sqlite.grammars.uri.ContentUriPlaceHolder) SQLProperty(com.abubusoft.kripton.processor.sqlite.model.SQLProperty) SQLiteEntity(com.abubusoft.kripton.processor.sqlite.model.SQLiteEntity)

Aggregations

JQLChecker (com.abubusoft.kripton.processor.sqlite.grammars.jql.JQLChecker)7 JQLPlaceHolder (com.abubusoft.kripton.processor.sqlite.grammars.jql.JQLPlaceHolder)7 BaseProcessorTest (base.BaseProcessorTest)5 JQL (com.abubusoft.kripton.processor.sqlite.grammars.jql.JQL)5 ArrayList (java.util.ArrayList)5 List (java.util.List)5 Test (org.junit.Test)5 JQLReplacerListenerImpl (com.abubusoft.kripton.processor.sqlite.grammars.jql.JQLReplacerListenerImpl)4 JQLDynamicStatementType (com.abubusoft.kripton.processor.sqlite.grammars.jql.JQL.JQLDynamicStatementType)3 JQLContext (com.abubusoft.kripton.processor.sqlite.grammars.jql.JQLContext)3 SQLProperty (com.abubusoft.kripton.processor.sqlite.model.SQLProperty)3 LinkedHashSet (java.util.LinkedHashSet)3 One (com.abubusoft.kripton.common.One)2 JQLProjection (com.abubusoft.kripton.processor.sqlite.grammars.jql.JQLProjection)2 JQLReplaceVariableStatementListenerImpl (com.abubusoft.kripton.processor.sqlite.grammars.jql.JQLReplaceVariableStatementListenerImpl)2 ContentUriPlaceHolder (com.abubusoft.kripton.processor.sqlite.grammars.uri.ContentUriPlaceHolder)2 SQLiteDaoDefinition (com.abubusoft.kripton.processor.sqlite.model.SQLiteDaoDefinition)2 SQLiteEntity (com.abubusoft.kripton.processor.sqlite.model.SQLiteEntity)2 MethodSpec (com.squareup.javapoet.MethodSpec)2 Finder (com.abubusoft.kripton.processor.core.Finder)1