com.infomaximum.database.schema.StructEntity Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of rdao Show documentation
Show all versions of rdao Show documentation
Library for creating a light cluster
The newest version!
package com.infomaximum.database.schema;
import com.infomaximum.database.anotation.*;
import com.infomaximum.database.domainobject.DomainObject;
import com.infomaximum.database.exception.FieldNotFoundException;
import com.infomaximum.database.exception.IndexNotFoundException;
import com.infomaximum.database.exception.StructEntityException;
import com.infomaximum.database.utils.ByteUtils;
import com.infomaximum.database.utils.TypeConvert;
import java.util.*;
import java.util.stream.Collectors;
public class StructEntity {
public static class Reference {
public final Class extends DomainObject> objClass;
public final com.infomaximum.database.schema.HashIndex fieldIndex;
private Reference(Class extends DomainObject> objClass, com.infomaximum.database.schema.HashIndex fieldIndex) {
this.objClass = objClass;
this.fieldIndex = fieldIndex;
}
}
public final static String NAMESPACE_SEPARATOR = ".";
private final Class extends DomainObject> clazz;
private final String name;
private final String columnFamily;
private final String indexColumnFamily;
private final String namespace;
private final com.infomaximum.database.schema.Field[] fields;
private final Map nameBytesFields;
private final List hashIndexes;
private final List prefixIndexes;
private final List intervalIndexes;
private final List rangeIndexes;
private final List referencingForeignFields = new ArrayList<>();
public StructEntity(Class extends DomainObject> clazz) {
final Entity annotationEntity = getAnnotationClass(clazz).getAnnotation(Entity.class);
this.clazz = clazz;
this.name = annotationEntity.name();
this.columnFamily = buildColumnFamily(annotationEntity);
this.indexColumnFamily = buildIndexColumnFamily(this.columnFamily);
this.namespace = annotationEntity.namespace();
Map modifiableNameToFields = new HashMap<>(annotationEntity.fields().length);
this.fields = new com.infomaximum.database.schema.Field[annotationEntity.fields().length];
for(com.infomaximum.database.anotation.Field field: annotationEntity.fields()) {
//Проверяем на уникальность
if (modifiableNameToFields.containsKey(field.name())) {
throw new StructEntityException("Field name=" + field.name() + " already exists into " + clazz.getName() + ".");
}
if (fields[field.number()] != null) {
throw new StructEntityException("Field number=" + field.number() + " already exists into " + clazz.getName() + ".");
}
com.infomaximum.database.schema.Field f = new com.infomaximum.database.schema.Field(field, this);
fields[field.number()] = f;
modifiableNameToFields.put(f.getName(), f);
if (f.isForeign()) {
registerToForeignEntity(f);
}
}
this.nameBytesFields = new HashMap<>(fields.length);
Arrays.stream(fields).forEach(field -> nameBytesFields.put(new ByteArray(field.getNameBytes()), field));
this.hashIndexes = buildHashIndexes(annotationEntity);
this.prefixIndexes = buildPrefixIndexes(annotationEntity);
this.intervalIndexes = buildIntervalIndexes(annotationEntity);
this.rangeIndexes = buildRangeIndexes(annotationEntity);
}
private void registerToForeignEntity(com.infomaximum.database.schema.Field foreignField) {
foreignField.getForeignDependency().referencingForeignFields.add(new Reference(clazz, buildForeignIndex(foreignField)));
}
public String getName() {
return name;
}
public String getColumnFamily() {
return columnFamily;
}
public String getNamespace() {
return namespace;
}
public String getIndexColumnFamily() {
return indexColumnFamily;
}
public Class extends DomainObject> getObjectClass() {
return clazz;
}
public com.infomaximum.database.schema.Field getField(ByteArray name) {
com.infomaximum.database.schema.Field field = nameBytesFields.get(name);
if (field == null) {
throw new FieldNotFoundException(clazz, name.convertToString());
}
return field;
}
public com.infomaximum.database.schema.Field getField(int number) {
if (number >= fields.length) {
throw new FieldNotFoundException(clazz, "number=" + number);
}
return fields[number];
}
public com.infomaximum.database.schema.Field[] getFields() {
return fields;
}
public Set getFieldNames(Collection fieldNumbers) {
if (fieldNumbers == null) {
return null;
}
return fieldNumbers.stream()
.map(i -> getField(i).getName())
.collect(Collectors.toSet());
}
public com.infomaximum.database.schema.HashIndex getHashIndex(Collection indexedFields) {
for (com.infomaximum.database.schema.HashIndex index : hashIndexes) {
if (index.sortedFields.size() != indexedFields.size()) {
continue;
}
if (index.sortedFields.stream().allMatch(f -> indexedFields.contains(f.getNumber()))) {
return index;
}
}
throw new IndexNotFoundException(com.infomaximum.database.schema.HashIndex.toString(getFieldNames(indexedFields)), clazz);
}
public com.infomaximum.database.schema.PrefixIndex getPrefixIndex(Collection indexedFields) {
for (com.infomaximum.database.schema.PrefixIndex index : prefixIndexes) {
if (index.sortedFields.size() != indexedFields.size()) {
continue;
}
if (index.sortedFields.stream().allMatch(f -> indexedFields.contains(f.getNumber()))) {
return index;
}
}
throw new IndexNotFoundException(com.infomaximum.database.schema.PrefixIndex.toString(getFieldNames(indexedFields)), clazz);
}
public com.infomaximum.database.schema.IntervalIndex getIntervalIndex(Collection hashedFields, Integer indexedField) {
for (com.infomaximum.database.schema.IntervalIndex index : intervalIndexes) {
if (index.sortedFields.size() != (hashedFields.size() + 1)) {
continue;
}
if (index.getIndexedField().getNumber() != indexedField) {
continue;
}
if (index.getHashedFields().stream().allMatch(f -> hashedFields.contains(f.getNumber()))) {
return index;
}
}
throw new IndexNotFoundException(com.infomaximum.database.schema.IntervalIndex.toString(getFieldNames(hashedFields), getField(indexedField).getName()), clazz);
}
public com.infomaximum.database.schema.RangeIndex getRangeIndex(Collection hashedFields, int beginField, int endField) {
for (com.infomaximum.database.schema.RangeIndex index : rangeIndexes) {
if (index.sortedFields.size() != (hashedFields.size() + 2)) {
continue;
}
if (index.getBeginIndexedField().getNumber() != beginField || index.getEndIndexedField().getNumber() != endField) {
continue;
}
if (index.getHashedFields().stream().allMatch(f -> hashedFields.contains(f.getNumber()))) {
return index;
}
}
throw new IndexNotFoundException(com.infomaximum.database.schema.RangeIndex.toString(getFieldNames(hashedFields), getField(beginField).getName(), getField(endField).getName()), clazz);
}
public List getHashIndexes() {
return hashIndexes;
}
public List getPrefixIndexes() {
return prefixIndexes;
}
public List getIntervalIndexes() {
return intervalIndexes;
}
public List getRangeIndexes() {
return rangeIndexes;
}
public List getReferencingForeignFields() {
return referencingForeignFields;
}
public static Class extends DomainObject> getAnnotationClass(Class extends DomainObject> clazz) {
while (!clazz.isAnnotationPresent(Entity.class)) {
if (!DomainObject.class.isAssignableFrom(clazz.getSuperclass())) {
throw new StructEntityException("Not found " + Entity.class + " annotation in " + clazz + ".");
}
clazz = (Class extends DomainObject>) clazz.getSuperclass();
}
return clazz;
}
private static String buildColumnFamily(Entity entity) {
return entity.namespace() + NAMESPACE_SEPARATOR + entity.name();
}
private static String buildIndexColumnFamily(String parentColumnFamily) {
return parentColumnFamily + NAMESPACE_SEPARATOR + "index";
}
private List buildHashIndexes(Entity entity) {
List result = new ArrayList<>(entity.hashIndexes().length);
Set singleFieldHashes = new HashSet<>();
for (com.infomaximum.database.schema.Field field : fields) {
if (!field.isForeign()) {
continue;
}
result.add(buildForeignIndex(field));
singleFieldHashes.add(field.getNumber());
}
for (com.infomaximum.database.anotation.HashIndex index: entity.hashIndexes()) {
if (index.fields().length != 1 || !singleFieldHashes.contains(index.fields()[0])) {
result.add(new com.infomaximum.database.schema.HashIndex(index, this));
}
}
checkExclusiveAttendants(result);
return Collections.unmodifiableList(result);
}
private com.infomaximum.database.schema.HashIndex buildForeignIndex(com.infomaximum.database.schema.Field foreignField) {
return new com.infomaximum.database.schema.HashIndex(foreignField, this);
}
private List buildPrefixIndexes(Entity entity) {
if (entity.prefixIndexes().length == 0) {
return Collections.emptyList();
}
List result = new ArrayList<>(entity.prefixIndexes().length);
for (com.infomaximum.database.anotation.PrefixIndex index: entity.prefixIndexes()) {
result.add(new com.infomaximum.database.schema.PrefixIndex(index, this));
}
checkExclusiveAttendants(result);
return Collections.unmodifiableList(result);
}
private List buildIntervalIndexes(Entity entity) {
if (entity.intervalIndexes().length == 0) {
return Collections.emptyList();
}
List result = new ArrayList<>(entity.intervalIndexes().length);
for (com.infomaximum.database.anotation.IntervalIndex index: entity.intervalIndexes()) {
result.add(new com.infomaximum.database.schema.IntervalIndex(index, this));
}
checkExclusiveAttendants(result);
return Collections.unmodifiableList(result);
}
private List buildRangeIndexes(Entity entity) {
if (entity.rangeIndexes().length == 0) {
return Collections.emptyList();
}
List result = new ArrayList<>(entity.rangeIndexes().length);
for (com.infomaximum.database.anotation.RangeIndex index: entity.rangeIndexes()) {
result.add(new com.infomaximum.database.schema.RangeIndex(index, this));
}
checkExclusiveAttendants(result);
return Collections.unmodifiableList(result);
}
private static void checkExclusiveAttendants(List indexes) {
for (int i = 0; i < indexes.size(); i++) {
T index = indexes.get(i);
for (int j = i + 1; j < indexes.size(); j++) {
if (Arrays.equals(index.attendant, indexes.get(j).attendant)) {
throw new StructEntityException("Attendant of " + index.getClass().getSimpleName() + " not unique");
}
}
}
}
public static class ByteArray {
private final byte[] array;
private final int from, to;
private final int hashCode;
public ByteArray(byte[] array) {
this(array, 0, array.length);
}
public ByteArray(byte[] array, int from, int to) {
this.array = array;
this.from = from;
this.to = to;
this.hashCode = hashCode(array, from, to);
}
private String convertToString() {
return TypeConvert.unpackString(array, from, to - from);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof ByteArray)) return false;
ByteArray byteArray = (ByteArray) o;
return ByteUtils.equals(array, from, to, byteArray.array, byteArray.from, byteArray.to);
}
@Override
public int hashCode() {
return hashCode;
}
private static int hashCode(byte[] array, int from, int to) {
int result = 1;
for (int i = from; i < to; ++i) {
result = 31 * result + array[i];
}
return result;
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy