Search in sources :

Example 11 with SQLiteDaoDefinition

use of com.abubusoft.kripton.processor.sqlite.model.SQLiteDaoDefinition in project kripton by xcesco.

the class JQLBuilder method buildJQLInsert.

/**
 * <pre>
 *
 * INSERT INTO person (name, surname, birth_city, birth_day) VALUES (${name}, ${surname}, ${birthCity}, ${birthDay})
 * </pre>
 *
 * @param method
 * @param preparedJql
 * @return
 */
private static JQL buildJQLInsert(SQLiteModelMethod method, final JQL result, String preparedJql) {
    if (StringUtils.hasText(preparedJql)) {
        result.value = preparedJql;
        // INSERT can contains bind parameter in column values and select
        // statement
        final One<Boolean> inColumnValueSet = new One<Boolean>(false);
        final One<Boolean> inWhereStatement = new One<Boolean>(false);
        JQLChecker.getInstance().analyze(method, result, new JqlBaseListener() {

            @Override
            public void enterConflict_algorithm(Conflict_algorithmContext ctx) {
                result.conflictAlgorithmType = ConflictAlgorithmType.valueOf(ctx.getText().toUpperCase());
            }

            @Override
            public void enterProjected_columns(Projected_columnsContext ctx) {
                result.containsSelectOperation = true;
            }

            @Override
            public void enterWhere_stmt(Where_stmtContext ctx) {
                inWhereStatement.value0 = true;
            }

            @Override
            public void exitWhere_stmt(Where_stmtContext ctx) {
                inWhereStatement.value0 = false;
            }

            @Override
            public void enterColumn_value_set(Column_value_setContext ctx) {
                inColumnValueSet.value0 = true;
            }

            @Override
            public void exitColumn_value_set(Column_value_setContext ctx) {
                inColumnValueSet.value0 = false;
            }

            @Override
            public void enterBind_parameter(Bind_parameterContext ctx) {
                if (inWhereStatement.value0) {
                    result.bindParameterOnWhereStatementCounter++;
                } else if (inColumnValueSet.value0) {
                    result.bindParameterAsColumnValueCounter++;
                }
                AssertKripton.assertTrue(inWhereStatement.value0 || inColumnValueSet.value0, "unknown situation!");
            }
        });
        if (result.containsSelectOperation) {
            AssertKripton.assertTrueOrInvalidMethodSignException(method.getReturnClass().equals(TypeName.VOID), method, "defined JQL requires that method's return type is void");
        }
    // ASSERT: a INSERT-SELECT SQL can not contains parameters on values
    // section.
    } else {
        // use annotation's attribute value and exclude and bean definition
        // to
        final Class<? extends Annotation> annotation = BindSqlInsert.class;
        final SQLiteDaoDefinition dao = method.getParent();
        final boolean includePrimaryKey = AnnotationUtility.extractAsBoolean(method.getElement(), annotation, AnnotationAttributeType.INCLUDE_PRIMARY_KEY);
        // define field list
        // every method parameter can be used only as insert field
        InsertType insertResultType = SqlInsertBuilder.detectInsertType(method);
        Set<String> fields;
        if (insertResultType == InsertType.INSERT_BEAN) {
            fields = extractFieldsFromAnnotation(method, annotation, includePrimaryKey);
        } else {
            fields = extractFieldsFromMethodParameters(method, annotation);
        }
        result.conflictAlgorithmType = ConflictAlgorithmType.valueOf(AnnotationUtility.extractAsEnumerationValue(method.getElement(), annotation, AnnotationAttributeType.CONFLICT_ALGORITHM_TYPE));
        StringBuilder builder = new StringBuilder();
        builder.append(INSERT_KEYWORD);
        builder.append(" " + result.conflictAlgorithmType.getSqlForInsert());
        builder.append(INTO_KEYWORD);
        builder.append(" " + dao.getEntitySimplyClassName());
        builder.append(" (");
        builder.append(forEachFields(fields, new OnFieldListener() {

            @Override
            public String onField(String item) {
                return item;
            }
        }));
        builder.append(") ");
        builder.append(VALUES_KEYWORD);
        final One<String> prefix = new One<>("");
        if (result.hasParamBean()) {
            prefix.value0 = result.paramBean + ".";
        }
        builder.append(" (");
        builder.append(forEachFields(fields, new OnFieldListener() {

            @Override
            public String onField(String item) {
                return "${" + prefix.value0 + item + "}";
            }
        }));
        builder.append(")");
        result.value = builder.toString();
    }
    result.operationType = JQLType.INSERT;
    result.dynamicReplace = new HashMap<>();
    return result;
}
Also used : Projected_columnsContext(com.abubusoft.kripton.processor.sqlite.grammars.jsql.JqlParser.Projected_columnsContext) Where_stmtContext(com.abubusoft.kripton.processor.sqlite.grammars.jsql.JqlParser.Where_stmtContext) Conflict_algorithmContext(com.abubusoft.kripton.processor.sqlite.grammars.jsql.JqlParser.Conflict_algorithmContext) One(com.abubusoft.kripton.common.One) JqlBaseListener(com.abubusoft.kripton.processor.sqlite.grammars.jsql.JqlBaseListener) Bind_parameterContext(com.abubusoft.kripton.processor.sqlite.grammars.jsql.JqlParser.Bind_parameterContext) BindSqlInsert(com.abubusoft.kripton.android.annotation.BindSqlInsert) SQLiteDaoDefinition(com.abubusoft.kripton.processor.sqlite.model.SQLiteDaoDefinition) Column_value_setContext(com.abubusoft.kripton.processor.sqlite.grammars.jsql.JqlParser.Column_value_setContext) InsertType(com.abubusoft.kripton.processor.sqlite.SqlInsertBuilder.InsertType)

Example 12 with SQLiteDaoDefinition

use of com.abubusoft.kripton.processor.sqlite.model.SQLiteDaoDefinition in project kripton by xcesco.

the class JQLBuilder method buildJQLDelete.

/**
 * <pre>
 * DELETE person WHERE id = ${bean.id} AND #{where}
 * </pre>
 *
 * @param method
 * @param preparedJql
 * @return
 */
private static JQL buildJQLDelete(SQLiteModelMethod method, final JQL result, Map<JQLDynamicStatementType, String> dynamicReplace, String preparedJql) {
    final SQLiteDaoDefinition dao = method.getParent();
    if (StringUtils.hasText(preparedJql)) {
        // in DELETE SQL only where statement can contains bind parameter
        result.value = preparedJql;
        JQLChecker.getInstance().analyze(method, result, new JqlBaseListener() {

            @Override
            public void enterBind_parameter(Bind_parameterContext ctx) {
                result.bindParameterOnWhereStatementCounter++;
            }
        });
        // where management
        JQLChecker.getInstance().replaceVariableStatements(method, preparedJql, new JQLReplaceVariableStatementListenerImpl() {

            @Override
            public String onWhere(String statement) {
                result.annotatedWhere = true;
                result.staticWhereConditions = true;
                return null;
            }
        });
    // if (result.containsSelectOperation) {
    // AssertKripton.failWithInvalidMethodSignException(!TypeUtility.typeName(Void.TYPE).equals(method.getReturnClass()),
    // method,
    // "method that contains SQL with inner SELECT can return only
    // void");
    // }
    } else {
        StringBuilder builder = new StringBuilder();
        builder.append(DELETE_KEYWORD + " " + FROM_KEYWORD);
        // entity name
        builder.append(" " + dao.getEntitySimplyClassName());
        builder.append(defineWhereStatement(method, result, BindSqlDelete.class, dynamicReplace));
        result.value = builder.toString();
    }
    result.operationType = JQLType.DELETE;
    result.dynamicReplace = dynamicReplace;
    return result;
}
Also used : BindSqlDelete(com.abubusoft.kripton.android.annotation.BindSqlDelete) JqlBaseListener(com.abubusoft.kripton.processor.sqlite.grammars.jsql.JqlBaseListener) Bind_parameterContext(com.abubusoft.kripton.processor.sqlite.grammars.jsql.JqlParser.Bind_parameterContext) SQLiteDaoDefinition(com.abubusoft.kripton.processor.sqlite.model.SQLiteDaoDefinition)

Example 13 with SQLiteDaoDefinition

use of com.abubusoft.kripton.processor.sqlite.model.SQLiteDaoDefinition in project kripton by xcesco.

the class SqlInsertBuilder method generateInsertForContentProvider.

/**
 * <p>
 * Generate insert used in content provider class.
 * </p>
 *
 * @param methodBuilder
 * @param method
 * @param insertResultType
 */
private static void generateInsertForContentProvider(TypeSpec.Builder classBuilder, final SQLiteModelMethod method, InsertType insertResultType) {
    final SQLiteDaoDefinition daoDefinition = method.getParent();
    final SQLiteEntity entity = daoDefinition.getEntity();
    final Set<String> columns = new LinkedHashSet<>();
    MethodSpec.Builder methodBuilder = MethodSpec.methodBuilder(method.contentProviderMethodName);
    ParameterSpec parameterSpec;
    parameterSpec = ParameterSpec.builder(Uri.class, "uri").build();
    methodBuilder.addParameter(parameterSpec);
    parameterSpec = ParameterSpec.builder(ContentValues.class, "contentValues").build();
    methodBuilder.addParameter(parameterSpec);
    methodBuilder.returns(Long.TYPE);
    SqlBuilderHelper.generateLogForContentProviderBeginning(method, methodBuilder);
    // just detect which columns are admitted
    JQLChecker.getInstance().replace(method, method.jql, new JQLReplacerListenerImpl(method) {

        @Override
        public String onColumnName(String columnName) {
            SQLProperty tempProperty = entity.get(columnName);
            AssertKripton.assertTrueOrUnknownPropertyInJQLException(tempProperty != null, method, columnName);
            columns.add(tempProperty.columnName);
            return tempProperty.columnName;
        }

        @Override
        public String onColumnFullyQualifiedName(String tableName, String columnName) {
            AssertKripton.fail("Inconsistent state");
            return null;
        }
    });
    // generate columnCheckSet
    SqlBuilderHelper.generateColumnCheckSet(classBuilder, method, columns);
    // retrieve content values
    methodBuilder.addStatement("$T _contentValues=contentValuesForContentProvider(contentValues)", KriptonContentValues.class);
    // generate column check
    SqlBuilderHelper.forEachColumnInContentValue(methodBuilder, method, "_contentValues.values().keySet()", true, null);
    methodBuilder.addCode("\n");
    // every controls was done in constructor of SQLiteModelMethod
    for (ContentUriPlaceHolder variable : method.contentProviderUriVariables) {
        SQLProperty entityProperty = entity.get(variable.value);
        if (entityProperty != null) {
            methodBuilder.addCode("// Add parameter $L at path segment $L\n", variable.value, variable.pathSegmentIndex);
            TypeName entityPropertyType = entityProperty.getPropertyType().getTypeName();
            if (TypeUtility.isString(entityPropertyType)) {
                methodBuilder.addStatement("contentValues.put($S, uri.getPathSegments().get($L))", entityProperty.columnName, variable.pathSegmentIndex);
            } else {
                methodBuilder.addStatement("contentValues.put($S, Long.valueOf(uri.getPathSegments().get($L)))", entityProperty.columnName, variable.pathSegmentIndex);
            }
        }
    }
    // generate log for inser operation
    SqlBuilderHelper.generateLogForContentValuesContentProvider(method, methodBuilder);
    ConflictAlgorithmType conflictAlgorithmType = InsertBeanHelper.getConflictAlgorithmType(method);
    String conflictString1 = "";
    String conflictString2 = "";
    if (conflictAlgorithmType != ConflictAlgorithmType.NONE) {
        conflictString1 = "WithOnConflict";
        conflictString2 = ", " + conflictAlgorithmType.getConflictAlgorithm();
        methodBuilder.addCode("// conflict algorithm $L\n", method.jql.conflictAlgorithmType);
    }
    methodBuilder.addComment("insert operation");
    methodBuilder.addStatement("long result = database().insert$L($S, null, _contentValues.values()$L)", conflictString1, daoDefinition.getEntity().getTableName(), conflictString2);
    if (method.getParent().getParent().generateRx) {
        GenericSQLHelper.generateSubjectNext(methodBuilder, SubjectType.INSERT);
    }
    // support for livedata
    if (daoDefinition.hasLiveData()) {
        methodBuilder.addComment("support for livedata");
        methodBuilder.addStatement(BindDaoBuilder.METHOD_NAME_REGISTRY_EVENT + "(result>0?1:0)");
    }
    methodBuilder.addStatement("return result");
    // javadoc
    // 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 contentValues content values\n");
    methodBuilder.addJavadoc("@return new row's id\n");
    classBuilder.addMethod(methodBuilder.build());
}
Also used : LinkedHashSet(java.util.LinkedHashSet) TypeName(com.squareup.javapoet.TypeName) MethodSpec(com.squareup.javapoet.MethodSpec) ParameterSpec(com.squareup.javapoet.ParameterSpec) ConflictAlgorithmType(com.abubusoft.kripton.android.sqlite.ConflictAlgorithmType) 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)

Example 14 with SQLiteDaoDefinition

use of com.abubusoft.kripton.processor.sqlite.model.SQLiteDaoDefinition in project kripton by xcesco.

the class SqlInsertBuilder method detectInsertType.

public static InsertType detectInsertType(SQLiteModelMethod method) {
    SQLiteDaoDefinition daoDefinition = method.getParent();
    SQLiteEntity entity = daoDefinition.getEntity();
    InsertType insertResultType = null;
    // check type of arguments
    int count = 0;
    for (Pair<String, TypeName> param : method.getParameters()) {
        if (TypeUtility.isEquals(param.value1, typeName(entity.getElement()))) {
            count++;
        }
    }
    AssertKripton.failWithInvalidMethodSignException(method.getParameters().size() == 0, method, " INSERT operations require at least one parameter");
    if (count == 0) {
        // method to insert raw data: no bean is used
        insertResultType = InsertType.INSERT_RAW;
        ModelAnnotation annotation = method.getAnnotation(BindSqlInsert.class);
        // check value attribute
        AssertKripton.failWithInvalidMethodSignException(AnnotationUtility.extractAsStringArray(method, annotation, AnnotationAttributeType.FIELDS).size() > 0, method, " can not use attribute %s in this kind of query definition", AnnotationAttributeType.FIELDS.getValue());
        // check excludeFields attribute
        AssertKripton.failWithInvalidMethodSignException(AnnotationUtility.extractAsStringArray(method, annotation, AnnotationAttributeType.EXCLUDED_FIELDS).size() > 0, method, " can not use attribute %s in this kind of query definition", AnnotationAttributeType.EXCLUDED_FIELDS.getValue());
        // check if there is only one parameter
        AssertKripton.failWithInvalidMethodSignException(method.getParameters().size() != 1 && TypeUtility.isEquals(method.getParameters().get(0).value1, daoDefinition.getEntityClassName()), method);
        // check no
        AssertKripton.failWithInvalidMethodSignException(annotation.getAttributeAsBoolean(AnnotationAttributeType.INCLUDE_PRIMARY_KEY), method, "attribute '%s' can not be used here", AnnotationAttributeType.INCLUDE_PRIMARY_KEY.getValue());
    } else if (count == 1) {
        insertResultType = InsertType.INSERT_BEAN;
        AssertKripton.failWithInvalidMethodSignException(method.getParameters().size() > 1, method, " aspected only one parameter of %s type", daoDefinition.getEntityClassName());
    } else {
        throw (new InvalidMethodSignException(method, "only one parameter of type " + typeName(entity.getElement()) + " can be used"));
    }
    return insertResultType;
}
Also used : TypeName(com.squareup.javapoet.TypeName) ModelAnnotation(com.abubusoft.kripton.processor.core.ModelAnnotation) SQLiteEntity(com.abubusoft.kripton.processor.sqlite.model.SQLiteEntity) InvalidMethodSignException(com.abubusoft.kripton.processor.exceptions.InvalidMethodSignException) SQLiteDaoDefinition(com.abubusoft.kripton.processor.sqlite.model.SQLiteDaoDefinition)

Example 15 with SQLiteDaoDefinition

use of com.abubusoft.kripton.processor.sqlite.model.SQLiteDaoDefinition in project kripton by xcesco.

the class SqlSelectBuilder method generateSelect.

/**
 * @param elementUtils
 * @param builder
 * @param method
 * @throws ClassNotFoundException
 */
public static void generateSelect(Builder builder, SQLiteModelMethod method) throws ClassNotFoundException {
    SQLiteDaoDefinition daoDefinition = method.getParent();
    SQLiteEntity entity = daoDefinition.getEntity();
    SelectBuilderUtility.SelectType selectResultType = null;
    // if true, field must be associate to ben attributes
    TypeName returnTypeName = method.getReturnClass();
    ParameterizedTypeName readBeanListener = ParameterizedTypeName.get(ClassName.get(OnReadBeanListener.class), ClassName.get(entity.getElement()));
    ClassName readCursorListener = ClassName.get(OnReadCursorListener.class);
    ModelAnnotation annotation = method.getAnnotation(BindSqlSelect.class);
    int pageSize = annotation.getAttributeAsInt(AnnotationAttributeType.PAGE_SIZE);
    AssertKripton.failWithInvalidMethodSignException(pageSize < 0, method, "in @%s(pageSize) must be set with positive number", BindSqlSelect.class.getSimpleName());
    AssertKripton.failWithInvalidMethodSignException(pageSize > 0 && method.hasDynamicPageSizeConditions(), method, "can not define @%s(pageSize) and mark a method parameter with @%s ", BindSqlSelect.class.getSimpleName(), BindSqlPageSize.class.getSimpleName());
    if (TypeUtility.isTypeIncludedIn(returnTypeName, Void.class, Void.TYPE)) {
        // return VOID (in the parameters must be a listener)
        if (SqlBuilderHelper.hasParameterOfType(method, readCursorListener)) {
            selectResultType = SelectBuilderUtility.SelectType.LISTENER_CURSOR;
        } else if (SqlBuilderHelper.hasParameterOfType(method, readBeanListener)) {
            selectResultType = SelectBuilderUtility.SelectType.LISTENER_BEAN;
        }
    } else if (TypeUtility.isTypeIncludedIn(returnTypeName, Cursor.class)) {
        // return Cursor (no listener)
        selectResultType = SelectBuilderUtility.SelectType.CURSOR;
    } else if (returnTypeName instanceof ParameterizedTypeName) {
        ParameterizedTypeName returnParameterizedTypeName = (ParameterizedTypeName) returnTypeName;
        ClassName returnParameterizedClassName = returnParameterizedTypeName.rawType;
        // return List (no listener)
        AssertKripton.assertTrueOrInvalidMethodSignException(returnParameterizedTypeName.typeArguments.size() == 1, method, "return type %s is not supported", returnTypeName);
        TypeName elementName = returnParameterizedTypeName.typeArguments.get(0);
        Class<?> wrapperClazz = Class.forName(returnParameterizedClassName.toString());
        if (PaginatedResult.class.isAssignableFrom(wrapperClazz)) {
            // method must have pageSize, statically or dynamically
            // defined
            AssertKripton.assertTrueOrInvalidMethodSignException(method.hasDynamicPageSizeConditions() || pageSize > 0, method, "use of PaginatedResult requires 'pageSize' attribute or a @%s annotated parameter", returnTypeName, BindSqlPageSize.class.getSimpleName());
            // paged result
            AssertKripton.assertTrueOrInvalidMethodSignException(TypeUtility.isEquals(elementName, entity.getName().toString()), method, "return type %s is not supported", returnTypeName);
            selectResultType = SelectBuilderUtility.SelectType.PAGED_RESULT;
            // set typeName of paginatedResult
            method.paginatedResultName = "paginatedResult";
        } else if (Collection.class.isAssignableFrom(wrapperClazz)) {
            if (TypeUtility.isEquals(elementName, entity.getName().toString())) {
                // entity list
                selectResultType = SelectBuilderUtility.SelectType.LIST_BEAN;
            } else if (SQLTransformer.isSupportedJDKType(elementName) || TypeUtility.isByteArray(elementName)) {
                // scalar list
                selectResultType = SelectBuilderUtility.SelectType.LIST_SCALAR;
            } else {
                AssertKripton.failWithInvalidMethodSignException(true, method, "%s is invalid return type", method.getReturnClass());
            }
        }
    } else if (TypeUtility.isEquals(returnTypeName, entity)) {
        // return one element (no listener)
        selectResultType = SelectBuilderUtility.SelectType.BEAN;
    } else if (SQLTransformer.isSupportedJDKType(returnTypeName) || TypeUtility.isByteArray(returnTypeName)) {
        // return single value string, int, long, short, double, float,
        // String (no listener)
        selectResultType = SelectBuilderUtility.SelectType.SCALAR;
    }
    AssertKripton.assertTrueOrInvalidMethodSignException(selectResultType != null, method, "'%s' as return type is not supported", returnTypeName);
    // generate select method
    selectResultType.generate(builder, method);
    if (method.hasLiveData()) {
        // generate
        selectResultType.generateLiveData(builder, method);
    }
    if (method.contentProviderEntryPathEnabled) {
        // we need to generate UPDATE or DELETE for content provider to
        generateSelectForContentProvider(builder, method, selectResultType);
    }
}
Also used : ParameterizedTypeName(com.squareup.javapoet.ParameterizedTypeName) TypeName(com.squareup.javapoet.TypeName) ArrayTypeName(com.squareup.javapoet.ArrayTypeName) OnReadBeanListener(com.abubusoft.kripton.android.sqlite.OnReadBeanListener) Cursor(android.database.Cursor) SQLiteDaoDefinition(com.abubusoft.kripton.processor.sqlite.model.SQLiteDaoDefinition) ModelAnnotation(com.abubusoft.kripton.processor.core.ModelAnnotation) SelectType(com.abubusoft.kripton.processor.sqlite.SelectBuilderUtility.SelectType) ClassName(com.squareup.javapoet.ClassName) Collection(java.util.Collection) SQLiteEntity(com.abubusoft.kripton.processor.sqlite.model.SQLiteEntity) BindSqlSelect(com.abubusoft.kripton.android.annotation.BindSqlSelect) ParameterizedTypeName(com.squareup.javapoet.ParameterizedTypeName) BindSqlPageSize(com.abubusoft.kripton.android.annotation.BindSqlPageSize)

Aggregations

SQLiteDaoDefinition (com.abubusoft.kripton.processor.sqlite.model.SQLiteDaoDefinition)43 SQLiteEntity (com.abubusoft.kripton.processor.sqlite.model.SQLiteEntity)25 SQLProperty (com.abubusoft.kripton.processor.sqlite.model.SQLProperty)22 TypeName (com.squareup.javapoet.TypeName)21 Pair (com.abubusoft.kripton.common.Pair)9 JQLProjection (com.abubusoft.kripton.processor.sqlite.grammars.jql.JQLProjection)9 ParameterizedTypeName (com.squareup.javapoet.ParameterizedTypeName)9 ArrayList (java.util.ArrayList)9 One (com.abubusoft.kripton.common.One)8 MethodSpec (com.squareup.javapoet.MethodSpec)8 InvalidMethodSignException (com.abubusoft.kripton.processor.exceptions.InvalidMethodSignException)6 ClassName (com.squareup.javapoet.ClassName)6 ModelAnnotation (com.abubusoft.kripton.processor.core.ModelAnnotation)5 JQLReplacerListenerImpl (com.abubusoft.kripton.processor.sqlite.grammars.jql.JQLReplacerListenerImpl)5 ArrayTypeName (com.squareup.javapoet.ArrayTypeName)5 TypeSpec (com.squareup.javapoet.TypeSpec)5 SQLiteStatement (android.database.sqlite.SQLiteStatement)4 BindSqlUpdate (com.abubusoft.kripton.android.annotation.BindSqlUpdate)4 GeneratedTypeElement (com.abubusoft.kripton.processor.element.GeneratedTypeElement)4 JqlBaseListener (com.abubusoft.kripton.processor.sqlite.grammars.jsql.JqlBaseListener)4