com.speedment.runtime.config.util.DocumentDbUtil Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of runtime-deploy Show documentation
Show all versions of runtime-deploy Show documentation
A Speedment bundle that shades all dependencies into one jar. This is
useful when deploying an application on a server.
/**
*
* 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();
}
}