PrimaryKeyResolver.java
package org.codefilarete.stalactite.engine.configurer.dslresolver;
import java.util.Map;
import org.codefilarete.reflection.AccessorDefinition;
import org.codefilarete.reflection.ReadWritePropertyAccessPoint;
import org.codefilarete.stalactite.dsl.entity.EntityMappingConfiguration.CompositeKeyMapping;
import org.codefilarete.stalactite.dsl.entity.EntityMappingConfiguration.KeyMapping;
import org.codefilarete.stalactite.dsl.entity.EntityMappingConfiguration.SingleKeyMapping;
import org.codefilarete.stalactite.dsl.idpolicy.GeneratedKeysPolicy;
import org.codefilarete.stalactite.dsl.key.CompositeKeyMappingConfiguration;
import org.codefilarete.stalactite.dsl.naming.ColumnNamingStrategy;
import org.codefilarete.stalactite.dsl.naming.UniqueConstraintNamingStrategy;
import org.codefilarete.stalactite.engine.configurer.builder.embeddable.EmbeddableMapping;
import org.codefilarete.stalactite.engine.configurer.builder.embeddable.EmbeddableMappingBuilder;
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.stalactite.sql.statement.binder.ColumnBinderRegistry;
import org.codefilarete.tool.VisibleForTesting;
import static org.codefilarete.tool.Nullable.nullable;
public class PrimaryKeyResolver<C, I> {
/**
* Creates a primary key on a table that owns the identification
*
* @param keyLinkage information that allow to create primary key
* @return the created {@link PrimaryKey}
*/
@VisibleForTesting
public <T extends Table<T>> PrimaryKey<T, I> addIdentifyingPrimarykey(KeyMapping<C, I> keyLinkage,
T pkTable,
ColumnBinderRegistry columnBinderRegistry,
ColumnNamingStrategy columnNamingStrategy,
UniqueConstraintNamingStrategy uniqueConstraintNamingStrategy) {
AccessorDefinition identifierDefinition = AccessorDefinition.giveDefinition(keyLinkage.getAccessor());
if (keyLinkage instanceof CompositeKeyMapping) {
CompositeKeyMappingConfiguration<I> configuration = ((CompositeKeyMapping<C, I>) keyLinkage).getCompositeKeyMappingBuilder().getConfiguration();
// Note that we won't care about readonly column returned by build(..) since we're on a primary key case, then
// some readonly columns would be nonsense
EmbeddableMappingBuilder<I, T> compositeKeyBuilder = new EmbeddableMappingBuilder<>(configuration, pkTable, columnBinderRegistry, columnNamingStrategy, uniqueConstraintNamingStrategy);
EmbeddableMapping<I, T> build = compositeKeyBuilder.build();
Map<ReadWritePropertyAccessPoint<I, Object>, Column<T, Object>> compositeKeyMapping = build.getMapping();
compositeKeyMapping.values().forEach(Column::primaryKey);
} else {
SingleKeyMapping<C, I> singleKeyLinkage = (SingleKeyMapping<C, I>) keyLinkage;
String columnName = determineColumnName(singleKeyLinkage, columnNamingStrategy);
// nullability = false may not be necessary because of primary key, let for principle
Column<?, I> primaryKey = pkTable.addColumn(columnName, identifierDefinition.getMemberType(), singleKeyLinkage.getColumnOptions().getColumnSize(), false);
primaryKey.primaryKey();
if (singleKeyLinkage.getIdentifierPolicy() instanceof GeneratedKeysPolicy) {
primaryKey.autoGenerated();
}
}
return pkTable.getPrimaryKey();
}
private <O> String determineColumnName(SingleKeyMapping<C, O> keyLinkage, ColumnNamingStrategy columnNamingStrategy) {
return nullable(keyLinkage.getColumnOptions().getColumnName())
.elseSet(keyLinkage::getFieldName)
.elseSet(() -> columnNamingStrategy.giveName(AccessorDefinition.giveDefinition(keyLinkage.getAccessor())))
.get();
}
}