package org.jcommons.db.column;
import static org.jcommons.lang.string.StringBuilderUtils.appendIfNotEmpty;
import org.apache.commons.lang.StringUtils;
/**
* Contains the database meta data for a single column
*
* @author Thorsten Goeckeler
*/
public class MetaColumn
{
private String name;
private String type;
private MetaType metaType;
private Integer size;
private Integer precision;
private Integer fraction;
private boolean nullable;
private boolean primary = false;
private String label;
private String schema;
private String table;
/** @return the column name */
public String getName() {
return name;
}
/**
* Set the name of the column.
*
* @param name the name to set
*/
public void setName(final String name) {
this.name = name;
}
/** @return the class name of the respective Java type */
public String getType() {
return type;
}
/** @return the simple name of the class of the respective Java type for debugging purposes */
public String getSimpleType() {
if (StringUtils.isBlank(getType())) return "ANY";
return getType().substring(Math.max(0, 1 + getType().lastIndexOf('.')));
}
/** @return the meta type in which we can convert this column, <code>null</code> if no type can be determined */
public MetaType getMetaType() {
// not determined yet? can only change if the type is changed
if (metaType == null) {
if (isTimestamp()) {
return MetaType.TIMESTAMP;
} else if (isDate()) {
return MetaType.DATE;
} else if (isNumeric()) {
return MetaType.NUMBER;
} else if (!"ANY".equalsIgnoreCase(getSimpleType())) { return MetaType.STRING; }
}
return null;
}
/**
* Set the Java type class name.
*
* @param type the type to set
*/
public void setType(final String type) {
this.type = type;
this.metaType = null;
}
/*** @return the size of the column, this is the string length for numeric values */
public Integer getSize() {
return size;
}
/**
* Define the size of this column.
*
* @param size the maximum size of the column
*/
public void setSize(final Integer size) {
this.size = size;
}
/** @return the amount of digits of the integral part if it is a numeric value, mostly 0 */
public Integer getPrecision() {
return precision;
}
/**
* Define the integral part of a numeric value.
*
* @param precision the amount of digits that form the integral part without the mantissa
*/
public void setPrecision(final Integer precision) {
this.precision = precision;
}
/** @return the amount of digits of the fraction part if it is a numeric value, that is the mantissa, mostly 0 */
public Integer getFraction() {
return fraction;
}
/**
* Define the fraction part of a numeric value.
*
* @param fraction the amount of digits that form the fraction (the mantissa)
*/
public void setFraction(final Integer fraction) {
this.fraction = fraction;
}
/** @return true if this column can contain <code>null</code> values, otherwise <code>false</code> */
public boolean isNullable() {
return nullable;
}
/** @return true if this column can not contain <code>null</code> values, otherwise <code>false</code> */
public boolean isNotNullable() {
return !isNullable();
}
/**
* Declare whether this column can contain <code>null</code> values or not.
*
* @param nullable <code>true</code> if <code>null</code> values are allowed, <code>false</code> otherwise
*/
public void setNullable(final boolean nullable) {
this.nullable = nullable;
}
/** @return true if this column is part of the primary key */
public boolean isPrimary() {
return primary;
}
/**
* Declare whether this column is part of the primary key.
*
* @param primary <code>true</code> if this is a primary key part, <code>false</code> otherwise
*/
public void setPrimary(final boolean primary) {
this.primary = primary;
}
/** @return the label of the column given in as the alternative name in the SQL statement */
public String getLabel() {
return label;
}
/**
* Indicate which label was used for this column.
*
* @param label the label name for this column to give it an alternative name
*/
public void setLabel(final String label) {
this.label = label;
}
/** @return the schema name for this table */
public String getSchema() {
return schema;
}
/**
* Indicate which schema is addressed by the table of this column.
*
* @param schema the schema name of the table of this column
*/
public void setSchema(final String schema) {
this.schema = schema;
}
/** @return the table name which contains this column */
public String getTable() {
return table;
}
/**
* Set the table name for this column
*
* @param table the table name that contains this column
*/
public void setTable(final String table) {
this.table = table;
}
/** @return true if this column can contain date details, can be day, time or time stamp */
public boolean isDate() {
String type = getSimpleType();
return "date".equalsIgnoreCase(type) || "timestamp".equalsIgnoreCase(type);
}
/** @return true if this column contains time stamps */
public boolean isTimestamp() {
String type = getSimpleType();
return "timestamp".equalsIgnoreCase(type);
}
/** @return true if the column can contain numeric data */
public boolean isNumeric() {
if (StringUtils.isNotBlank(getType())) {
try {
Class< ? > clazz = Class.forName(getType());
return Number.class.isAssignableFrom(clazz);
} catch (ClassNotFoundException e) {
// unsupported type ...
}
}
return false;
}
/** {@inheritDoc} */
@Override
public int hashCode() {
StringBuilder text = new StringBuilder(StringUtils.defaultString(getTable()));
text.append(".").append(StringUtils.defaultString(getName()));
return text.toString().hashCode();
}
/** {@inheritDoc} */
@Override
public boolean equals(final Object other) {
if (this == other) return true;
if (other == null) return false;
if (!this.getClass().isAssignableFrom(other.getClass())) return false;
MetaColumn that = (MetaColumn) other;
return StringUtils.equals(this.toString(), that.toString());
}
/** {@inheritDoc} */
@Override
public String toString() {
StringBuilder text = new StringBuilder();
appendIfNotEmpty(text, null, getSchema(), ".");
if (StringUtils.isNotBlank(getTable())) {
text.append(getTable()).append('.');
}
text.append(StringUtils.defaultIfEmpty(getName(), "<column>")).append('[');
text.append(getSimpleType());
if (isNumeric()) {
text.append("(").append(getPrecision());
if (getFraction() != null && getFraction() > 0) {
text.append(",").append(getFraction());
}
text.append(")");
} else if (!isDate() && getSize() != null && getSize() > 0) {
text.append("(").append(getSize()).append(")");
}
text.append(']');
text.append(isPrimary() ? "!" : (isNullable() ? "" : "*"));
return text.toString();
}
}