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;
}
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();
}
});
}
Aggregations