Search in sources :

Example 1 with CascadeAction

use of io.requery.CascadeAction in project requery by requery.

the class EntityMetaGenerator method generateAttribute.

private FieldSpec generateAttribute(AttributeDescriptor attribute, AttributeDescriptor parent, TypeName targetName, String fieldName, TypeMirror mirror, boolean expression) {
    TypeMirror typeMirror = mirror;
    TypeName typeName;
    if (attribute.isIterable()) {
        typeMirror = tryFirstTypeArgument(typeMirror);
        typeName = parameterizedCollectionName(attribute.typeMirror());
    } else if (attribute.isOptional()) {
        typeMirror = tryFirstTypeArgument(typeMirror);
        typeName = TypeName.get(typeMirror);
    } else {
        typeName = nameResolver.generatedTypeNameOf(typeMirror).orElse(null);
    }
    if (typeName == null) {
        typeName = boxedTypeName(typeMirror);
    }
    ParameterizedTypeName type;
    ClassName attributeType = null;
    boolean useKotlinDelegate = false;
    if (expression) {
        type = parameterizedTypeName(QueryExpression.class, typeName);
    } else {
        // if it's an association don't make it available as a query attribute
        boolean isQueryable = attribute.cardinality() == null || attribute.isForeignKey();
        Class<?> attributeClass = isQueryable ? QueryAttribute.class : Attribute.class;
        attributeType = ClassName.get(attributeClass);
        if (isQueryable) {
            TypeElement delegateType = elements.getTypeElement(KOTLIN_ATTRIBUTE_DELEGATE);
            if (delegateType != null) {
                attributeType = ClassName.get(delegateType);
                useKotlinDelegate = true;
            }
        }
        type = ParameterizedTypeName.get(attributeType, targetName, typeName);
    }
    CodeBlock.Builder builder = CodeBlock.builder();
    String attributeName = attribute.name();
    if (parent != null && parent.isEmbedded()) {
        attributeName = embeddedAttributeName(parent, attribute);
    }
    if (attribute.isIterable()) {
        typeMirror = tryFirstTypeArgument(typeMirror);
        TypeName name = nameResolver.tryGeneratedTypeName(typeMirror);
        TypeElement collection = (TypeElement) types.asElement(attribute.typeMirror());
        ParameterizedTypeName builderName = parameterizedTypeName(attribute.builderClass(), targetName, typeName, name);
        builder.add("\nnew $T($S, $T.class, $T.class)\n", builderName, attributeName, ClassName.get(collection), name);
    } else if (attribute.isMap() && attribute.cardinality() != null) {
        List<TypeMirror> parameters = Mirrors.listGenericTypeArguments(typeMirror);
        // key type
        TypeName keyName = TypeName.get(parameters.get(0));
        // value type
        typeMirror = parameters.get(1);
        TypeName valueName = nameResolver.tryGeneratedTypeName(typeMirror);
        TypeElement valueElement = (TypeElement) types.asElement(attribute.typeMirror());
        ParameterizedTypeName builderName = parameterizedTypeName(attribute.builderClass(), targetName, typeName, keyName, valueName);
        builder.add("\nnew $T($S, $T.class, $T.class, $T.class)\n", builderName, attributeName, ClassName.get(valueElement), keyName, valueName);
    } else {
        ParameterizedTypeName builderName = parameterizedTypeName(attribute.builderClass(), targetName, typeName);
        TypeName classType = typeName;
        if (typeMirror.getKind().isPrimitive()) {
            // if primitive just use the primitive class not the boxed version
            classType = TypeName.get(typeMirror);
        }
        String statement;
        if (Mirrors.listGenericTypeArguments(typeMirror).size() > 0) {
            // use the erased type and cast to class
            classType = TypeName.get(types.erasure(typeMirror));
            statement = "\nnew $T($S, (Class)$T.class)\n";
        } else {
            statement = "\nnew $T($S, $T.class)\n";
        }
        builder.add(statement, builderName, attributeName, classType);
    }
    if (!expression) {
        generateProperties(attribute, parent, typeMirror, targetName, typeName, builder);
    }
    // attribute builder properties
    if (attribute.isKey()) {
        builder.add(".setKey(true)\n");
    }
    builder.add(".setGenerated($L)\n", attribute.isGenerated());
    builder.add(".setLazy($L)\n", attribute.isLazy());
    builder.add(".setNullable($L)\n", attribute.isNullable());
    builder.add(".setUnique($L)\n", attribute.isUnique());
    if (!Names.isEmpty(attribute.defaultValue())) {
        builder.add(".setDefaultValue($S)\n", attribute.defaultValue());
    }
    if (!Names.isEmpty(attribute.collate())) {
        builder.add(".setCollate($S)\n", attribute.collate());
    }
    if (attribute.columnLength() != null) {
        builder.add(".setLength($L)\n", attribute.columnLength());
    }
    if (!Names.isEmpty(attribute.definition())) {
        builder.add(".setDefinition($S)\n", attribute.definition());
    }
    if (attribute.isVersion()) {
        builder.add(".setVersion($L)\n", attribute.isVersion());
    }
    if (attribute.converterName() != null) {
        builder.add(".setConverter(new $L())\n", attribute.converterName());
    }
    if (attribute.isForeignKey()) {
        builder.add(".setForeignKey($L)\n", attribute.isForeignKey());
        Optional<EntityDescriptor> referencedType = graph.referencingEntity(attribute);
        referencedType.ifPresent(referenced -> {
            builder.add(".setReferencedClass($T.class)\n", referenced.isImmutable() ? TypeName.get(referenced.element().asType()) : nameResolver.typeNameOf(referenced));
            graph.referencingAttribute(attribute, referenced).ifPresent(referencedAttribute -> {
                String name = upperCaseUnderscoreRemovePrefixes(referencedAttribute.fieldName());
                TypeSpec provider = CodeGeneration.createAnonymousSupplier(ClassName.get(Attribute.class), CodeBlock.builder().addStatement("return $T.$L", nameResolver.typeNameOf(referenced), name).build());
                builder.add(".setReferencedAttribute($L)\n", provider);
            });
        });
    }
    if (attribute.isIndexed()) {
        builder.add(".setIndexed($L)\n", attribute.isIndexed());
        if (!attribute.indexNames().isEmpty()) {
            StringJoiner joiner = new StringJoiner(",");
            attribute.indexNames().forEach(name -> joiner.add("$S"));
            builder.add(".setIndexNames(" + joiner + ")\n", attribute.indexNames().toArray());
        }
    }
    if (attribute.deleteAction() != null) {
        builder.add(".setDeleteAction($T.$L)\n", ClassName.get(ReferentialAction.class), attribute.deleteAction());
    }
    if (attribute.updateAction() != null) {
        builder.add(".setUpdateAction($T.$L)\n", ClassName.get(ReferentialAction.class), attribute.updateAction());
    }
    if (!attribute.cascadeActions().isEmpty()) {
        StringJoiner joiner = new StringJoiner(",");
        attribute.cascadeActions().forEach(action -> joiner.add("$T.$L"));
        int index = 0;
        ClassName cascadeClass = ClassName.get(CascadeAction.class);
        Object[] args = new Object[attribute.cascadeActions().size() * 2];
        for (CascadeAction action : attribute.cascadeActions()) {
            args[index++] = cascadeClass;
            args[index++] = action;
        }
        builder.add(".setCascadeAction(" + joiner + ")\n", args);
    }
    if (attribute.cardinality() != null) {
        if (!expression) {
            builder.add(".setCardinality($T.$L)\n", ClassName.get(Cardinality.class), attribute.cardinality());
        }
        graph.referencingEntity(attribute).ifPresent(referenced -> {
            Set<AttributeDescriptor> mappings = graph.mappedAttributes(entity, attribute, referenced);
            if (attribute.cardinality() == Cardinality.MANY_TO_MANY) {
                generateJunctionType(attribute, referenced, mappings).ifPresent(name -> builder.add(".setReferencedClass($T.class)\n", name));
            }
            if (mappings.size() == 1) {
                AttributeDescriptor mapped = mappings.iterator().next();
                String staticMemberName = upperCaseUnderscoreRemovePrefixes(mapped.fieldName());
                TypeSpec provider = CodeGeneration.createAnonymousSupplier(ClassName.get(Attribute.class), CodeBlock.builder().addStatement("return $T.$L", nameResolver.typeNameOf(referenced), staticMemberName).build());
                builder.add(".setMappedAttribute($L)\n", provider);
            }
            if (attribute.orderBy() != null) {
                referenced.attributes().values().stream().filter(entry -> entry.name().equals(attribute.orderBy())).findFirst().ifPresent(orderBy -> {
                    String staticMemberName = upperCaseUnderscoreRemovePrefixes(orderBy.fieldName());
                    TypeSpec provider = CodeGeneration.createAnonymousSupplier(ClassName.get(Attribute.class), CodeBlock.builder().addStatement("return $T.$L", nameResolver.typeNameOf(referenced), staticMemberName).build());
                    builder.add(".setOrderByAttribute($L)\n", provider);
                    builder.add(".setOrderByDirection($T.$L)\n", ClassName.get(Order.class), attribute.orderByDirection());
                });
            }
        });
    }
    builder.add(".build()");
    FieldSpec.Builder field = FieldSpec.builder(type, fieldName, Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL);
    if (useKotlinDelegate) {
        return field.initializer("new $T($L)", attributeType, builder.build()).build();
    } else {
        return field.initializer("$L", builder.build()).build();
    }
}
Also used : ParameterizedTypeName(com.squareup.javapoet.ParameterizedTypeName) TypeName(com.squareup.javapoet.TypeName) QueryAttribute(io.requery.meta.QueryAttribute) Attribute(io.requery.meta.Attribute) ReferentialAction(io.requery.ReferentialAction) TypeMirror(javax.lang.model.type.TypeMirror) ClassName(com.squareup.javapoet.ClassName) LinkedList(java.util.LinkedList) List(java.util.List) QueryExpression(io.requery.meta.QueryExpression) StringJoiner(java.util.StringJoiner) ParameterizedTypeName(com.squareup.javapoet.ParameterizedTypeName) CascadeAction(io.requery.CascadeAction) Order(io.requery.query.Order) Cardinality(io.requery.meta.Cardinality) TypeElement(javax.lang.model.element.TypeElement) CodeBlock(com.squareup.javapoet.CodeBlock) FieldSpec(com.squareup.javapoet.FieldSpec) TypeSpec(com.squareup.javapoet.TypeSpec)

Aggregations

ClassName (com.squareup.javapoet.ClassName)1 CodeBlock (com.squareup.javapoet.CodeBlock)1 FieldSpec (com.squareup.javapoet.FieldSpec)1 ParameterizedTypeName (com.squareup.javapoet.ParameterizedTypeName)1 TypeName (com.squareup.javapoet.TypeName)1 TypeSpec (com.squareup.javapoet.TypeSpec)1 CascadeAction (io.requery.CascadeAction)1 ReferentialAction (io.requery.ReferentialAction)1 Attribute (io.requery.meta.Attribute)1 Cardinality (io.requery.meta.Cardinality)1 QueryAttribute (io.requery.meta.QueryAttribute)1 QueryExpression (io.requery.meta.QueryExpression)1 Order (io.requery.query.Order)1 LinkedList (java.util.LinkedList)1 List (java.util.List)1 StringJoiner (java.util.StringJoiner)1 TypeElement (javax.lang.model.element.TypeElement)1 TypeMirror (javax.lang.model.type.TypeMirror)1