All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.infomaximum.database.maintenance.DomainService Maven / Gradle / Ivy

The newest version!
package com.infomaximum.database.maintenance;

import com.google.common.collect.Range;
import com.google.common.collect.RangeSet;
import com.google.common.collect.TreeRangeSet;
import com.infomaximum.database.domainobject.DomainObject;
import com.infomaximum.database.domainobject.DomainObjectSource;
import com.infomaximum.database.domainobject.filter.EmptyFilter;
import com.infomaximum.database.domainobject.iterator.IteratorEntity;
import com.infomaximum.database.exception.DatabaseException;
import com.infomaximum.database.exception.ForeignDependencyException;
import com.infomaximum.database.exception.InconsistentDatabaseException;
import com.infomaximum.database.provider.DBIterator;
import com.infomaximum.database.provider.DBProvider;
import com.infomaximum.database.schema.Field;
import com.infomaximum.database.schema.Schema;
import com.infomaximum.database.schema.StructEntity;
import com.infomaximum.database.utils.key.FieldKey;

import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

public class DomainService {

    private final DBProvider dbProvider;

    private ChangeMode changeMode = ChangeMode.NONE;
    private boolean isValidationMode = false;

    private StructEntity domain;
    private final Schema dbSchema;
    private boolean existsData = false;

    public DomainService(DBProvider dbProvider, Schema dbSchema) {
        this.dbProvider = dbProvider;
        this.dbSchema = dbSchema;
    }

    public DomainService setChangeMode(ChangeMode value) {
        this.changeMode = value;
        return this;
    }

    public DomainService setValidationMode(boolean value) {
        this.isValidationMode = value;
        return this;
    }

    public DomainService setDomain(StructEntity value) {
        this.domain = value;
        return this;
    }

    public void execute() throws DatabaseException {
        final String dataColumnFamily = domain.getColumnFamily();

        existsData = isExistsColumnFamily(dataColumnFamily);

        if (changeMode == ChangeMode.REMOVAL) {
//            remove();
        }

        validate();
    }

    static void removeDomainColumnFamiliesFrom(Set columnFamilies, final StructEntity domain) {
        columnFamilies.remove(domain.getColumnFamily());
        columnFamilies.remove(domain.getIndexColumnFamily());
    }

    //todo add it to remove module
    private void remove() throws DatabaseException {
        dbSchema.dropTable(domain.getName(), domain.getNamespace());
        for (String columnFamily : getColumnFamilies()) {
            dbProvider.dropColumnFamily(columnFamily);
        }
    }

    private void validate() throws DatabaseException {
        if (!isValidationMode) {
            return;
        }

        validateUnknownColumnFamilies();

        if (changeMode != ChangeMode.REMOVAL) {
            validateIntegrity();
        }
    }

    private Set getColumnFamilies() throws DatabaseException {
        final String namespacePrefix = domain.getColumnFamily() + StructEntity.NAMESPACE_SEPARATOR;
        Set result = Arrays.stream(dbProvider.getColumnFamilies())
                .filter(s -> s.startsWith(namespacePrefix))
                .collect(Collectors.toSet());
        result.add(domain.getColumnFamily());
        return result;
    }

    private void validateUnknownColumnFamilies() throws DatabaseException {
        Set columnFamilies = getColumnFamilies();
        removeDomainColumnFamiliesFrom(columnFamilies, domain);
        if (!columnFamilies.isEmpty()) {
            throw new InconsistentDatabaseException(domain.getObjectClass() + " contains unknown column families " + String.join(", ", columnFamilies) + ".");
        }
    }

    private boolean isExistsColumnFamily(String columnFamily) throws DatabaseException {
        if (dbProvider.containsColumnFamily(columnFamily)) {
            return existsKeys(columnFamily);
        }
//
//        if (changeMode == ChangeMode.CREATION) {
//            dbProvider.createColumnFamily(columnFamily);
//        } else if (isValidationMode) {
//            throw new InconsistentDatabaseException("Column family " + columnFamily + " not found.");
//        }
        return false;
    }

    private boolean existsKeys(String columnFamily) throws DatabaseException {
        try (DBIterator i = dbProvider.createIterator(columnFamily)) {
            return i.seek(null) != null;
        }
    }

    private void validateIntegrity() throws DatabaseException {
        if (!existsData) {
            return;
        }

        List foreignFields = Arrays.stream(domain.getFields())
                .filter(Field::isForeign)
                .collect(Collectors.toList());

        if (foreignFields.isEmpty()) {
            return;
        }

        Set fieldNames = foreignFields
                .stream()
                .map(Field::getNumber)
                .collect(Collectors.toSet());

        FieldKey fieldKey = new FieldKey(0);

        RangeSet[] processedIds = new RangeSet[domain.getFields().length];
        for (Field field : foreignFields) {
            processedIds[field.getNumber()] = TreeRangeSet.create();
        }

        DomainObjectSource domainObjectSource = new DomainObjectSource(dbProvider, true);
        try (IteratorEntity iter = domainObjectSource.find(domain.getObjectClass(), EmptyFilter.INSTANCE, fieldNames)) {
            while (iter.hasNext()) {
                DomainObject obj = iter.next();

                for (Field field : foreignFields) {
                    Long value = obj.get(field.getNumber());
                    if (value == null) {
                        continue;
                    }

                    RangeSet processedId = processedIds[field.getNumber()];
                    if (processedId.contains(value)) {
                        continue;
                    }

                    fieldKey.setId(value);
                    if (dbProvider.getValue(field.getForeignDependency().getColumnFamily(), fieldKey.pack()) == null) {
                        throw new ForeignDependencyException(obj.getId(), domain.getObjectClass(), field, value);
                    }
                    processedId.add(Range.closedOpen(value, value + 1));
                }
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy