Search in sources :

Example 1 with StorIOSQLiteColumnMeta

use of com.pushtorefresh.storio.sqlite.annotations.processor.introspection.StorIOSQLiteColumnMeta in project storio by pushtorefresh.

the class StorIOSQLiteProcessor method processAnnotatedFieldOrMethod.

/**
     * Processes annotated field and returns result of processing or throws exception.
     *
     * @param annotatedField field that was annotated with {@link StorIOSQLiteColumn}
     * @return non-null {@link StorIOSQLiteColumnMeta} with meta information about field
     */
@NotNull
@Override
protected StorIOSQLiteColumnMeta processAnnotatedFieldOrMethod(@NotNull final Element annotatedField) {
    final JavaType javaType;
    try {
        javaType = JavaType.from(annotatedField.getKind() == ElementKind.FIELD ? annotatedField.asType() : ((ExecutableElement) annotatedField).getReturnType());
    } catch (Exception e) {
        throw new ProcessingException(annotatedField, "Unsupported type of field or method for " + StorIOSQLiteColumn.class.getSimpleName() + " annotation, if you need to serialize/deserialize field of that type " + "-> please write your own resolver: " + e.getMessage());
    }
    final StorIOSQLiteColumn storIOSQLiteColumn = annotatedField.getAnnotation(StorIOSQLiteColumn.class);
    if (storIOSQLiteColumn.ignoreNull() && annotatedField.asType().getKind().isPrimitive()) {
        throw new ProcessingException(annotatedField, "ignoreNull should not be used for primitive type: " + annotatedField.getSimpleName());
    }
    final String columnName = storIOSQLiteColumn.name();
    if (columnName.length() == 0) {
        throw new ProcessingException(annotatedField, "Column name is empty: " + annotatedField.getSimpleName());
    }
    return new StorIOSQLiteColumnMeta(annotatedField.getEnclosingElement(), annotatedField, annotatedField.getSimpleName().toString(), javaType, storIOSQLiteColumn);
}
Also used : StorIOSQLiteColumn(com.pushtorefresh.storio.sqlite.annotations.StorIOSQLiteColumn) StorIOSQLiteColumnMeta(com.pushtorefresh.storio.sqlite.annotations.processor.introspection.StorIOSQLiteColumnMeta) JavaType(com.pushtorefresh.storio.common.annotations.processor.introspection.JavaType) ProcessingException(com.pushtorefresh.storio.common.annotations.processor.ProcessingException) SkipNotAnnotatedClassWithAnnotatedParentException(com.pushtorefresh.storio.common.annotations.processor.SkipNotAnnotatedClassWithAnnotatedParentException) ProcessingException(com.pushtorefresh.storio.common.annotations.processor.ProcessingException) NotNull(org.jetbrains.annotations.NotNull)

Example 2 with StorIOSQLiteColumnMeta

use of com.pushtorefresh.storio.sqlite.annotations.processor.introspection.StorIOSQLiteColumnMeta in project storio by pushtorefresh.

the class StorIOSQLiteProcessor method validateAnnotatedClassesAndColumns.

@Override
protected void validateAnnotatedClassesAndColumns(@NotNull Map<TypeElement, StorIOSQLiteTypeMeta> annotatedClasses) {
    // Check that each annotated class has columns with at least one key column.
    for (final Map.Entry<TypeElement, StorIOSQLiteTypeMeta> annotatedType : annotatedClasses.entrySet()) {
        final StorIOSQLiteTypeMeta storIOSQLiteTypeMeta = annotatedType.getValue();
        if (storIOSQLiteTypeMeta.columns.size() == 0) {
            throw new ProcessingException(annotatedType.getKey(), "Class marked with " + StorIOSQLiteType.class.getSimpleName() + " annotation should have at least one field or method marked with " + StorIOSQLiteColumn.class.getSimpleName() + " annotation: " + storIOSQLiteTypeMeta.simpleName);
        }
        boolean hasAtLeastOneKeyColumn = false;
        for (final StorIOSQLiteColumnMeta columnMeta : storIOSQLiteTypeMeta.columns.values()) {
            if (columnMeta.storIOColumn.key()) {
                hasAtLeastOneKeyColumn = true;
                break;
            }
        }
        if (!hasAtLeastOneKeyColumn) {
            throw new ProcessingException(annotatedType.getKey(), "Class marked with " + StorIOSQLiteType.class.getSimpleName() + " annotation should have at least one KEY field or method marked with " + StorIOSQLiteColumn.class.getSimpleName() + " annotation: " + storIOSQLiteTypeMeta.simpleName);
        }
        if (storIOSQLiteTypeMeta.needCreator && storIOSQLiteTypeMeta.creator == null) {
            throw new ProcessingException(annotatedType.getKey(), "Class marked with " + StorIOSQLiteType.class.getSimpleName() + " annotation needs factory method or constructor marked with " + StorIOSQLiteCreator.class.getSimpleName() + " annotation: " + storIOSQLiteTypeMeta.simpleName);
        }
        if (storIOSQLiteTypeMeta.needCreator && storIOSQLiteTypeMeta.creator.getParameters().size() != storIOSQLiteTypeMeta.columns.size()) {
            throw new ProcessingException(annotatedType.getKey(), "Class marked with " + StorIOSQLiteType.class.getSimpleName() + " annotation needs factory method or constructor marked with " + StorIOSQLiteCreator.class.getSimpleName() + " annotation with the same amount of parameters as the number of columns: " + storIOSQLiteTypeMeta.simpleName);
        }
    }
}
Also used : StorIOSQLiteColumnMeta(com.pushtorefresh.storio.sqlite.annotations.processor.introspection.StorIOSQLiteColumnMeta) StorIOSQLiteTypeMeta(com.pushtorefresh.storio.sqlite.annotations.processor.introspection.StorIOSQLiteTypeMeta) TypeElement(javax.lang.model.element.TypeElement) Map(java.util.Map) ProcessingException(com.pushtorefresh.storio.common.annotations.processor.ProcessingException)

Example 3 with StorIOSQLiteColumnMeta

use of com.pushtorefresh.storio.sqlite.annotations.processor.introspection.StorIOSQLiteColumnMeta in project storio by pushtorefresh.

the class GetResolverGenerator method createMapFromCursorWithCreatorMethodSpec.

@NotNull
private MethodSpec createMapFromCursorWithCreatorMethodSpec(@NotNull StorIOSQLiteTypeMeta storIOSQLiteTypeMeta, @NotNull ClassName storIOSQLiteTypeClassName) {
    final MethodSpec.Builder builder = MethodSpec.methodBuilder("mapFromCursor").addJavadoc("{@inheritDoc}\n").addAnnotation(Override.class).addAnnotation(ANDROID_NON_NULL_ANNOTATION_CLASS_NAME).addModifiers(PUBLIC).returns(storIOSQLiteTypeClassName).addParameter(ParameterSpec.builder(ClassName.get("android.database", "Cursor"), "cursor").addAnnotation(ANDROID_NON_NULL_ANNOTATION_CLASS_NAME).build()).addCode("\n");
    final StringBuilder paramsBuilder = new StringBuilder();
    paramsBuilder.append("(");
    boolean first = true;
    for (final StorIOSQLiteColumnMeta columnMeta : storIOSQLiteTypeMeta.getOrderedColumns()) {
        final String columnIndex = "cursor.getColumnIndex(\"" + columnMeta.storIOColumn.name() + "\")";
        final JavaType javaType = columnMeta.javaType;
        final String getFromCursor = getFromCursorString(columnMeta, javaType, columnIndex);
        final TypeName name = TypeName.get(((ExecutableElement) columnMeta.element).getReturnType());
        final boolean isBoxed = javaType.isBoxedType();
        if (isBoxed) {
            // otherwise -> if primitive and value from cursor null -> fail early
            builder.addStatement("$T $L = null", name, columnMeta.getRealElementName());
            builder.beginControlFlow("if (!cursor.isNull($L))", columnIndex);
            builder.addStatement("$L = cursor.$L", columnMeta.getRealElementName(), getFromCursor);
            builder.endControlFlow();
        } else {
            builder.addStatement("$T $L = cursor.$L", name, columnMeta.getRealElementName(), getFromCursor);
        }
        if (!first) {
            paramsBuilder.append(", ");
        }
        first = false;
        paramsBuilder.append(columnMeta.getRealElementName());
    }
    paramsBuilder.append(")");
    builder.addCode("\n");
    if (storIOSQLiteTypeMeta.creator.getKind() == ElementKind.CONSTRUCTOR) {
        builder.addStatement("$T object = new $T" + paramsBuilder.toString(), storIOSQLiteTypeClassName, storIOSQLiteTypeClassName);
    } else {
        builder.addStatement("$T object = $T.$L", storIOSQLiteTypeClassName, storIOSQLiteTypeClassName, storIOSQLiteTypeMeta.creator.getSimpleName() + paramsBuilder.toString());
    }
    return builder.addCode("\n").addStatement("return object").build();
}
Also used : StorIOSQLiteColumnMeta(com.pushtorefresh.storio.sqlite.annotations.processor.introspection.StorIOSQLiteColumnMeta) JavaType(com.pushtorefresh.storio.common.annotations.processor.introspection.JavaType) ParameterizedTypeName(com.squareup.javapoet.ParameterizedTypeName) TypeName(com.squareup.javapoet.TypeName) MethodSpec(com.squareup.javapoet.MethodSpec) Common.getFromCursorString(com.pushtorefresh.storio.common.annotations.processor.generate.Common.getFromCursorString) NotNull(org.jetbrains.annotations.NotNull)

Example 4 with StorIOSQLiteColumnMeta

use of com.pushtorefresh.storio.sqlite.annotations.processor.introspection.StorIOSQLiteColumnMeta in project storio by pushtorefresh.

the class PutResolverGenerator method createMapToContentValuesMethodSpec.

@NotNull
private MethodSpec createMapToContentValuesMethodSpec(@NotNull StorIOSQLiteTypeMeta storIOSQLiteTypeMeta, @NotNull ClassName storIOSQLiteTypeClassName) {
    final MethodSpec.Builder builder = MethodSpec.methodBuilder("mapToContentValues").addJavadoc("{@inheritDoc}\n").addAnnotation(Override.class).addAnnotation(ANDROID_NON_NULL_ANNOTATION_CLASS_NAME).addModifiers(PUBLIC).returns(ClassName.get("android.content", "ContentValues")).addParameter(ParameterSpec.builder(storIOSQLiteTypeClassName, "object").addAnnotation(ANDROID_NON_NULL_ANNOTATION_CLASS_NAME).build()).addStatement("ContentValues contentValues = new ContentValues($L)", storIOSQLiteTypeMeta.columns.size()).addCode("\n");
    for (StorIOSQLiteColumnMeta columnMeta : storIOSQLiteTypeMeta.columns.values()) {
        final boolean ignoreNull = columnMeta.storIOColumn.ignoreNull();
        if (ignoreNull) {
            builder.beginControlFlow("if (object.$L != null)", columnMeta.elementName + (columnMeta.isMethod() ? "()" : ""));
        }
        builder.addStatement("contentValues.put($S, object.$L)", columnMeta.storIOColumn.name(), columnMeta.elementName + (columnMeta.isMethod() ? "()" : ""));
        if (ignoreNull) {
            builder.endControlFlow();
        }
    }
    return builder.addCode("\n").addStatement("return contentValues").build();
}
Also used : StorIOSQLiteColumnMeta(com.pushtorefresh.storio.sqlite.annotations.processor.introspection.StorIOSQLiteColumnMeta) MethodSpec(com.squareup.javapoet.MethodSpec) NotNull(org.jetbrains.annotations.NotNull)

Example 5 with StorIOSQLiteColumnMeta

use of com.pushtorefresh.storio.sqlite.annotations.processor.introspection.StorIOSQLiteColumnMeta in project storio by pushtorefresh.

the class StorIOSQLiteProcessor method processAnnotatedFieldsOrMethods.

/**
     * Processes fields annotated with {@link StorIOSQLiteColumn}.
     *
     * @param roundEnvironment current processing environment
     * @param annotatedClasses map of classes annotated with {@link StorIOSQLiteType}
     */
@Override
protected void processAnnotatedFieldsOrMethods(@NotNull final RoundEnvironment roundEnvironment, @NotNull Map<TypeElement, StorIOSQLiteTypeMeta> annotatedClasses) {
    final Set<? extends Element> elementsAnnotatedWithStorIOSQLiteColumn = roundEnvironment.getElementsAnnotatedWith(StorIOSQLiteColumn.class);
    for (final Element annotatedFieldElement : elementsAnnotatedWithStorIOSQLiteColumn) {
        try {
            validateAnnotatedFieldOrMethod(annotatedFieldElement);
            final StorIOSQLiteColumnMeta storIOSQLiteColumnMeta = processAnnotatedFieldOrMethod(annotatedFieldElement);
            final StorIOSQLiteTypeMeta storIOSQLiteTypeMeta = annotatedClasses.get(storIOSQLiteColumnMeta.enclosingElement);
            // If class already contains column with same name -> throw an exception.
            if (storIOSQLiteTypeMeta.columns.containsKey(storIOSQLiteColumnMeta.storIOColumn.name())) {
                throw new ProcessingException(annotatedFieldElement, "Column name already used in this class: " + storIOSQLiteColumnMeta.storIOColumn.name());
            }
            // If field annotation applied to both fields and methods in a same class.
            if ((storIOSQLiteTypeMeta.needCreator && !storIOSQLiteColumnMeta.isMethod()) || (!storIOSQLiteTypeMeta.needCreator && storIOSQLiteColumnMeta.isMethod() && !storIOSQLiteTypeMeta.columns.isEmpty())) {
                throw new ProcessingException(annotatedFieldElement, "Can't apply " + StorIOSQLiteColumn.class.getSimpleName() + " annotation to both fields and methods in a same class: " + storIOSQLiteTypeMeta.simpleName);
            }
            // If column needs creator then enclosing class needs it as well.
            if (!storIOSQLiteTypeMeta.needCreator && storIOSQLiteColumnMeta.isMethod()) {
                storIOSQLiteTypeMeta.needCreator = true;
            }
            // Put meta column info.
            storIOSQLiteTypeMeta.columns.put(storIOSQLiteColumnMeta.storIOColumn.name(), storIOSQLiteColumnMeta);
        } catch (SkipNotAnnotatedClassWithAnnotatedParentException e) {
            messager.printMessage(WARNING, e.getMessage());
        }
    }
}
Also used : StorIOSQLiteColumnMeta(com.pushtorefresh.storio.sqlite.annotations.processor.introspection.StorIOSQLiteColumnMeta) StorIOSQLiteTypeMeta(com.pushtorefresh.storio.sqlite.annotations.processor.introspection.StorIOSQLiteTypeMeta) TypeElement(javax.lang.model.element.TypeElement) ExecutableElement(javax.lang.model.element.ExecutableElement) Element(javax.lang.model.element.Element) SkipNotAnnotatedClassWithAnnotatedParentException(com.pushtorefresh.storio.common.annotations.processor.SkipNotAnnotatedClassWithAnnotatedParentException) ProcessingException(com.pushtorefresh.storio.common.annotations.processor.ProcessingException)

Aggregations

StorIOSQLiteColumnMeta (com.pushtorefresh.storio.sqlite.annotations.processor.introspection.StorIOSQLiteColumnMeta)7 NotNull (org.jetbrains.annotations.NotNull)5 ProcessingException (com.pushtorefresh.storio.common.annotations.processor.ProcessingException)3 JavaType (com.pushtorefresh.storio.common.annotations.processor.introspection.JavaType)3 MethodSpec (com.squareup.javapoet.MethodSpec)3 SkipNotAnnotatedClassWithAnnotatedParentException (com.pushtorefresh.storio.common.annotations.processor.SkipNotAnnotatedClassWithAnnotatedParentException)2 Common.getFromCursorString (com.pushtorefresh.storio.common.annotations.processor.generate.Common.getFromCursorString)2 StorIOSQLiteTypeMeta (com.pushtorefresh.storio.sqlite.annotations.processor.introspection.StorIOSQLiteTypeMeta)2 TypeElement (javax.lang.model.element.TypeElement)2 StorIOSQLiteColumn (com.pushtorefresh.storio.sqlite.annotations.StorIOSQLiteColumn)1 ParameterizedTypeName (com.squareup.javapoet.ParameterizedTypeName)1 TypeName (com.squareup.javapoet.TypeName)1 HashMap (java.util.HashMap)1 Map (java.util.Map)1 Element (javax.lang.model.element.Element)1 ExecutableElement (javax.lang.model.element.ExecutableElement)1