PrimaryKeyPropagationStep.java
package org.codefilarete.stalactite.engine.configurer.builder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import org.codefilarete.stalactite.dsl.naming.ForeignKeyNamingStrategy;
import org.codefilarete.stalactite.engine.configurer.builder.InheritanceMappingStep.MappingPerTable;
import org.codefilarete.stalactite.sql.ddl.structure.Column;
import org.codefilarete.stalactite.sql.ddl.structure.PrimaryKey;
import org.codefilarete.stalactite.sql.ddl.structure.Table;
import org.codefilarete.tool.VisibleForTesting;
import org.codefilarete.tool.collection.KeepOrderSet;
import org.codefilarete.tool.function.Hanger.Holder;
public class PrimaryKeyPropagationStep<C, I> {
<T extends Table<T>> void propagate(PrimaryKey<T, I> primaryKey,
MappingPerTable<C> inheritanceMappingPerTable,
ForeignKeyNamingStrategy foreignKeyNamingStrategy) {
Set<Table> inheritanceTables = inheritanceMappingPerTable.giveTables();
inheritanceTables.remove(primaryKey.getTable());
// add primary key and foreign key to all tables
propagatePrimaryKey(primaryKey, inheritanceTables);
List<Table> tables = new ArrayList<>(inheritanceTables);
Collections.reverse(tables);
applyForeignKeys(primaryKey, new KeepOrderSet<>(tables), foreignKeyNamingStrategy);
}
/**
* Creates foreign keys between given tables primary keys.
*
* @param primaryKey initial primary key on which the very first table primary key must point to
* @param tables target tables on which foreign keys must be added, <strong>order matters</strong>
*/
@VisibleForTesting
void applyForeignKeys(PrimaryKey primaryKey, Set<Table> tables, ForeignKeyNamingStrategy foreignKeyNamingStrategy) {
applyForeignKeys(primaryKey, foreignKeyNamingStrategy, tables);
}
/**
* Creates primary keys on given tables with name and type of given primary key.
*
* @param tables target tables on which primary keys must be added
* @param primaryKey
*/
public static void propagatePrimaryKey(PrimaryKey<?, ?> primaryKey, Set<Table> tables) {
Holder<PrimaryKey<?, ?>> previousPk = new Holder<>(primaryKey);
tables.forEach(t -> {
previousPk.get().getColumns().forEach(pkColumn -> {
// nullability = false may not be necessary because of primary key, let for principle
Column newColumn = t.addColumn(pkColumn.getName(), pkColumn.getJavaType(), pkColumn.getSize(), false);
newColumn.primaryKey();
});
previousPk.set(t.getPrimaryKey());
});
}
public static void applyForeignKeys(PrimaryKey primaryKey, ForeignKeyNamingStrategy foreignKeyNamingStrategy, Set<Table> tables) {
Holder<PrimaryKey> previousPk = new Holder<>(primaryKey);
tables.forEach(t -> {
PrimaryKey currentPrimaryKey = t.getPrimaryKey();
t.addForeignKey(foreignKeyNamingStrategy.giveName(currentPrimaryKey, previousPk.get()), currentPrimaryKey, previousPk.get());
previousPk.set(currentPrimaryKey);
});
}
}