PrimaryKeyPropagator.java
package org.codefilarete.stalactite.engine.configurer.dslresolver;
import org.codefilarete.stalactite.dsl.naming.ForeignKeyNamingStrategy;
import org.codefilarete.stalactite.sql.ddl.structure.Column;
import org.codefilarete.stalactite.sql.ddl.structure.ForeignKey;
import org.codefilarete.stalactite.sql.ddl.structure.PrimaryKey;
import org.codefilarete.stalactite.sql.ddl.structure.Table;
/**
* Creates a primary key equivalent to another one and creates a foreign key between them.
*
* @param <SRCTABLE> the type of the source table
* @param <TARGETTABLE> the type of the target table
* @param <I> the type of the primary key identifier
* @author Guillaume Mary
* @see #propagate(PrimaryKey, Table, ForeignKeyNamingStrategy)
*/
public class PrimaryKeyPropagator<SRCTABLE extends Table<SRCTABLE>, TARGETTABLE extends Table<TARGETTABLE>, I> {
/**
* Creates a primary key on the given table by mimicking the given primary key.
* Also creates a foreign key between both.
*
* @param primaryKey the template primary key that must be applied to the target table
* @param target target table on which primary key and foreign key must be added
* @param foreignKeyNamingStrategy the naming strategy to use for the foreign key to create
* @return the created foreign key
*/
public ForeignKey<TARGETTABLE, SRCTABLE, I> propagate(PrimaryKey<SRCTABLE, I> primaryKey,
TARGETTABLE target,
ForeignKeyNamingStrategy foreignKeyNamingStrategy) {
// add primary key and foreign key to all tables
projectPrimaryKey(primaryKey, target);
return addForeignKey(target, primaryKey, foreignKeyNamingStrategy);
}
/**
* Creates foreign keys between given tables primary keys.
*
* @param from target tables on which foreign keys must be added, <strong>order matters</strong>
* @param to initial primary key on which the very first table primary key must point to
* @return the created foreign key
*/
private ForeignKey<TARGETTABLE, SRCTABLE, I> addForeignKey(TARGETTABLE from, PrimaryKey<SRCTABLE, I> to, ForeignKeyNamingStrategy foreignKeyNamingStrategy) {
return addForeignKey(from.getPrimaryKey(), to, foreignKeyNamingStrategy);
}
/**
* Creates the primary key on the given table by creating the equivalent columns with the name and type of the given primary key.
*
* @param source the template primary key that must be applied to the target table
* @param table target table on which the primary key must be added
*/
private void projectPrimaryKey(PrimaryKey<SRCTABLE, I> source, TARGETTABLE table) {
source.getColumns().forEach(pkColumn -> {
// nullability = false may not be necessary because of primary key, let for principle
Column<TARGETTABLE, ?> newColumn = table.addColumn(pkColumn.getName(), pkColumn.getJavaType(), pkColumn.getSize(), false);
newColumn.primaryKey();
});
}
private ForeignKey<TARGETTABLE, SRCTABLE, I> addForeignKey(PrimaryKey<TARGETTABLE, I> from, PrimaryKey<SRCTABLE, I> to, ForeignKeyNamingStrategy foreignKeyNamingStrategy) {
return from.getTable().addForeignKey(foreignKeyNamingStrategy.giveName(from, to), from, to);
}
}