package liquibase.ext.spatial.change;
import java.util.ArrayList;
import java.util.List;
import liquibase.change.AbstractChange;
import liquibase.change.Change;
import liquibase.change.ChangeMetaData;
import liquibase.change.ChangeWithColumns;
import liquibase.change.ColumnConfig;
import liquibase.change.DatabaseChange;
import liquibase.change.DatabaseChangeProperty;
import liquibase.database.Database;
import liquibase.exception.ValidationErrors;
import liquibase.ext.spatial.statement.CreateSpatialIndexStatement;
import liquibase.ext.spatial.xml.XmlConstants;
import liquibase.statement.SqlStatement;
import liquibase.util.StringUtils;
/**
* The <code>CreateSpatialIndexChange</code> represents a database change to
* create a spatial index.
*/
@DatabaseChange(name = "createSpatialIndex",
description = "Creates a spatial index on an existing column or set of columns.",
priority = ChangeMetaData.PRIORITY_DEFAULT,
appliesTo = "index")
public class CreateSpatialIndexChange extends AbstractChange
implements ChangeWithColumns<ColumnConfig> {
private String catalogName;
private String schemaName;
private String tableName;
private String indexName;
private String tablespace;
private List<ColumnConfig> columns = new ArrayList<ColumnConfig>();
private String geometryType;
private String srid;
/**
* Sets the database catalog name.
*
* @param catalogName
* the catalog name.
*/
public void setCatalogName(final String catalogName) {
this.catalogName = catalogName;
}
@DatabaseChangeProperty(description = "Name of the catalog")
public String getCatalogName() {
return this.catalogName;
}
@DatabaseChangeProperty(mustEqualExisting = "index",
description = "Name of the index to create",
requiredForDatabase = "mysql, oracle, postgresql")
public String getIndexName() {
return this.indexName;
}
public void setIndexName(final String indexName) {
this.indexName = indexName;
}
@DatabaseChangeProperty(mustEqualExisting = "index.schema")
public String getSchemaName() {
return this.schemaName;
}
public void setSchemaName(final String schemaName) {
this.schemaName = schemaName;
}
@DatabaseChangeProperty(mustEqualExisting = "index.table",
description = "Name of the table to add the index to",
exampleValue = "person",
requiredForDatabase = "all")
public String getTableName() {
return this.tableName;
}
public void setTableName(final String tableName) {
this.tableName = tableName;
}
/**
* Returns the geometry type.
*
* @return the geometry type.
*/
@DatabaseChangeProperty(description = "The Well-Known Text geometry type",
exampleValue = "POINT")
public String getGeometryType() {
return this.geometryType;
}
/**
* Sets the geometry type.
*
* @param geometryType
* the geometry type.
*/
public void setGeometryType(final String geometryType) {
this.geometryType = geometryType;
}
/**
* Returns the srid.
*
* @return the srid.
*/
@DatabaseChangeProperty(
description = "The Spatial Reference ID of the indexed data. An EPSG SRID is assumed.",
exampleValue = "4326",
requiredForDatabase = "derby, h2")
public String getSrid() {
return this.srid;
}
/**
* Sets the srid.
*
* @param srid
* the srid.
*/
public void setSrid(final String srid) {
this.srid = srid;
}
@Override
@DatabaseChangeProperty(mustEqualExisting = "index.column",
description = "Column(s) to add to the index",
requiredForDatabase = "all")
public List<ColumnConfig> getColumns() {
if (this.columns == null) {
return new ArrayList<ColumnConfig>();
}
return this.columns;
}
@Override
public void setColumns(final List<ColumnConfig> columns) {
this.columns = columns;
}
@Override
public void addColumn(final ColumnConfig column) {
this.columns.add(column);
}
@DatabaseChangeProperty(description = "Tablepace to create the index in.")
public String getTablespace() {
return this.tablespace;
}
public void setTablespace(final String tablespace) {
this.tablespace = tablespace;
}
/**
* @see liquibase.change.AbstractChange#validate(liquibase.database.Database)
*/
@Override
public ValidationErrors validate(final Database database) {
final ValidationErrors validationErrors = new ValidationErrors();
if (this.srid != null) {
if (!this.srid.matches("[0-9]+")) {
validationErrors.addError("The SRID must be numeric");
}
}
if (!validationErrors.hasErrors()) {
validationErrors.addAll(super.validate(database));
}
return validationErrors;
}
@Override
public String getConfirmationMessage() {
final StringBuilder message = new StringBuilder("Spatial index");
if (StringUtils.trimToNull(getIndexName()) != null) {
message.append(' ').append(getIndexName().trim());
}
message.append(" created");
if (StringUtils.trimToNull(getTableName()) != null) {
message.append(" on ").append(getTableName().trim());
}
return message.toString();
}
@Override
public SqlStatement[] generateStatements(final Database database) {
final String[] columns = new String[this.columns.size()];
int ii = 0;
for (final ColumnConfig columnConfig : this.columns) {
columns[ii++] = columnConfig.getName();
}
// Parse the string SRID into an integer.
Integer srid = null;
if (getSrid() != null) {
srid = Integer.valueOf(getSrid());
}
final CreateSpatialIndexStatement statement = new CreateSpatialIndexStatement(
getIndexName(), getCatalogName(), getSchemaName(), getTableName(), columns,
getTablespace(), getGeometryType(), srid);
return new SqlStatement[] { statement };
}
@Override
protected Change[] createInverses() {
final DropSpatialIndexChange inverse = new DropSpatialIndexChange();
inverse.setCatalogName(getCatalogName());
inverse.setSchemaName(getSchemaName());
inverse.setTableName(getTableName());
inverse.setIndexName(getIndexName());
return new Change[] { inverse };
}
@Override
public String getSerializedObjectNamespace() {
return XmlConstants.SPATIAL_CHANGELOG_NAMESPACE;
}
}