Search in sources :

Example 1 with ForeignKey

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

the class EntityGraphValidator method validateEntity.

private Set<ElementValidator> validateEntity(EntityDescriptor entity) {
    Set<ElementValidator> results = new LinkedHashSet<>();
    for (Map.Entry<Element, ? extends AttributeDescriptor> entry : entity.attributes().entrySet()) {
        AttributeDescriptor attribute = entry.getValue();
        ElementValidator validator = new ElementValidator(attribute.element(), processingEnvironment);
        // check mapped associations
        if (attribute.cardinality() != null) {
            Optional<EntityDescriptor> referencingEntity = graph.referencingEntity(attribute);
            if (referencingEntity.isPresent()) {
                EntityDescriptor referenced = referencingEntity.get();
                Set<AttributeDescriptor> mappings = graph.mappedAttributes(entity, attribute, referenced);
                if (mappings.isEmpty()) {
                    if (attribute.cardinality() == Cardinality.ONE_TO_ONE && !attribute.isForeignKey()) {
                        validator.error("Single sided @OneToOne should specify @ForeignKey/@JoinColumn");
                    } else if (attribute.cardinality() == Cardinality.ONE_TO_MANY) {
                        validator.error("Corresponding @OneToMany relation not present in mapped entity");
                    }
                } else if (mappings.size() == 1) {
                    // validate the relationship
                    AttributeDescriptor mapped = mappings.iterator().next();
                    validateRelationship(validator, attribute, mapped);
                } else if (mappings.size() > 1) {
                    validator.warning(mappings.size() + " mappings found for: " + attribute + " -> " + referenced.typeName());
                }
            } else {
                validator.warning("Couldn't find referenced element for " + attribute);
            }
        } else {
            Types types = processingEnvironment.getTypeUtils();
            for (EntityDescriptor descriptor : graph.entities()) {
                if (types.isSubtype(descriptor.element().asType(), attribute.typeMirror()) && attribute.converterName() == null) {
                    validator.error("Entity reference missing relationship annotation");
                }
            }
        }
        // checked foreign key reference
        if (attribute.isForeignKey()) {
            Optional<EntityDescriptor> referenced = graph.referencingEntity(attribute);
            if (referenced.isPresent()) {
                Optional<? extends AttributeDescriptor> referencedElement = graph.referencingAttribute(attribute, referenced.get());
                if (!referencedElement.isPresent()) {
                    validator.warning("Couldn't find referenced element " + referenced.get().typeName() + " for " + attribute);
                } else {
                    // check all the foreign keys and see if they reference this entity
                    referenced.get().attributes().values().stream().filter(AttributeDescriptor::isForeignKey).map(graph::referencingEntity).filter(Optional::isPresent).map(Optional::get).filter(entity::equals).findAny().ifPresent(other -> validator.warning("Circular Foreign Key reference found between " + entity.typeName() + " and " + other.typeName(), ForeignKey.class));
                }
            } else if (attribute.cardinality() != null) {
                validator.error("Couldn't find referenced attribute " + attribute.referencedColumn() + " for " + attribute);
            }
        }
        if (validator.hasErrors() || validator.hasWarnings()) {
            results.add(validator);
        }
    }
    return results;
}
Also used : LinkedHashSet(java.util.LinkedHashSet) Types(javax.lang.model.util.Types) Optional(java.util.Optional) Element(javax.lang.model.element.Element) ForeignKey(io.requery.ForeignKey) Map(java.util.Map)

Example 2 with ForeignKey

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

the class AttributeMember method processBasicColumnAnnotations.

private void processBasicColumnAnnotations(ElementValidator validator) {
    if (annotationOf(Key.class).isPresent() || annotationOf(javax.persistence.Id.class).isPresent()) {
        isKey = true;
        if (isTransient) {
            validator.error("Key field cannot be transient");
        }
    }
    // generated keys can't be set through a setter
    if (annotationOf(Generated.class).isPresent() || annotationOf(GeneratedValue.class).isPresent()) {
        isGenerated = true;
        isReadOnly = true;
        // check generation strategy
        annotationOf(GeneratedValue.class).ifPresent(generatedValue -> {
            if (generatedValue.strategy() != GenerationType.IDENTITY && generatedValue.strategy() != GenerationType.AUTO) {
                validator.warning("GeneratedValue.strategy() " + generatedValue.strategy() + " not supported", generatedValue.getClass());
            }
        });
    }
    if (annotationOf(Lazy.class).isPresent()) {
        if (isKey) {
            cannotCombine(validator, Key.class, Lazy.class);
        }
        isLazy = true;
    }
    if (annotationOf(Nullable.class).isPresent() || isOptional || Mirrors.findAnnotationMirror(element(), "javax.annotation.Nullable").isPresent()) {
        isNullable = true;
    } else {
        // if not a primitive type the value assumed nullable
        if (element().getKind().isField()) {
            isNullable = !element().asType().getKind().isPrimitive();
        } else if (element().getKind() == ElementKind.METHOD) {
            ExecutableElement executableElement = (ExecutableElement) element();
            isNullable = !executableElement.getReturnType().getKind().isPrimitive();
        }
    }
    if (annotationOf(Version.class).isPresent() || annotationOf(javax.persistence.Version.class).isPresent()) {
        isVersion = true;
        if (isKey) {
            cannotCombine(validator, Key.class, Version.class);
        }
    }
    Column column = annotationOf(Column.class).orElse(null);
    ForeignKey foreignKey = null;
    boolean foreignKeySetFromColumn = false;
    if (column != null) {
        name = "".equals(column.name()) ? null : column.name();
        isUnique = column.unique();
        isNullable = column.nullable();
        defaultValue = column.value();
        collate = column.collate();
        definition = column.definition();
        if (column.length() > 0) {
            length = column.length();
        }
        if (column.foreignKey().length > 0) {
            foreignKey = column.foreignKey()[0];
            foreignKeySetFromColumn = true;
        }
    }
    if (!foreignKeySetFromColumn) {
        foreignKey = annotationOf(ForeignKey.class).orElse(null);
    }
    if (foreignKey != null) {
        this.isForeignKey = true;
        deleteAction = foreignKey.delete();
        updateAction = foreignKey.update();
        referencedColumn = foreignKey.referencedColumn();
    }
    annotationOf(Index.class).ifPresent(index -> {
        isIndexed = true;
        Collections.addAll(indexNames, index.value());
    });
    // JPA specific
    annotationOf(Basic.class).ifPresent(basic -> {
        isNullable = basic.optional();
        isLazy = basic.fetch() == FetchType.LAZY;
    });
    annotationOf(javax.persistence.Index.class).ifPresent(index -> {
        isIndexed = true;
        Collections.addAll(indexNames, index.name());
    });
    annotationOf(JoinColumn.class).ifPresent(joinColumn -> {
        javax.persistence.ForeignKey joinForeignKey = joinColumn.foreignKey();
        this.isForeignKey = true;
        ConstraintMode constraintMode = joinForeignKey.value();
        switch(constraintMode) {
            default:
            case PROVIDER_DEFAULT:
            case CONSTRAINT:
                deleteAction = ReferentialAction.CASCADE;
                updateAction = ReferentialAction.CASCADE;
                break;
            case NO_CONSTRAINT:
                deleteAction = ReferentialAction.NO_ACTION;
                updateAction = ReferentialAction.NO_ACTION;
                break;
        }
        this.referencedTable = joinColumn.table();
        this.referencedColumn = joinColumn.referencedColumnName();
    });
    annotationOf(javax.persistence.Column.class).ifPresent(persistenceColumn -> {
        name = "".equals(persistenceColumn.name()) ? null : persistenceColumn.name();
        isUnique = persistenceColumn.unique();
        isNullable = persistenceColumn.nullable();
        length = persistenceColumn.length();
        isReadOnly = !persistenceColumn.updatable();
        definition = persistenceColumn.columnDefinition();
    });
    annotationOf(Enumerated.class).ifPresent(enumerated -> {
        EnumType enumType = enumerated.value();
        if (enumType == EnumType.ORDINAL) {
            converterType = EnumOrdinalConverter.class.getCanonicalName();
        }
    });
}
Also used : Basic(javax.persistence.Basic) ExecutableElement(javax.lang.model.element.ExecutableElement) Index(io.requery.Index) ConstraintMode(javax.persistence.ConstraintMode) ForeignKey(io.requery.ForeignKey) GeneratedValue(javax.persistence.GeneratedValue) Lazy(io.requery.Lazy) EnumOrdinalConverter(io.requery.converter.EnumOrdinalConverter) Enumerated(javax.persistence.Enumerated) JoinColumn(javax.persistence.JoinColumn) JoinColumn(javax.persistence.JoinColumn) Column(io.requery.Column) EnumType(javax.persistence.EnumType) Nullable(io.requery.Nullable)

Aggregations

ForeignKey (io.requery.ForeignKey)2 Column (io.requery.Column)1 Index (io.requery.Index)1 Lazy (io.requery.Lazy)1 Nullable (io.requery.Nullable)1 EnumOrdinalConverter (io.requery.converter.EnumOrdinalConverter)1 LinkedHashSet (java.util.LinkedHashSet)1 Map (java.util.Map)1 Optional (java.util.Optional)1 Element (javax.lang.model.element.Element)1 ExecutableElement (javax.lang.model.element.ExecutableElement)1 Types (javax.lang.model.util.Types)1 Basic (javax.persistence.Basic)1 ConstraintMode (javax.persistence.ConstraintMode)1 EnumType (javax.persistence.EnumType)1 Enumerated (javax.persistence.Enumerated)1 GeneratedValue (javax.persistence.GeneratedValue)1 JoinColumn (javax.persistence.JoinColumn)1