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

com.speedment.runtime.config.util.DocumentDbUtil Maven / Gradle / Ivy

Go to download

A Speedment bundle that shades all dependencies into one jar. This is useful when deploying an application on a server.

There is a newer version: 3.1.18
Show newest version
/**
 *
 * Copyright (c) 2006-2019, Speedment, Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); You may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at:
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.speedment.runtime.config.util;

import com.speedment.runtime.config.Column;
import com.speedment.runtime.config.Dbms;
import com.speedment.runtime.config.Document;
import com.speedment.runtime.config.ForeignKey;
import com.speedment.runtime.config.ForeignKeyColumn;
import com.speedment.runtime.config.Index;
import com.speedment.runtime.config.IndexColumn;
import com.speedment.runtime.config.PrimaryKeyColumn;
import com.speedment.runtime.config.Project;
import com.speedment.runtime.config.Schema;
import com.speedment.runtime.config.Table;
import com.speedment.runtime.config.exception.SpeedmentConfigException;
import com.speedment.runtime.config.identifier.ColumnIdentifier;
import com.speedment.runtime.config.identifier.trait.HasColumnId;
import com.speedment.runtime.config.identifier.trait.HasDbmsId;
import com.speedment.runtime.config.identifier.trait.HasSchemaId;
import com.speedment.runtime.config.identifier.trait.HasTableId;
import com.speedment.runtime.config.trait.HasEnabled;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Stream;

/**
 * Common utility methods specific to the database document model.
 * 
 * @author  Per Minborg
 * @author  Emil Forslund
 * @since   2.3.0
 */
public final class DocumentDbUtil {

    public static Stream traverseOver(Project project) {
        return Stream.concat(project.dbmses(), project.dbmses().flatMap(DocumentDbUtil::traverseOver));
    }

    public static Stream traverseOver(Dbms dbms) {
        return Stream.concat(dbms.schemas(), dbms.schemas().flatMap(DocumentDbUtil::traverseOver));
    }

    public static Stream traverseOver(Schema schema) {
        return Stream.concat(schema.tables(), schema.tables().flatMap(DocumentDbUtil::traverseOver));
    }

    public static Stream traverseOver(Table table) {
        return Stream.of(
                table.columns(), table.columns().flatMap(DocumentDbUtil::traverseOver),
                table.primaryKeyColumns(), table.primaryKeyColumns().flatMap(DocumentDbUtil::traverseOver),
                table.indexes(), table.indexes().flatMap(DocumentDbUtil::traverseOver),
                table.foreignKeys(), table.foreignKeys().flatMap(DocumentDbUtil::traverseOver)
        ).flatMap(Function.identity());
    }

    public static Stream traverseOver(Column column) {
        return Stream.empty();
    }

    public static Stream traverseOver(PrimaryKeyColumn primaryKeyColumn) {
        return Stream.empty();
    }

    public static Stream traverseOver(Index index) {
        return Stream.concat(index.indexColumns(), index.indexColumns().flatMap(DocumentDbUtil::traverseOver));
    }

    public static Stream traverseOver(IndexColumn indexColumn) {
        return Stream.empty();
    }

    public static Stream traverseOver(ForeignKey foreignKey) {
        return Stream.concat(foreignKey.foreignKeyColumns(), foreignKey.foreignKeyColumns().flatMap(DocumentDbUtil::traverseOver));
    }

    public static Stream traverseOver(ForeignKeyColumn foreignKeyColumn) {
        return Stream.empty();
    }

    public static  Stream traverseOver(Project project, Class clazz) {
        if (Dbms.class.isAssignableFrom(clazz)) {
            return project.dbmses().map(clazz::cast);
        } else {
            return project.dbmses().flatMap(dbms -> traverseOver(dbms, clazz));
        }
    }

    public static  Stream traverseOver(Dbms dbms, Class clazz) {
        if (Schema.class.isAssignableFrom(clazz)) {
            return dbms.schemas().map(clazz::cast);
        } else {
            return dbms.schemas().flatMap(schema -> traverseOver(schema, clazz));
        }
    }

    public static  Stream traverseOver(Schema schema, Class clazz) {
        if (Table.class.isAssignableFrom(clazz)) {
            return schema.tables().map(clazz::cast);
        } else {
            return schema.tables().flatMap(table -> traverseOver(table, clazz));
        }
    }

    public static  Stream traverseOver(Table table, Class clazz) {
        if (Column.class.isAssignableFrom(clazz)) {
            return table.columns().map(clazz::cast);
        } else if (PrimaryKeyColumn.class.isAssignableFrom(clazz)) {
            return table.primaryKeyColumns().map(clazz::cast);
        } else if (Index.class.isAssignableFrom(clazz)) {
            return table.indexes().map(clazz::cast);
        } else if (ForeignKey.class.isAssignableFrom(clazz)) {
            return table.foreignKeys().map(clazz::cast);
        } else {
            final Stream.Builder sb = Stream.builder();
            table.columns().flatMap(c -> traverseOver(c, clazz)).forEachOrdered(sb::accept);
            table.primaryKeyColumns().flatMap(c -> traverseOver(c, clazz)).forEachOrdered(sb::accept);
            table.indexes().flatMap(c -> traverseOver(c, clazz)).forEachOrdered(sb::accept);
            table.foreignKeys().flatMap(c -> traverseOver(c, clazz)).forEachOrdered(sb::accept);
            return sb.build();
        }
    }

    public static  Stream traverseOver(Column column, Class clazz) {
        return Stream.empty();
    }

    public static  Stream traverseOver(PrimaryKeyColumn pkColumn, Class clazz) {
        return Stream.empty();
    }

    public static  Stream traverseOver(Index index, Class clazz) {
        if (IndexColumn.class.isAssignableFrom(clazz)) {
            return index.indexColumns().map(clazz::cast);
        } else {
            return index.indexColumns().flatMap(ic -> traverseOver(ic, clazz));
        }
    }

    public static  Stream traverseOver(IndexColumn indexColumn, Class clazz) {
        return Stream.empty();
    }

    public static  Stream traverseOver(ForeignKey fk, Class clazz) {
        if (ForeignKeyColumn.class.isAssignableFrom(clazz)) {
            return fk.foreignKeyColumns().map(clazz::cast);
        } else {
            return fk.foreignKeyColumns().flatMap(fcc -> traverseOver(fcc, clazz));
        }
    }

    public static  Stream traverseOver(ForeignKeyColumn foreignKeyColumn, Class clazz) {
        return Stream.empty();
    }

    public static Stream typedChildrenOf(Table table) {
        return Stream.of(
            table.columns().map(Document.class::cast),
            table.primaryKeyColumns().map(Document.class::cast),
            table.indexes().map(Document.class::cast),
            table.foreignKeys().map(Document.class::cast)
        ).flatMap(Function.identity());
    }
        
    /**
     * Returns {@code true} if the specified {@link Column} represents a column
     * that can only hold unique values in the database.
     * 
     * @param column               the column
     * @return                     {@code true} if unique, else {@code false}
     * @throws SpeedmentConfigException  if an index or PK could not be traversed
     */
    public static boolean isUnique(Column column) throws SpeedmentConfigException {
        final Table table = column.getParentOrThrow();
        
        return
            table.indexes()
                .filter(i -> i.indexColumns().count() == 1)
                .filter(Index::isUnique)
                .filter(Index::isEnabled)
                .flatMap(Index::indexColumns)
                .map(IndexColumn::findColumn)
                .filter(Optional::isPresent)
                .map(Optional::get)
                .anyMatch(col -> isSame(column, col))
            || (
                table.primaryKeyColumns().count() == 1 &&
                table.primaryKeyColumns()
                    .map(PrimaryKeyColumn::findColumn)
                    .filter(Optional::isPresent)
                    .map(Optional::get)
                    .anyMatch(col -> isSame(column, col))
            );
    }
    
    /**
     * Returns {@code true} if the specified document and all its ancestors are 
     * enabled. If at least one ancestor is not enabled, {@code false} is 
     * returned.
     * 
     * @param document  the document to test
     * @return          {@code true} if enabled, else {@code false}
     */
    public static boolean isAllAncestorsEnabled(Document document) {
        return HasEnabled.test(document)
            && document.ancestors()
                .noneMatch(doc -> !HasEnabled.test(doc));
    }
    
    public static Optional referencedColumnIfPresent(Project project, ColumnIdentifier identifier) {
        return referencedColumnIfPresent(project, identifier.getDbmsId(), identifier.getSchemaId(), identifier.getTableId(), identifier.getColumnId());
    }
    
    public static Optional referencedTableIfPresent(Project project, ColumnIdentifier identifier) {
        return referencedTableIfPresent(project, identifier.getDbmsId(), identifier.getSchemaId(), identifier.getTableId());
    }
    
    public static Optional referencedSchemaIfPresent(Project project, ColumnIdentifier identifier) {
        return referencedSchemaIfPresent(project, identifier.getDbmsId(), identifier.getSchemaId());
    }
    
    public static Optional referencedDbmsIfPresent(Project project, ColumnIdentifier identifier) {
        return referencedDbmsIfPresent(project, identifier.getDbmsId());
    }
    
    public static Optional referencedColumnIfPresent(Project project, String dbmsId, String schemaId, String tableId, String columnId) {
        return referencedTableIfPresent(project, dbmsId, schemaId, tableId)
            .flatMap(table -> table.columns().filter(column -> columnId.equals(column.getId()))
                .findAny()
            );
    }
    
    public static Optional referencedTableIfPresent(Project project, String dbmsId, String schemaId, String tableId) {
        return referencedSchemaIfPresent(project, dbmsId, schemaId)
            .flatMap(schema -> schema.tables().filter(table -> tableId.equals(table.getId()))
                .findAny()
            );
    }
    
    public static Optional referencedSchemaIfPresent(Project project, String dbmsId, String schemaId) {
        return referencedDbmsIfPresent(project, dbmsId)
            .flatMap(dbms -> dbms.schemas().filter(schema -> schemaId.equals(schema.getId()))
                .findAny()
            );
    }
    
    public static Optional referencedDbmsIfPresent(Project project, String dbmsId) {
        return project.dbmses().filter(dbms -> dbmsId.equals(dbms.getId())).findAny();
    }
    
    public static  Column referencedColumn(Project project, T identifier) {
        return referencedColumn(project, identifier.getDbmsId(), identifier.getSchemaId(), identifier.getTableId(), identifier.getColumnId());
    }
    
    public static  Table referencedTable(Project project, T identifier) {
        return referencedTable(project, identifier.getDbmsId(), identifier.getSchemaId(), identifier.getTableId());
    }
    
    public static  Schema referencedSchema(Project project, T identifier) {
        return referencedSchema(project, identifier.getDbmsId(), identifier.getSchemaId());
    }
    
    public static Dbms referencedDbms(Project project, HasDbmsId identifier) {
        return referencedDbms(project, identifier.getDbmsId());
    }
    
    public static Column referencedColumn(Project project, String dbmsName, String schemaName, String tableName, String columnName) {
        return referencedColumnIfPresent(project, dbmsName, schemaName, tableName, columnName)
            .orElseThrow(() -> new SpeedmentConfigException(
                "Could not find referenced " + Column.class.getSimpleName() + 
                " with name '" + columnName + "'."
            ));
    }
    
    public static Table referencedTable(Project project, String dbmsId, String schemaId, String tableId) {
        return referencedSchema(project, dbmsId, schemaId)
            .tables().filter(table -> tableId.equals(table.getId()))
            .findAny().orElseThrow(() -> new SpeedmentConfigException(
                "Could not find referenced " + Table.class.getSimpleName() + 
                " with name '" + tableId + "'."
            ));
    }
    
    public static Schema referencedSchema(Project project, String dbmsId, String schemaId) {
        return referencedDbms(project, dbmsId)
            .schemas().filter(schema -> schemaId.equals(schema.getId()))
            .findAny().orElseThrow(() -> new SpeedmentConfigException(
                "Could not find referenced " + Schema.class.getSimpleName() + 
                " with name '" + schemaId + "'."
            ));
    }
    
    public static Dbms referencedDbms(Project project, String dbmsId) {
        return project
            .dbmses().filter(dbms -> dbmsId.equals(dbms.getId()))
            .findAny().orElseThrow(() -> new SpeedmentConfigException(
                "Could not find referenced " + Dbms.class.getSimpleName() + 
                " with name '" + dbmsId + "'."
            ));
    }
    
    /**
     * Returns {@code true} if the two specified documents represents the same
     * element in the database. Two documents are considered same if they have
     * the same name and type and their parents are considered same.
     * 
     * @param first   the first document
     * @param second  the second document
     * @return        {@code true} if same, else {@code false}
     */
    public static boolean isSame(Column first, Column second) {
        if (first.getId().equals(second.getId())) {
            final Table firstParent  = first.getParentOrThrow();
            final Table secondParent = second.getParentOrThrow();
            return isSame(firstParent, secondParent);
        } else {
            return false;
        }
    }
    
    /**
     * Returns {@code true} if the two specified documents represents the same
     * element in the database. Two documents are considered same if they have
     * the same name and type and their parents are considered same.
     * 
     * @param first   the first document
     * @param second  the second document
     * @return        {@code true} if same, else {@code false}
     */
    public static boolean isSame(IndexColumn first, IndexColumn second) {
        if (first.getId().equals(second.getId())) {
            final Index firstParent  = first.getParentOrThrow();
            final Index secondParent = second.getParentOrThrow();
            return isSame(firstParent, secondParent);
        } else {
            return false;
        }
    }
    
    /**
     * Returns {@code true} if the two specified documents represents the same
     * element in the database. Two documents are considered same if they have
     * the same name and type and their parents are considered same.
     * 
     * @param first   the first document
     * @param second  the second document
     * @return        {@code true} if same, else {@code false}
     */
    public static boolean isSame(Index first, Index second) {
        if (first.getId().equals(second.getId())) {
            final Table firstParent  = first.getParentOrThrow();
            final Table secondParent = second.getParentOrThrow();
            return isSame(firstParent, secondParent);
        } else {
            return false;
        }
    }
    
    /**
     * Returns {@code true} if the two specified documents represents the same
     * element in the database. Two documents are considered same if they have
     * the same name and type and their parents are considered same.
     * 
     * @param first   the first document
     * @param second  the second document
     * @return        {@code true} if same, else {@code false}
     */
    public static boolean isSame(PrimaryKeyColumn first, PrimaryKeyColumn second) {
        if (first.getId().equals(second.getId())) {
            final Table firstParent  = first.getParentOrThrow();
            final Table secondParent = second.getParentOrThrow();
            return isSame(firstParent, secondParent);
        } else {
            return false;
        }
    }
    
    /**
     * Returns {@code true} if the two specified documents represents the same
     * element in the database. Two documents are considered same if they have
     * the same name and type and their parents are considered same.
     * 
     * @param first   the first document
     * @param second  the second document
     * @return        {@code true} if same, else {@code false}
     */
    public static boolean isSame(ForeignKeyColumn first, ForeignKeyColumn second) {
        if (first.getId().equals(second.getId())) {
            final ForeignKey firstParent  = first.getParentOrThrow();
            final ForeignKey secondParent = second.getParentOrThrow();
            return isSame(firstParent, secondParent);
        } else {
            return false;
        }
    }
    
    /**
     * Returns {@code true} if the two specified documents represents the same
     * element in the database. Two documents are considered same if they have
     * the same name and type and their parents are considered same.
     * 
     * @param first   the first document
     * @param second  the second document
     * @return        {@code true} if same, else {@code false}
     */
    public static boolean isSame(ForeignKey first, ForeignKey second) {
        if (first.getId().equals(second.getId())) {
            final Table firstParent  = first.getParentOrThrow();
            final Table secondParent = second.getParentOrThrow();
            return isSame(firstParent, secondParent);
        } else {
            return false;
        }
    }
    
    /**
     * Returns {@code true} if the two specified documents represents the same
     * element in the database. Two documents are considered same if they have
     * the same name and type and their parents are considered same.
     * 
     * @param first   the first document
     * @param second  the second document
     * @return        {@code true} if same, else {@code false}
     */
    public static boolean isSame(Table first, Table second) {
        if (first.getId().equals(second.getId())) {
            final Schema firstParent  = first.getParentOrThrow();
            final Schema secondParent = second.getParentOrThrow();
            return isSame(firstParent, secondParent);
        } else {
            return false;
        }
    }
    
    /**
     * Returns {@code true} if the two specified documents represents the same
     * element in the database. Two documents are considered same if they have
     * the same name and type and their parents are considered same.
     * 
     * @param first   the first document
     * @param second  the second document
     * @return        {@code true} if same, else {@code false}
     */
    public static boolean isSame(Schema first, Schema second) {
        if (first.getId().equals(second.getId())) {
            final Dbms firstParent  = first.getParentOrThrow();
            final Dbms secondParent = second.getParentOrThrow();
            return isSame(firstParent, secondParent);
        } else {
            return false;
        }
    }
    
    /**
     * Returns {@code true} if the two specified documents represents the same
     * element in the database. Two documents are considered same if they have
     * the same name and type and their parents are considered same.
     * 
     * @param first   the first document
     * @param second  the second document
     * @return        {@code true} if same, else {@code false}
     */
    public static boolean isSame(Dbms first, Dbms second) {
        if (first.getId().equals(second.getId())) {
            final Project firstParent  = first.getParentOrThrow();
            final Project secondParent = second.getParentOrThrow();
            return isSame(firstParent, secondParent);
        } else {
            return false;
        }
    }
    
    /**
     * Returns {@code true} if the two specified documents represents the same
     * element in the database. Two documents are considered same if they have
     * the same name and type and their parents are considered same.
     * 
     * @param first   the first document
     * @param second  the second document
     * @return        {@code true} if same, else {@code false}
     */
    public static boolean isSame(Project first, Project second) {
        return first.getId().equals(second.getId());
    }

    /**
     * Utility classes should not be instantiated.
     */
    private DocumentDbUtil() {
        throw new UnsupportedOperationException();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy