Search in sources :

Example 26 with Attribute

use of io.requery.meta.Attribute in project requery by requery.

the class UpsertMergeGenerator method write.

@Override
public void write(Output output, Map<Expression<?>, Object> values) {
    QueryBuilder qb = output.builder();
    // TODO only supporting 1 type for now
    Type<?> type = null;
    for (Expression<?> expression : values.keySet()) {
        if (expression.getExpressionType() == ExpressionType.ATTRIBUTE) {
            Attribute attribute = (Attribute) expression;
            type = attribute.getDeclaringType();
            break;
        }
    }
    if (type == null) {
        throw new IllegalStateException();
    }
    qb.keyword(MERGE).keyword(INTO).tableName(type.getName()).keyword(USING);
    appendUsing(output, values);
    qb.keyword(ON).openParenthesis();
    int count = 0;
    Set<? extends Attribute<?, ?>> attributes = type.getKeyAttributes();
    if (attributes.isEmpty()) {
        attributes = type.getAttributes();
    }
    for (Attribute<?, ?> attribute : attributes) {
        if (count > 0) {
            qb.keyword(Keyword.AND);
        }
        qb.aliasAttribute(type.getName(), attribute);
        qb.append(" = ");
        qb.aliasAttribute(alias, attribute);
        count++;
    }
    qb.closeParenthesis().space();
    // update fragment
    LinkedHashSet<Attribute<?, ?>> updates = new LinkedHashSet<>();
    for (Expression<?> expression : values.keySet()) {
        if (expression.getExpressionType() == ExpressionType.ATTRIBUTE) {
            Attribute attribute = (Attribute) expression;
            if (!attribute.isKey()) {
                updates.add(attribute);
            }
        }
    }
    qb.keyword(WHEN, MATCHED, THEN, UPDATE, SET).commaSeparated(updates, new QueryBuilder.Appender<Attribute<?, ?>>() {

        @Override
        public void append(QueryBuilder qb, Attribute<?, ?> value) {
            qb.attribute(value);
            qb.append(" = " + alias + "." + value.getName());
        }
    }).space();
    // insert fragment
    qb.keyword(WHEN, NOT, MATCHED, THEN, INSERT).openParenthesis().commaSeparatedExpressions(values.keySet()).closeParenthesis().space().keyword(VALUES).openParenthesis().commaSeparated(values.keySet(), new QueryBuilder.Appender<Expression<?>>() {

        @Override
        public void append(QueryBuilder qb, Expression<?> value) {
            qb.aliasAttribute(alias, (Attribute) value);
        }
    }).closeParenthesis();
}
Also used : LinkedHashSet(java.util.LinkedHashSet) Attribute(io.requery.meta.Attribute) Expression(io.requery.query.Expression) QueryBuilder(io.requery.sql.QueryBuilder)

Example 27 with Attribute

use of io.requery.meta.Attribute in project requery by requery.

the class EntityGenerator method generateMembers.

private void generateMembers(TypeSpec.Builder builder) {
    // generate property states
    if (!entity.isStateless()) {
        entity.attributes().stream().filter(attribute -> !attribute.isTransient()).forEach(attribute -> {
            TypeName stateType = ClassName.get(PropertyState.class);
            builder.addField(FieldSpec.builder(stateType, propertyStateFieldName(attribute), generatedMemberModifiers()).build());
        });
    }
    if (entity.isEmbedded() && !(entity.isImmutable() || entity.isUnimplementable())) {
        entity.attributes().stream().filter(attribute -> !attribute.isTransient()).forEach(attribute -> {
            ParameterizedTypeName attributeType = ParameterizedTypeName.get(ClassName.get(Attribute.class), nameResolver.typeNameOf(parent), resolveAttributeType(attribute));
            builder.addField(FieldSpec.builder(attributeType, attributeFieldName(attribute), generatedMemberModifiers(Modifier.FINAL)).build());
        });
    }
    // only generate for interfaces or if the entity is immutable but has no builder
    boolean generateMembers = typeElement.getKind().isInterface() || !entity.builderType().isPresent();
    Set<String> existingFieldNames = entity.attributes().stream().map(AttributeDescriptor::element).filter(it -> it.getKind() == ElementKind.FIELD).map(it -> it.getSimpleName().toString()).collect(Collectors.toSet());
    if (generateMembers) {
        for (AttributeDescriptor attribute : entity.attributes()) {
            Element element = attribute.element();
            if (element.getKind() == ElementKind.METHOD) {
                ExecutableElement methodElement = (ExecutableElement) element;
                TypeMirror typeMirror = methodElement.getReturnType();
                TypeName fieldName;
                if (attribute.isIterable()) {
                    fieldName = parameterizedCollectionName(typeMirror);
                } else if (attribute.isOptional()) {
                    typeMirror = tryFirstTypeArgument(attribute.typeMirror());
                    fieldName = TypeName.get(typeMirror);
                } else {
                    fieldName = nameResolver.tryGeneratedTypeName(typeMirror);
                }
                if (entity.isImmutable() || !existingFieldNames.contains(attribute.fieldName())) {
                    builder.addField(FieldSpec.builder(fieldName, attribute.fieldName(), generatedMemberModifiers()).build());
                }
            }
        }
    }
    if (entity.isImmutable()) {
        generateBuilder(builder, entity, "builder");
        entity.attributes().stream().filter(AttributeDescriptor::isEmbedded).forEach(attribute -> graph.embeddedDescriptorOf(attribute).ifPresent(embedded -> embedded.builderType().ifPresent(type -> {
            String fieldName = attribute.fieldName() + "Builder";
            generateBuilder(builder, embedded, fieldName);
        })));
    }
}
Also used : EntityProxy(io.requery.proxy.EntityProxy) PackageElement(javax.lang.model.element.PackageElement) Modifier(javax.lang.model.element.Modifier) FieldSpec(com.squareup.javapoet.FieldSpec) VariableElement(javax.lang.model.element.VariableElement) ClassName(com.squareup.javapoet.ClassName) WildcardTypeName(com.squareup.javapoet.WildcardTypeName) TypeElement(javax.lang.model.element.TypeElement) Elements(javax.lang.model.util.Elements) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) Map(java.util.Map) PropertyNameStyle(io.requery.PropertyNameStyle) ElementFilter(javax.lang.model.util.ElementFilter) Persistable(io.requery.Persistable) ParameterSpec(com.squareup.javapoet.ParameterSpec) Entity(io.requery.Entity) ElementKind(javax.lang.model.element.ElementKind) MethodSpec(com.squareup.javapoet.MethodSpec) ExecutableElement(javax.lang.model.element.ExecutableElement) Set(java.util.Set) ParameterizedTypeName(com.squareup.javapoet.ParameterizedTypeName) Element(javax.lang.model.element.Element) IOException(java.io.IOException) Attribute(io.requery.meta.Attribute) PropertyState(io.requery.proxy.PropertyState) TypeSpec(com.squareup.javapoet.TypeSpec) Collectors(java.util.stream.Collectors) TypeMirror(javax.lang.model.type.TypeMirror) List(java.util.List) PreInsertListener(io.requery.proxy.PreInsertListener) AnnotationSpec(com.squareup.javapoet.AnnotationSpec) StringJoiner(java.util.StringJoiner) ProcessingEnvironment(javax.annotation.processing.ProcessingEnvironment) Annotation(java.lang.annotation.Annotation) TypeName(com.squareup.javapoet.TypeName) Collections(java.util.Collections) WildcardTypeName(com.squareup.javapoet.WildcardTypeName) ParameterizedTypeName(com.squareup.javapoet.ParameterizedTypeName) TypeName(com.squareup.javapoet.TypeName) Attribute(io.requery.meta.Attribute) TypeMirror(javax.lang.model.type.TypeMirror) PackageElement(javax.lang.model.element.PackageElement) VariableElement(javax.lang.model.element.VariableElement) TypeElement(javax.lang.model.element.TypeElement) ExecutableElement(javax.lang.model.element.ExecutableElement) Element(javax.lang.model.element.Element) ExecutableElement(javax.lang.model.element.ExecutableElement) ParameterizedTypeName(com.squareup.javapoet.ParameterizedTypeName)

Example 28 with Attribute

use of io.requery.meta.Attribute in project requery by requery.

the class EntityGenerator method generateProxyMethods.

private void generateProxyMethods(TypeSpec.Builder builder) {
    // add proxy field
    TypeName entityType = entity.isEmbedded() ? nameResolver.typeNameOf(parent) : typeName;
    TypeName proxyName = parameterizedTypeName(EntityProxy.class, entityType);
    FieldSpec.Builder proxyField = FieldSpec.builder(proxyName, PROXY_NAME, generatedMemberModifiers(Modifier.FINAL, Modifier.TRANSIENT));
    if (!entity.isEmbedded()) {
        proxyField.initializer("new $T(this, $L)", proxyName, TYPE_NAME);
    }
    builder.addField(proxyField.build());
    for (AttributeDescriptor attribute : entity.attributes()) {
        boolean useField = attribute.isTransient() || attribute.isEmbedded();
        TypeMirror typeMirror = attribute.typeMirror();
        TypeName unboxedTypeName;
        if (attribute.isIterable()) {
            unboxedTypeName = parameterizedCollectionName(typeMirror);
        } else if (attribute.isOptional()) {
            unboxedTypeName = TypeName.get(tryFirstTypeArgument(attribute.typeMirror()));
        } else if (attribute.isEmbedded()) {
            EntityDescriptor embedded = graph.embeddedDescriptorOf(attribute).orElseThrow(IllegalStateException::new);
            unboxedTypeName = nameResolver.embeddedTypeNameOf(embedded, entity);
        } else {
            unboxedTypeName = nameResolver.tryGeneratedTypeName(typeMirror);
        }
        String attributeName = attribute.fieldName();
        String getterName = attribute.getterName();
        String fieldName = Names.upperCaseUnderscore(Names.removeMemberPrefixes(attributeName));
        if (entity.isEmbedded()) {
            fieldName = attributeFieldName(attribute);
        }
        // getter
        MethodSpec.Builder getter = MethodSpec.methodBuilder(getterName).addModifiers(Modifier.PUBLIC).returns(attribute.isOptional() ? TypeName.get(typeMirror) : unboxedTypeName);
        if (Mirrors.overridesMethod(types, typeElement, getterName)) {
            getter.addAnnotation(Override.class);
        }
        memberExtensions.forEach(extension -> extension.addToGetter(attribute, getter));
        if (useField) {
            if (attribute.isEmbedded()) {
                // have to cast to embedded type
                getter.addStatement("return ($T)this.$L", unboxedTypeName, attributeName);
            } else {
                getter.addStatement("return this.$L", attributeName);
            }
        } else if (attribute.isOptional()) {
            String ofNullable = "ofNullable";
            if ("com.google.common.base.Optional".equals(attribute.optionalClass())) {
                ofNullable = "fromNullable";
            }
            getter.addStatement("return $T.$L($L.get($L))", ClassName.bestGuess(attribute.optionalClass()), ofNullable, PROXY_NAME, fieldName);
        } else {
            getter.addStatement("return $L.get($L)", PROXY_NAME, fieldName);
        }
        builder.addMethod(getter.build());
        // setter
        String setterName = attribute.setterName();
        // if read only don't generate a public setter
        boolean readOnly = entity.isReadOnly() || attribute.isReadOnly();
        // edge case check if it's interface and we need to implement the setter
        if (entity.element().getKind().isInterface() && ElementFilter.methodsIn(entity.element().getEnclosedElements()).stream().anyMatch(element -> element.getSimpleName().toString().equals(setterName))) {
            readOnly = false;
        }
        if (!readOnly) {
            TypeName setTypeName = unboxedTypeName;
            boolean castType = false;
            // use wildcard generic collection type if necessary
            if (setTypeName instanceof ParameterizedTypeName) {
                ParameterizedTypeName parameterizedName = (ParameterizedTypeName) setTypeName;
                List<TypeName> arguments = parameterizedName.typeArguments;
                List<TypeName> wildcards = new ArrayList<>();
                for (TypeName argument : arguments) {
                    if (!(argument instanceof WildcardTypeName)) {
                        Elements elements = processingEnv.getElementUtils();
                        TypeElement element = elements.getTypeElement(argument.toString());
                        if (element != null && element.getKind() == ElementKind.INTERFACE) {
                            wildcards.add(WildcardTypeName.subtypeOf(argument));
                        } else {
                            wildcards.add(argument);
                        }
                    } else {
                        wildcards.add(argument);
                    }
                }
                TypeName[] array = new TypeName[wildcards.size()];
                setTypeName = ParameterizedTypeName.get(parameterizedName.rawType, wildcards.toArray(array));
                castType = true;
            }
            String paramName = Names.lowerCaseFirst(Names.removeMemberPrefixes(attributeName));
            MethodSpec.Builder setter = MethodSpec.methodBuilder(setterName).addModifiers(Modifier.PUBLIC).addParameter(setTypeName, paramName);
            if (useField) {
                setter.addStatement("this.$L = $L", attributeName, paramName);
            } else {
                if (castType) {
                    setter.addAnnotation(AnnotationSpec.builder(SuppressWarnings.class).addMember("value", "$S", "unchecked").build());
                    setter.addStatement("$L.set($L, ($T)$L)", PROXY_NAME, fieldName, unboxedTypeName, paramName);
                } else {
                    setter.addStatement("$L.set($L, $L)", PROXY_NAME, fieldName, paramName);
                }
            }
            memberExtensions.forEach(extension -> extension.addToSetter(attribute, setter));
            PropertyNameStyle style = entity.propertyNameStyle();
            if (style == PropertyNameStyle.FLUENT || style == PropertyNameStyle.FLUENT_BEAN) {
                setter.addStatement("return this");
                setter.returns(typeName);
            }
            builder.addMethod(setter.build());
        }
    }
    MethodSpec.Builder constructor = MethodSpec.constructorBuilder().addModifiers(Modifier.PUBLIC);
    if (entity.isEmbedded()) {
        constructor.addParameter(ParameterSpec.builder(proxyName, "proxy").build());
        constructor.addStatement("this.$L = proxy", PROXY_NAME);
        entity.attributes().stream().filter(attribute -> !attribute.isTransient()).forEach(attribute -> {
            ParameterizedTypeName attributeType = ParameterizedTypeName.get(ClassName.get(Attribute.class), nameResolver.typeNameOf(parent), resolveAttributeType(attribute));
            constructor.addParameter(ParameterSpec.builder(attributeType, attribute.name()).build());
            constructor.addStatement("this.$L = $L", attributeFieldName(attribute), attribute.name());
        });
    }
    generateListeners(constructor);
    // initialize the generated embedded entities
    entity.attributes().stream().filter(AttributeDescriptor::isEmbedded).forEach(attribute -> graph.embeddedDescriptorOf(attribute).ifPresent(embedded -> {
        ClassName embeddedName = nameResolver.embeddedTypeNameOf(embedded, entity);
        String format = embedded.attributes().stream().map(attr -> Names.upperCaseUnderscore(embeddedAttributeName(attribute, attr))).collect(Collectors.joining(", ", "$L = new $T($L, ", ")"));
        constructor.addStatement(format, attribute.fieldName(), embeddedName, PROXY_NAME);
    }));
    builder.addMethod(constructor.build());
}
Also used : EntityProxy(io.requery.proxy.EntityProxy) PackageElement(javax.lang.model.element.PackageElement) Modifier(javax.lang.model.element.Modifier) FieldSpec(com.squareup.javapoet.FieldSpec) VariableElement(javax.lang.model.element.VariableElement) ClassName(com.squareup.javapoet.ClassName) WildcardTypeName(com.squareup.javapoet.WildcardTypeName) TypeElement(javax.lang.model.element.TypeElement) Elements(javax.lang.model.util.Elements) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) Map(java.util.Map) PropertyNameStyle(io.requery.PropertyNameStyle) ElementFilter(javax.lang.model.util.ElementFilter) Persistable(io.requery.Persistable) ParameterSpec(com.squareup.javapoet.ParameterSpec) Entity(io.requery.Entity) ElementKind(javax.lang.model.element.ElementKind) MethodSpec(com.squareup.javapoet.MethodSpec) ExecutableElement(javax.lang.model.element.ExecutableElement) Set(java.util.Set) ParameterizedTypeName(com.squareup.javapoet.ParameterizedTypeName) Element(javax.lang.model.element.Element) IOException(java.io.IOException) Attribute(io.requery.meta.Attribute) PropertyState(io.requery.proxy.PropertyState) TypeSpec(com.squareup.javapoet.TypeSpec) Collectors(java.util.stream.Collectors) TypeMirror(javax.lang.model.type.TypeMirror) List(java.util.List) PreInsertListener(io.requery.proxy.PreInsertListener) AnnotationSpec(com.squareup.javapoet.AnnotationSpec) StringJoiner(java.util.StringJoiner) ProcessingEnvironment(javax.annotation.processing.ProcessingEnvironment) Annotation(java.lang.annotation.Annotation) TypeName(com.squareup.javapoet.TypeName) Collections(java.util.Collections) WildcardTypeName(com.squareup.javapoet.WildcardTypeName) ParameterizedTypeName(com.squareup.javapoet.ParameterizedTypeName) TypeName(com.squareup.javapoet.TypeName) MethodSpec(com.squareup.javapoet.MethodSpec) Attribute(io.requery.meta.Attribute) TypeElement(javax.lang.model.element.TypeElement) ArrayList(java.util.ArrayList) Elements(javax.lang.model.util.Elements) FieldSpec(com.squareup.javapoet.FieldSpec) TypeMirror(javax.lang.model.type.TypeMirror) ClassName(com.squareup.javapoet.ClassName) WildcardTypeName(com.squareup.javapoet.WildcardTypeName) ParameterizedTypeName(com.squareup.javapoet.ParameterizedTypeName) PropertyNameStyle(io.requery.PropertyNameStyle)

Example 29 with Attribute

use of io.requery.meta.Attribute in project requery by requery.

the class EntityMetaGenerator method generate.

void generate(TypeSpec.Builder builder) {
    boolean metadataOnly = entity.isImmutable() || entity.isUnimplementable();
    TypeName targetName = metadataOnly ? ClassName.get(entity.element()) : typeName;
    List<QualifiedName> generatedEmbeddedTypes = new LinkedList<>();
    entity.attributes().stream().filter(attribute -> !attribute.isTransient()).forEach(attribute -> {
        String fieldName = upperCaseUnderscoreRemovePrefixes(attribute.fieldName());
        if (attribute.isForeignKey() && attribute.cardinality() != null) {
            // generate a foreign key attribute for use in queries but not stored in the type
            graph.referencingEntity(attribute).flatMap(entity -> graph.referencingAttribute(attribute, entity)).ifPresent(foreignKey -> {
                String name = fieldName + "_ID";
                TypeMirror mirror = foreignKey.typeMirror();
                builder.addField(generateAttribute(attribute, null, targetName, name, mirror, true));
                expressionNames.add(name);
            });
        }
        if (attribute.isEmbedded()) {
            graph.embeddedDescriptorOf(attribute).ifPresent(embedded -> {
                generateEmbeddedAttributes(attribute, embedded, builder, targetName);
                if (!generatedEmbeddedTypes.contains(embedded.typeName())) {
                    generatedEmbeddedTypes.add(embedded.typeName());
                    generateEmbeddedEntity(embedded);
                }
            });
        } else {
            TypeMirror mirror = attribute.typeMirror();
            builder.addField(generateAttribute(attribute, null, targetName, fieldName, mirror, false));
            attributeNames.add(fieldName);
        }
    });
    generateType(builder, targetName);
}
Also used : EntityProxy(io.requery.proxy.EntityProxy) Modifier(javax.lang.model.element.Modifier) BooleanProperty(io.requery.proxy.BooleanProperty) FieldSpec(com.squareup.javapoet.FieldSpec) LongProperty(io.requery.proxy.LongProperty) VariableElement(javax.lang.model.element.VariableElement) ClassName(com.squareup.javapoet.ClassName) QueryAttribute(io.requery.meta.QueryAttribute) TypeBuilder(io.requery.meta.TypeBuilder) NumericAttribute(io.requery.meta.NumericAttribute) TypeElement(javax.lang.model.element.TypeElement) ReferentialAction(io.requery.ReferentialAction) HashSet(java.util.HashSet) Function(io.requery.util.function.Function) ByteProperty(io.requery.proxy.ByteProperty) Diagnostic(javax.tools.Diagnostic) Type(io.requery.meta.Type) FloatProperty(io.requery.proxy.FloatProperty) ElementFilter(javax.lang.model.util.ElementFilter) LinkedList(java.util.LinkedList) CodeBlock(com.squareup.javapoet.CodeBlock) Property(io.requery.proxy.Property) MethodSpec(com.squareup.javapoet.MethodSpec) IntProperty(io.requery.proxy.IntProperty) ExecutableElement(javax.lang.model.element.ExecutableElement) Supplier(io.requery.util.function.Supplier) Set(java.util.Set) ParameterizedTypeName(com.squareup.javapoet.ParameterizedTypeName) IOException(java.io.IOException) Attribute(io.requery.meta.Attribute) PropertyState(io.requery.proxy.PropertyState) TypeSpec(com.squareup.javapoet.TypeSpec) Order(io.requery.query.Order) QueryExpression(io.requery.meta.QueryExpression) TypeKind(javax.lang.model.type.TypeKind) CascadeAction(io.requery.CascadeAction) TypeMirror(javax.lang.model.type.TypeMirror) List(java.util.List) Cardinality(io.requery.meta.Cardinality) DoubleProperty(io.requery.proxy.DoubleProperty) StringJoiner(java.util.StringJoiner) ProcessingEnvironment(javax.annotation.processing.ProcessingEnvironment) TypeName(com.squareup.javapoet.TypeName) Optional(java.util.Optional) ShortProperty(io.requery.proxy.ShortProperty) StringAttribute(io.requery.meta.StringAttribute) ParameterizedTypeName(com.squareup.javapoet.ParameterizedTypeName) TypeName(com.squareup.javapoet.TypeName) TypeMirror(javax.lang.model.type.TypeMirror) LinkedList(java.util.LinkedList)

Example 30 with Attribute

use of io.requery.meta.Attribute 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();
        if (isQueryable) {
            Class<?> attributeClass;
            String kotlinDelegate;
            switch(attribute.getType()) {
                case STRING:
                    attributeClass = StringAttribute.class;
                    kotlinDelegate = "StringAttributeDelegate";
                    break;
                case NUMERIC:
                    attributeClass = NumericAttribute.class;
                    kotlinDelegate = "NumericAttributeDelegate";
                    break;
                default:
                case DEFAULT:
                    attributeClass = QueryAttribute.class;
                    kotlinDelegate = "AttributeDelegate";
                    break;
            }
            attributeType = ClassName.get(attributeClass);
            // check if the kotlin delegate is available, if so use that
            TypeElement delegateType = elements.getTypeElement("io.requery.meta." + kotlinDelegate);
            if (delegateType != null) {
                attributeType = ClassName.get(delegateType);
                useKotlinDelegate = true;
            }
        } else {
            attributeType = ClassName.get(Attribute.class);
        }
        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(".setReadOnly($L)\n", attribute.isReadOnly());
    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().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());
                });
            }
        });
    }
    switch(attribute.getType()) {
        case DEFAULT:
            builder.add(".build()");
            break;
        case STRING:
            builder.add(".buildString()");
            break;
        case NUMERIC:
            builder.add(".buildNumeric()");
            break;
    }
    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) NumericAttribute(io.requery.meta.NumericAttribute) Attribute(io.requery.meta.Attribute) StringAttribute(io.requery.meta.StringAttribute) 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

Attribute (io.requery.meta.Attribute)30 QueryAttribute (io.requery.meta.QueryAttribute)13 ClassName (com.squareup.javapoet.ClassName)5 FieldSpec (com.squareup.javapoet.FieldSpec)5 ParameterizedTypeName (com.squareup.javapoet.ParameterizedTypeName)5 TypeName (com.squareup.javapoet.TypeName)5 TypeSpec (com.squareup.javapoet.TypeSpec)5 EntityProxy (io.requery.proxy.EntityProxy)5 Expression (io.requery.query.Expression)5 ResultSet (java.sql.ResultSet)5 SQLException (java.sql.SQLException)5 ArrayList (java.util.ArrayList)5 List (java.util.List)5 MethodSpec (com.squareup.javapoet.MethodSpec)4 PropertyState (io.requery.proxy.PropertyState)4 UPDATE (io.requery.query.element.QueryType.UPDATE)4 StringJoiner (java.util.StringJoiner)4 TypeElement (javax.lang.model.element.TypeElement)4 TypeMirror (javax.lang.model.type.TypeMirror)4 CodeBlock (com.squareup.javapoet.CodeBlock)3