package com.goodworkalan.addendum;
import static com.goodworkalan.addendum.Addendum.COLUMN_EXISTS;
import static com.goodworkalan.addendum.Addendum.PRIMARY_KEY_COLUMN_MISSING;
import static com.goodworkalan.addendum.Addendum.PRIMARY_KEY_EXISTS;
import static com.goodworkalan.addendum.Addendum.PROPERTY_EXISTS;
import com.goodworkalan.addendum.dialect.Column;
import com.goodworkalan.danger.Danger;
/**
* Builds an entity definition specifying the entity primary key and entity
* properties.
* <p>
* This class is used in the context of a domain-specific language that is
* implemented as chained Java method calls. Refer to the package documentation
* for documentation of the language and examples of use.
*
* @author Alan Gutierrez
*/
public class DefineEntity {
/** The root individual migration builder. */
private final Addendum addendum;
/** The entity definition. */
protected final Entity entity;
/**
* Create a table builder with the given root language element.
*
* @param addendum
* The root individual migration builder.
* @param entity
* The entity definition.
*/
DefineEntity(Addendum addendum, Entity entity) {
this.addendum = addendum;
this.entity = entity;
}
/**
* Define a new column in the table with the given name and given column
* type stored in the given column name in the database.
*
* @param name
* The column name.
* @param columnName
* The name of the column in the database.
* @param columnType
* The SQL column type.
* @return A new property builder.
*/
public CreateProperty add(String name, String columnName, int columnType) {
if (entity.properties.containsKey(name)) {
throw new Danger(Addendum.class, PROPERTY_EXISTS, name);
}
if (entity.columns.containsKey(columnName)) {
throw new Danger(Addendum.class, COLUMN_EXISTS, columnName);
}
entity.properties.put(name, columnName);
Column column = new Column(columnName, columnType);
entity.columns.put(columnName, column);
return new CreateProperty(this, column);
}
/**
* Define a new column in the table with the given name and given column
* type.
*
* @param name
* The property name.
* @param columnType
* The SQL column type.
* @return A new property builder.
*/
public CreateProperty add(String name, int columnType) {
return add(name, name, columnType);
}
/**
* Define a new property in the entity with the given name and a
* <code>java.sql.Types</code> column type appropriate for the given Java
* native type stored in the given column name in the database.
*
* @param name
* The property name.
* @param columnName
* The name of the column in the database.
* @param nativeType
* The native column type.
* @return A column builder.
*/
public CreateProperty add(String name, String columnName, Class<?> nativeType) {
return add(name, columnName, Column.getColumnType(nativeType));
}
/**
* Define a new property in the entity with the given name and a
* <code>java.sql.Types</code> column type appropriate for the given Java
* native type.
*
* @param name
* The property name.
* @param nativeType
* The native column type.
* @return A column builder.
*/
public CreateProperty add(String name, Class<?> nativeType) {
return add(name, name, nativeType);
}
/**
* Define the primary key of the table using column names.
*
* @param columns
* The primary key column names.
* @return This builder to continue building.
*/
public DefineEntity primaryKey(String... columns) {
if (!entity.primaryKey.isEmpty()) {
throw new Danger(Addendum.class, PRIMARY_KEY_EXISTS);
}
for (String column : columns) {
if (!entity.columns.containsKey(column)) {
throw new Danger(Addendum.class, PRIMARY_KEY_COLUMN_MISSING, entity.tableName, column);
}
entity.primaryKey.add(column);
}
return this;
}
/**
* Called when the {@link #end() end} method is called to perform any
* actions based on this entity definition.
*/
protected void ending() {
}
/**
* Terminate the entity definition and the parent addendum builder.
*
* @return The addendum builder.
*/
public Addendum end() {
ending();
return addendum;
}
}