tech.ydb.yoj.repository.db.EntitySchema Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of yoj-repository Show documentation
Show all versions of yoj-repository Show documentation
Core YOJ (YDB ORM for Java) abstractions and APIs for domain entities, repositories, transactions etc.
The newest version!
package tech.ydb.yoj.repository.db;
import com.google.common.reflect.TypeToken;
import lombok.Getter;
import tech.ydb.yoj.databind.schema.Schema;
import tech.ydb.yoj.databind.schema.configuration.SchemaRegistry;
import tech.ydb.yoj.databind.schema.configuration.SchemaRegistry.SchemaKey;
import tech.ydb.yoj.databind.schema.naming.NamingStrategy;
import tech.ydb.yoj.databind.schema.reflect.ReflectField;
import tech.ydb.yoj.databind.schema.reflect.Reflector;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
import static java.lang.String.format;
import static lombok.AccessLevel.PACKAGE;
public final class EntitySchema> extends Schema {
private static final Type ENTITY_TYPE_PARAMETER = Entity.class.getTypeParameters()[0];
@Getter(PACKAGE)
private final SchemaRegistry registry;
public static > EntitySchema of(Class type) {
return of(type, null);
}
public static > EntitySchema of(Class type, NamingStrategy namingStrategy) {
return of(SchemaRegistry.getDefault(), type, namingStrategy);
}
public static > EntitySchema of(SchemaRegistry registry, Class type) {
return of(registry, type, null);
}
/**
* @param namingStrategy naming strategy with mandatory equals/hashCode.
*/
public static > EntitySchema of(SchemaRegistry registry, Class type, NamingStrategy namingStrategy) {
return of(registry, SchemaKey.of(type, namingStrategy));
}
public static > EntitySchema of(SchemaRegistry registry, SchemaKey key) {
return registry.getOrCreate(EntitySchema.class, (k, r) -> new EntitySchema<>(k, r, registry), key);
}
private EntitySchema(SchemaKey key, Reflector reflector, SchemaRegistry registry) {
super(checkEntityType(key), reflector);
this.registry = registry;
}
private static > SchemaKey checkEntityType(SchemaKey key) {
Class entityType = key.clazz();
if (!Entity.class.isAssignableFrom(entityType)) {
throw new IllegalArgumentException(format(
"Entity type [%s] must implement [%s]", entityType.getName(), Entity.class));
}
Class> entityTypeFromEntityIface = resolveEntityTypeFromEntityIface(entityType);
if (!entityTypeFromEntityIface.equals(entityType)) {
throw new IllegalArgumentException(format(
"Entity type [%s] must implement [%s] specified by the same type, but it is specified by [%s]",
entityType.getName(), Entity.class, entityTypeFromEntityIface.getName()));
}
Class> idFieldType;
try {
idFieldType = entityType.getDeclaredField(EntityIdSchema.ID_FIELD_NAME).getType();
} catch (NoSuchFieldException e) {
throw new IllegalArgumentException(format(
"Entity type [%s] does not contain a mandatory \"%s\" field",
entityType.getName(), EntityIdSchema.ID_FIELD_NAME));
}
if (!Entity.Id.class.isAssignableFrom(idFieldType)) {
throw new IllegalArgumentException(format(
"Entity ID type [%s] must implement [%s]", idFieldType.getName(), Entity.Id.class));
}
Class> entityTypeFromIdType = EntityIdSchema.resolveEntityType(idFieldType);
if (!entityTypeFromIdType.equals(entityType)) {
throw new IllegalArgumentException(format(
"An identifier field \"%s\" has a type [%s] that is not an identifier type for an entity of type [%s]",
EntityIdSchema.ID_FIELD_NAME, idFieldType.getName(), entityType.getName()));
}
return key;
}
static Class> resolveEntityTypeFromEntityIface(Class> entityType) {
return TypeToken.of(entityType).resolveType(ENTITY_TYPE_PARAMETER).getRawType();
}
@Override
protected boolean isFlattenable(ReflectField field) {
return Entity.Id.class.isAssignableFrom(field.getType());
}
public > EntityIdSchema getIdSchema() {
return EntityIdSchema.from(this);
}
public List flattenId() {
return getIdSchema().flattenFields();
}
public Map flattenId(Entity.Id idValue) {
return getIdSchema().flatten(idValue);
}
}