package tap.metadata;
/*
* This file is part of TAPLibrary.
*
* TAPLibrary is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* TAPLibrary is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with TAPLibrary. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2012-2016 - UDS/Centre de Données astronomiques de Strasbourg (CDS),
* Astronomisches Rechen Institut (ARI)
*/
import java.awt.List;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
import adql.db.DBColumn;
import adql.db.DBTable;
import adql.db.DBType;
import adql.db.DBType.DBDatatype;
/**
* <p>Represent a column as described by the IVOA standard in the TAP protocol definition.</p>
*
* <p>
* This object representation has exactly the same fields as the column of the table TAP_SCHEMA.columns.
* But it also provides a way to add other data. For instance, if information not listed in the standard
* may be stored here, they can be using the function {@link #setOtherData(Object)}. This object can be
* a single value (integer, string, ...), but also a {@link Map}, {@link List}, etc...
* </p>
*
* <p><i><b>Important note:</b>
* A {@link TAPColumn} object MUST always have a DB name. That's why, {@link #getDBName()} returns
* what {@link #getADQLName()} returns when no DB name is set. After creation, it is possible to set
* the DB name with {@link #setDBName(String)}.
* <br/>
* This DB name MUST be UNqualified and without double quotes. If a NULL or empty value is provided,
* {@link #getDBName()} returns what {@link #getADQLName()} returns.
* </i></p>
*
* <h3>Set a table</h3>
*
* <p>
* By default a column is detached (not part of a table). To specify the table in which this column is,
* you must use {@link TAPTable#addColumn(TAPColumn)}. By doing this, the table link inside this column
* will be set automatically and you will be able to get the table with {@link #getTable()}.
* </p>
*
* <h3>Foreign keys</h3>
*
* <p>
* In case this column is linked to one or several of other tables, it will be possible to list all
* foreign keys where the target columns is with {@link #getTargets()}. In the same way, it will be
* possible to list all foreign keys in which this column is a target with {@link #getSources()}.
* However, in order to ensure the consistency between all metadata, these foreign key's links are
* set at the table level by the table itself using {@link #addSource(TAPForeignKey)} and
* {@link #addTarget(TAPForeignKey)}.
* </p>
*
* @author Grégory Mantelet (CDS;ARI)
* @version 2.1 (07/2016)
*/
public class TAPColumn implements DBColumn {
/** Name that this column MUST have in ADQL queries. */
private final String adqlName;
/** Indicates whether the given ADQL name must be simplified by {@link #getADQLName()}.
* <p>Here, "simplification" means removing the surrounding double quotes and the table prefix if any.</p>
* @since 2.1 */
private final boolean simplificationNeeded;
/** Name that this column have in the database.
* <i>Note: It CAN NOT be NULL. By default, it is the ADQL name.</i> */
private String dbName = null;
/** Table which owns this column.
* <i>Note: It should be NULL only at the construction or for a quick representation of a column.
* Then, this attribute is automatically set by a {@link TAPTable} when adding this column inside it
* with {@link TAPTable#addColumn(TAPColumn)}.</i> */
private DBTable table = null;
/** Description of this column.
* <i>Note: Standard TAP column field ; MAY be NULL.</i> */
private String description = null;
/** Unit of this column's values.
* <i>Note: Standard TAP column field ; MAY be NULL.</i> */
private String unit = null;
/** UCD describing the scientific content of this column.
* <i>Note: Standard TAP column field ; MAY be NULL.</i> */
private String ucd = null;
/** UType associating this column with a data-model.
* <i>Note: Standard TAP column field ; MAY be NULL.</i> */
private String utype = null;
/** Type of this column.
* <i>Note: Standard TAP column field ; CAN'T be NULL.</i> */
private DBType datatype = new DBType(DBDatatype.UNKNOWN);
/** Flag indicating whether this column is one of those that should be returned by default.
* <i>Note: Standard TAP column field ; FALSE by default.</i> */
private boolean principal = false;
/** Flag indicating whether this column is indexed in the database.
* <i>Note: Standard TAP column field ; FALSE by default.</i> */
private boolean indexed = false;
/** Flag indicating whether this column can be set to NULL in the database.
* <i>Note: Standard TAP column field ; FALSE by default.</i>
* @since 2.0 */
private boolean nullable = false;
/** Flag indicating whether this column is defined by a standard.
* <i>Note: Standard TAP column field ; FALSE by default.</i> */
private boolean std = false;
/** Ordering index of this column inside its table.
* <i>Note: Standard TAP column field since TAP 1.1.</i>
* @since 2.1 */
private int index = -1;
/** Let add some information in addition of the ones of the TAP protocol.
* <i>Note: This object can be anything: an {@link Integer}, a {@link String}, a {@link Map}, a {@link List}, ...
* Its content is totally free and never used or checked.</i> */
protected Object otherData = null;
/** List all foreign keys in which this column is a source.
* <p><b>CAUTION: For consistency consideration, this attribute SHOULD never be modified!
* It is set by the constructor and filled ONLY by the table.</b></p> */
protected final ArrayList<TAPForeignKey> lstTargets;
/** List all foreign keys in which this column is a target.
* <p><b>CAUTION: For consistency consideration, this attribute SHOULD never be modified!
* It is set by the constructor and filled ONLY by the table.</b></p> */
protected final ArrayList<TAPForeignKey> lstSources;
/**
* <p>Build a VARCHAR {@link TAPColumn} instance with the given ADQL name.</p>
*
* <p><i>Note 1:
* The DB name is set by default to NULL so that {@link #getDBName()} returns exactly what {@link #getADQLName()} returns.
* To set a specific DB name, you MUST call {@link #setDBName(String)}.
* </i></p>
*
* <p><i>Note 2:
* The datatype is set by default to VARCHAR.
* </i></p>
*
* <p><b>Important notes on the given ADQL name:</b></p>
* <ul>
* <li>Any leading or trailing space is immediately deleted.</li>
* <li>
* If the column name is prefixed by its table name, this prefix is removed by {@link #getADQLName()}
* but will be still here when using {@link #getRawName()}. To work, the table name must be exactly the same
* as what the function {@link TAPTable#getRawName()} of the set table returns.
* </li>
* <li>
* Double quotes may surround the single column name. They will be removed by {@link #getADQLName()} but will
* still appear in the result of {@link #getRawName()}.
* </li>
* </ul>
*
* @param columnName Name that this column MUST have in ADQL queries.
* <i>CAN'T be NULL ; this name can never be changed after initialization.</i>
*
* @throws NullPointerException If the given name is <code>null</code>,
* or if the given string is empty after simplification
* (i.e. without the surrounding double quotes).
*/
public TAPColumn(String columnName) throws NullPointerException{
if (columnName == null)
throw new NullPointerException("Missing column name!");
adqlName = columnName.trim();
simplificationNeeded = (adqlName.indexOf('.') > 0 || adqlName.indexOf('"') >= 0);
if (getADQLName().length() == 0)
throw new NullPointerException("Missing column name!");
dbName = null;
lstTargets = new ArrayList<TAPForeignKey>(1);
lstSources = new ArrayList<TAPForeignKey>(1);
}
/**
* <p>Build a {@link TAPColumn} instance with the given ADQL name and datatype.</p>
*
* <p><i>Note 1:
* The DB name is set by default to NULL so that {@link #getDBName()} returns exactly what {@link #getADQLName()} returns.
* To set a specific DB name, you MUST call {@link #setDBName(String)}.
* </i></p>
*
* <p><i>Note 2:
* The datatype is set by default to VARCHAR.
* </i></p>
*
* <p><b>Important notes on the given ADQL name:</b></p>
* <ul>
* <li>Any leading or trailing space is immediately deleted.</li>
* <li>
* If the column name is prefixed by its table name, this prefix is removed by {@link #getADQLName()}
* but will be still here when using {@link #getRawName()}. To work, the table name must be exactly the same
* as what the function {@link TAPTable#getRawName()} of the set table returns.
* </li>
* <li>
* Double quotes may surround the single column name. They will be removed by {@link #getADQLName()} but will
* still appear in the result of {@link #getRawName()}.
* </li>
* </ul>
*
* @param columnName Name that this column MUST have in ADQL queries.
* <i>CAN'T be NULL ; this name can never be changed after initialization.</i>
* @param type Datatype of this column. <i>If NULL, VARCHAR will be the datatype of this column</i>
*
* @throws NullPointerException If the given name is <code>null</code>,
* or if the given string is empty after simplification
* (i.e. without the surrounding double quotes).
*
* @see #setDatatype(DBType)
*/
public TAPColumn(String columnName, DBType type) throws NullPointerException{
this(columnName);
setDatatype(type);
}
/**
* <p>Build a VARCHAR {@link TAPColumn} instance with the given ADQL name and description.</p>
*
* <p><i>Note 1:
* The DB name is set by default to NULL so that {@link #getDBName()} returns exactly what {@link #getADQLName()} returns.
* To set a specific DB name, you MUST call {@link #setDBName(String)}.
* </i></p>
*
* <p><i>Note 2:
* The datatype is set by default to VARCHAR.
* </i></p>
*
* <p><b>Important notes on the given ADQL name:</b></p>
* <ul>
* <li>Any leading or trailing space is immediately deleted.</li>
* <li>
* If the column name is prefixed by its table name, this prefix is removed by {@link #getADQLName()}
* but will be still here when using {@link #getRawName()}. To work, the table name must be exactly the same
* as what the function {@link TAPTable#getRawName()} of the set table returns.
* </li>
* <li>
* Double quotes may surround the single column name. They will be removed by {@link #getADQLName()} but will
* still appear in the result of {@link #getRawName()}.
* </li>
* </ul>
*
* @param columnName Name that this column MUST have in ADQL queries.
* <i>CAN'T be NULL ; this name can never be changed after initialization.</i>
* @param description Description of the column's content. <i>May be NULL</i>
*
* @throws NullPointerException If the given name is <code>null</code>,
* or if the given string is empty after simplification
* (i.e. without the surrounding double quotes).
*/
public TAPColumn(String columnName, String description) throws NullPointerException{
this(columnName, (DBType)null, description);
}
/**
* <p>Build a {@link TAPColumn} instance with the given ADQL name, datatype and description.</p>
*
* <p><i>Note 1:
* The DB name is set by default to NULL so that {@link #getDBName()} returns exactly what {@link #getADQLName()} returns.
* To set a specific DB name, you MUST call {@link #setDBName(String)}.
* </i></p>
*
* <p><i>Note 2:
* The datatype is set by calling the function {@link #setDatatype(DBType)} which does not do
* anything if the given datatype is NULL.
* </i></p>
*
* <p><b>Important notes on the given ADQL name:</b></p>
* <ul>
* <li>Any leading or trailing space is immediately deleted.</li>
* <li>
* If the column name is prefixed by its table name, this prefix is removed by {@link #getADQLName()}
* but will be still here when using {@link #getRawName()}. To work, the table name must be exactly the same
* as what the function {@link TAPTable#getRawName()} of the set table returns.
* </li>
* <li>
* Double quotes may surround the single column name. They will be removed by {@link #getADQLName()} but will
* still appear in the result of {@link #getRawName()}.
* </li>
* </ul>
*
* @param columnName Name that this column MUST have in ADQL queries.
* <i>CAN'T be NULL ; this name can never be changed after initialization.</i>
* @param type Datatype of this column. <i>If NULL, VARCHAR will be the datatype of this column</i>
* @param description Description of the column's content. <i>May be NULL</i>
*
* @throws NullPointerException If the given name is <code>null</code>,
* or if the given string is empty after simplification
* (i.e. without the surrounding double quotes).
*/
public TAPColumn(String columnName, DBType type, String description) throws NullPointerException{
this(columnName, type);
this.description = description;
}
/**
* <p>Build a VARCHAR {@link TAPColumn} instance with the given ADQL name, description and unit.</p>
*
* <p><i>Note 1:
* The DB name is set by default to NULL so that {@link #getDBName()} returns exactly what {@link #getADQLName()} returns.
* To set a specific DB name, you MUST call {@link #setDBName(String)}.
* </i></p>
*
* <p><i>Note 2:
* The datatype is set by default to VARCHAR.
* </i></p>
*
* <p><b>Important notes on the given ADQL name:</b></p>
* <ul>
* <li>Any leading or trailing space is immediately deleted.</li>
* <li>
* If the column name is prefixed by its table name, this prefix is removed by {@link #getADQLName()}
* but will be still here when using {@link #getRawName()}. To work, the table name must be exactly the same
* as what the function {@link TAPTable#getRawName()} of the set table returns.
* </li>
* <li>
* Double quotes may surround the single column name. They will be removed by {@link #getADQLName()} but will
* still appear in the result of {@link #getRawName()}.
* </li>
* </ul>
*
* @param columnName Name that this column MUST have in ADQL queries.
* <i>CAN'T be NULL ; this name can never be changed after initialization.</i>
* @param description Description of the column's content. <i>May be NULL</i>
* @param unit Unit of the column's values. <i>May be NULL</i>
*
* @throws NullPointerException If the given name is <code>null</code>,
* or if the given string is empty after simplification
* (i.e. without the surrounding double quotes).
*/
public TAPColumn(String columnName, String description, String unit) throws NullPointerException{
this(columnName, null, description, unit);
}
/**
* <p>Build a {@link TAPColumn} instance with the given ADQL name, type, description and unit.</p>
*
* <p><i>Note 1:
* The DB name is set by default to NULL so that {@link #getDBName()} returns exactly what {@link #getADQLName()} returns.
* To set a specific DB name, you MUST call {@link #setDBName(String)}.
* </i></p>
*
* <p><i>Note 2:
* The datatype is set by calling the function {@link #setDatatype(DBType)} which does not do
* anything if the given datatype is NULL.
* </i></p>
*
* <p><b>Important notes on the given ADQL name:</b></p>
* <ul>
* <li>Any leading or trailing space is immediately deleted.</li>
* <li>
* If the column name is prefixed by its table name, this prefix is removed by {@link #getADQLName()}
* but will be still here when using {@link #getRawName()}. To work, the table name must be exactly the same
* as what the function {@link TAPTable#getRawName()} of the set table returns.
* </li>
* <li>
* Double quotes may surround the single column name. They will be removed by {@link #getADQLName()} but will
* still appear in the result of {@link #getRawName()}.
* </li>
* </ul>
*
* @param columnName Name that this column MUST have in ADQL queries.
* <i>CAN'T be NULL ; this name can never be changed after initialization.</i>
* @param type Datatype of this column. <i>If NULL, VARCHAR will be the datatype of this column</i>
* @param description Description of the column's content. <i>May be NULL</i>
* @param unit Unit of the column's values. <i>May be NULL</i>
*
* @throws NullPointerException If the given name is <code>null</code>,
* or if the given string is empty after simplification
* (i.e. without the surrounding double quotes).
*/
public TAPColumn(String columnName, DBType type, String description, String unit) throws NullPointerException{
this(columnName, type, description);
this.unit = unit;
}
/**
* <p>Build a VARCHAR {@link TAPColumn} instance with the given fields.</p>
*
* <p><i>Note 1:
* The DB name is set by default to NULL so that {@link #getDBName()} returns exactly what {@link #getADQLName()} returns.
* To set a specific DB name, you MUST call {@link #setDBName(String)}.
* </i></p>
*
* <p><i>Note 2:
* The datatype is set by default to VARCHAR.
* </i></p>
*
* <p><b>Important notes on the given ADQL name:</b></p>
* <ul>
* <li>Any leading or trailing space is immediately deleted.</li>
* <li>
* If the column name is prefixed by its table name, this prefix is removed by {@link #getADQLName()}
* but will be still here when using {@link #getRawName()}. To work, the table name must be exactly the same
* as what the function {@link TAPTable#getRawName()} of the set table returns.
* </li>
* <li>
* Double quotes may surround the single column name. They will be removed by {@link #getADQLName()} but will
* still appear in the result of {@link #getRawName()}.
* </li>
* </ul>
*
* @param columnName Name that this column MUST have in ADQL queries.
* <i>CAN'T be NULL ; this name can never be changed after initialization.</i>
* @param description Description of the column's content. <i>May be NULL</i>
* @param unit Unit of the column's values. <i>May be NULL</i>
* @param ucd UCD describing the scientific content of this column.
* @param utype UType associating this column with a data-model.
*
* @throws NullPointerException If the given name is <code>null</code>,
* or if the given string is empty after simplification
* (i.e. without the surrounding double quotes).
*/
public TAPColumn(String columnName, String description, String unit, String ucd, String utype) throws NullPointerException{
this(columnName, null, description, unit, ucd, utype);
}
/**
* <p>Build a {@link TAPColumn} instance with the given fields.</p>
*
* <p><i>Note 1:
* The DB name is set by default to NULL so that {@link #getDBName()} returns exactly what {@link #getADQLName()} returns.
* To set a specific DB name, you MUST call {@link #setDBName(String)}.
* </i></p>
*
* <p><i>Note 2:
* The datatype is set by calling the function {@link #setDatatype(DBType)} which does not do
* anything if the given datatype is NULL.
* </i></p>
*
* <p><b>Important notes on the given ADQL name:</b></p>
* <ul>
* <li>Any leading or trailing space is immediately deleted.</li>
* <li>
* If the column name is prefixed by its table name, this prefix is removed by {@link #getADQLName()}
* but will be still here when using {@link #getRawName()}. To work, the table name must be exactly the same
* as what the function {@link TAPTable#getRawName()} of the set table returns.
* </li>
* <li>
* Double quotes may surround the single column name. They will be removed by {@link #getADQLName()} but will
* still appear in the result of {@link #getRawName()}.
* </li>
* </ul>
*
* @param columnName Name that this column MUST have in ADQL queries.
* <i>CAN'T be NULL ; this name can never be changed after initialization.</i>
* @param type Datatype of this column. <i>If NULL, VARCHAR will be the datatype of this column</i>
* @param description Description of the column's content. <i>May be NULL</i>
* @param unit Unit of the column's values. <i>May be NULL</i>
* @param ucd UCD describing the scientific content of this column.
* @param utype UType associating this column with a data-model.
*
* @throws NullPointerException If the given name is <code>null</code>,
* or if the given string is empty after simplification
* (i.e. without the surrounding double quotes).
*/
public TAPColumn(String columnName, DBType type, String description, String unit, String ucd, String utype) throws NullPointerException{
this(columnName, type, description, unit);
this.ucd = ucd;
this.utype = utype;
}
/**
* Get the ADQL name (the name this column MUST have in ADQL queries).
*
* @return Its ADQL name.
* @see #getADQLName()
* @deprecated Does not do anything special: just call {@link #getADQLName()}.
*/
@Deprecated
public final String getName(){
return getADQLName();
}
@Override
public final String getADQLName(){
if (simplificationNeeded){
String tmp = adqlName;
// Remove the table prefix if any:
if (table != null){
String tablePrefix = ((table instanceof TAPTable) ? ((TAPTable)table).getRawName() : table.getADQLName()) + ".";
if (tmp.startsWith(tablePrefix))
tmp = tmp.substring(tablePrefix.length()).trim();
}
// Remove the surrounding double-quotes if any:
if (tmp.matches("\"[^\"]*\""))
tmp = tmp.substring(1, tmp.length() - 1);
// Finally, return the result:
return tmp;
}else
return adqlName;
}
/**
* Get the full ADQL name of this table, as it has been provided at initialization.
*
* @return Get the original ADQL name.
*
* @since 2.1
*/
public final String getRawName(){
return adqlName;
}
@Override
public final String getDBName(){
return (dbName == null) ? getADQLName() : dbName;
}
/**
* <p>Change the name that this column MUST have in the database (i.e. in SQL queries).</p>
*
* <p><i>Note:
* If the given value is NULL or an empty string, nothing is done ; the DB name keeps is former value.
* </i></p>
*
* @param name The new database name of this column.
*/
public final void setDBName(String name){
name = (name != null) ? name.trim() : name;
if (name != null && name.length() > 0)
dbName = name;
else
dbName = null;
}
@Override
public final DBTable getTable(){
return table;
}
/**
* <p>Set the table in which this column is.</p>
*
* <p><i><b>Warning:</b>
* For consistency reasons, this function SHOULD be called only by the {@link TAPTable}
* that owns this column.
* </i></p>
*
* <p><i><b>Important note:</b>
* If this column was already linked with another {@link TAPTable} object, the previous link is removed
* here, but also in the table (by calling {@link TAPTable#removeColumn(String)}).
* </i></p>
*
* @param table The table that owns this column.
*/
protected final void setTable(final DBTable table){
if (this.table != null && this.table instanceof TAPTable && (table == null || !table.equals(this.table)))
((TAPTable)this.table).removeColumn(adqlName);
this.table = table;
}
/**
* Get the description of this column.
*
* @return Its description. <i>MAY be NULL</i>
*/
public final String getDescription(){
return description;
}
/**
* Set the description of this column.
*
* @param description Its new description. <i>MAY be NULL</i>
*/
public final void setDescription(String description){
this.description = description;
}
/**
* Get the unit of the column's values.
*
* @return Its unit. <i>MAY be NULL</i>
*/
public final String getUnit(){
return unit;
}
/**
* Set the unit of the column's values.
*
* @param unit Its new unit. <i>MAY be NULL</i>
*/
public final void setUnit(String unit){
this.unit = unit;
}
/**
* Get the UCD describing the scientific content of this column.
*
* @return Its UCD. <i>MAY be NULL</i>
*/
public final String getUcd(){
return ucd;
}
/**
* Set the UCD describing the scientific content of this column.
*
* @param ucd Its new UCD. <i>MAY be NULL</i>
*/
public final void setUcd(String ucd){
this.ucd = ucd;
}
/**
* Get the UType associating this column with a data-model.
*
* @return Its UType. <i>MAY be NULL</i>
*/
public final String getUtype(){
return utype;
}
/**
* Set the UType associating this column with a data-model.
*
* @param utype Its new UType. <i>MAY be NULL</i>
*/
public final void setUtype(String utype){
this.utype = utype;
}
/**
* Get the type of the column's values.
*
* @return Its datatype. <i>CAN'T be NULL</i>
*/
@Override
public final DBType getDatatype(){
return datatype;
}
/**
* <p>Set the type of the column's values.</p>
*
* <p><i>Note:
* If the given type is NULL, an {@link DBDatatype#UNKNOWN UNKNOWN} type will be set instead.
* </i></p>
*
* @param type Its new datatype.
*/
public final void setDatatype(final DBType type){
if (type != null)
datatype = type;
else
datatype = new DBType(DBDatatype.UNKNOWN);
}
/**
* Tell whether this column is one of those returned by default.
*
* @return <i>true</i> if this column should be returned by default, <i>false</i> otherwise.
*/
public final boolean isPrincipal(){
return principal;
}
/**
* Set whether this column should be one of those returned by default.
*
* @param principal <i>true</i> if this column should be returned by default, <i>false</i> otherwise.
*/
public final void setPrincipal(boolean principal){
this.principal = principal;
}
/**
* Tell whether this column is indexed.
*
* @return <i>true</i> if this column is indexed, <i>false</i> otherwise.
*/
public final boolean isIndexed(){
return indexed;
}
/**
* Set whether this column is indexed or not.
*
* @param indexed <i>true</i> if this column is indexed, <i>false</i> otherwise.
*/
public final void setIndexed(boolean indexed){
this.indexed = indexed;
}
/**
* Tell whether this column is nullable.
*
* @return <i>true</i> if this column is nullable, <i>false</i> otherwise.
*
* @since 2.0
*/
public final boolean isNullable(){
return nullable;
}
/**
* Set whether this column is nullable or not.
*
* @param nullable <i>true</i> if this column is nullable, <i>false</i> otherwise.
*
* @since 2.0
*/
public final void setNullable(boolean nullable){
this.nullable = nullable;
}
/**
* Tell whether this column is defined by a standard.
*
* @return <i>true</i> if this column is defined by a standard, <i>false</i> otherwise.
*/
public final boolean isStd(){
return std;
}
/**
* Set whether this column is defined by a standard.
*
* @param std <i>true</i> if this column is defined by a standard, <i>false</i> otherwise.
*/
public final void setStd(boolean std){
this.std = std;
}
/**
* Get the ordering index of this column inside its table.
*
* @return Its ordering index.
*
* @since 2.1
*/
public final int getIndex(){
return index;
}
/**
* Set the ordering index of this column inside its table.
*
* @param columnIndex Its new ordering index.
*
* @since 2.1
*/
public final void setIndex(int columnIndex){
this.index = columnIndex;
}
/**
* <p>Get the other (piece of) information associated with this column.</p>
*
* <p><i>Note:
* By default, NULL is returned, but it may be any kind of value ({@link Integer},
* {@link String}, {@link Map}, {@link List}, ...).
* </i></p>
*
* @return The other (piece of) information. <i>MAY be NULL</i>
*/
public Object getOtherData(){
return otherData;
}
/**
* Set the other (piece of) information associated with this column.
*
* @param data Another information about this column. <i>MAY be NULL</i>
*/
public void setOtherData(Object data){
otherData = data;
}
/**
* <p>Let add a foreign key in which this column is a source (= which is targeting another column).</p>
*
* <p><i>Note:
* Nothing is done if the given value is NULL.
* </i></p>
*
* <p><i><b>Warning:</b>
* For consistency reasons, this function SHOULD be called only by the {@link TAPTable}
* that owns this column or that is part of the foreign key.
* </i></p>
*
* @param key A foreign key.
*/
protected void addTarget(TAPForeignKey key){
if (key != null)
lstTargets.add(key);
}
/**
* Get the number of times this column is targeting another column.
*
* @return How many this column is source in a foreign key.
*/
public int getNbTargets(){
return lstTargets.size();
}
/**
* Get the list of foreign keys in which this column is a source (= is targeting another column).
*
* @return List of foreign keys in which this column is a source.
*/
public Iterator<TAPForeignKey> getTargets(){
return lstTargets.iterator();
}
/**
* <p>Remove the fact that this column is a source (= is targeting another column)
* in the given foreign key.</p>
*
* <p><i>Note:
* Nothing is done if the given value is NULL.
* </i></p>
*
* <p><i><b>Warning:</b>
* For consistency reasons, this function SHOULD be called only by the {@link TAPTable}
* that owns this column or that is part of the foreign key.
* </i></p>
*
* @param key Foreign key in which this column was targeting another column.
*/
protected void removeTarget(TAPForeignKey key){
if (key != null)
lstTargets.remove(key);
}
/**
* <p>Remove the fact that this column is a source (= is targeting another column)
* in any foreign key in which it was.</p>
*
* <p><i><b>Warning:</b>
* For consistency reasons, this function SHOULD be called only by the {@link TAPTable}
* that owns this column or that is part of the foreign key.
* </i></p>
*/
protected void removeAllTargets(){
lstTargets.clear();
}
/**
* <p>Let add a foreign key in which this column is a target (= which is targeted by another column).</p>
*
* <p><i>Note:
* Nothing is done if the given value is NULL.
* </i></p>
*
* <p><i><b>Warning:</b>
* For consistency reasons, this function SHOULD be called only by the {@link TAPTable}
* that owns this column or that is part of the foreign key.
* </i></p>
*
* @param key A foreign key.
*/
protected void addSource(TAPForeignKey key){
if (key != null)
lstSources.add(key);
}
/**
* Get the number of times this column is targeted by another column.
*
* @return How many this column is target in a foreign key.
*/
public int getNbSources(){
return lstSources.size();
}
/**
* Get the list of foreign keys in which this column is a target (= is targeted another column).
*
* @return List of foreign keys in which this column is a target.
*/
public Iterator<TAPForeignKey> getSources(){
return lstSources.iterator();
}
/**
* <p>Remove the fact that this column is a target (= is targeted by another column)
* in the given foreign key.</p>
*
* <p><i>Note:
* Nothing is done if the given value is NULL.
* </i></p>
*
* <p><i><b>Warning:</b>
* For consistency reasons, this function SHOULD be called only by the {@link TAPTable}
* that owns this column or that is part of the foreign key.
* </i></p>
*
* @param key Foreign key in which this column was targeted by another column.
*/
protected void removeSource(TAPForeignKey key){
lstSources.remove(key);
}
/**
* <p>Remove the fact that this column is a target (= is targeted by another column)
* in any foreign key in which it was.</p>
*
* <p><i><b>Warning:</b>
* For consistency reasons, this function SHOULD be called only by the {@link TAPTable}
* that owns this column or that is part of the foreign key.
* </i></p>
*/
protected void removeAllSources(){
lstSources.clear();
}
/**
* <p><i><b>Warning:</b>
* Since the type of the other data is not known, the copy of its value
* can not be done properly. So, this column and its copy will share the same other data object.
* If it is also needed to make a deep copy of this other data object, this function MUST be
* overridden.
* </i></b>
*
* @see adql.db.DBColumn#copy(java.lang.String, java.lang.String, adql.db.DBTable)
*/
@Override
public DBColumn copy(final String dbName, final String adqlName, final DBTable dbTable){
TAPColumn copy = new TAPColumn((adqlName == null) ? this.adqlName : adqlName, datatype, description, unit, ucd, utype);
copy.setDBName((dbName == null) ? this.getDBName() : dbName);
copy.setTable(dbTable);
copy.setIndexed(indexed);
copy.setPrincipal(principal);
copy.setStd(std);
copy.setOtherData(otherData);
return copy;
}
/**
* <p>Provide a deep copy (included the other data) of this column.</p>
*
* <p><i><b>Warning:</b>
* Since the type of the other data is not known, the copy of its value
* can not be done properly. So, this column and its copy will share the same other data object.
* If it is also needed to make a deep copy of this other data object, this function MUST be
* overridden.
* </i></b>
*
* @return The deep copy of this column.
*/
public DBColumn copy(){
TAPColumn copy = new TAPColumn(adqlName, datatype, description, unit, ucd, utype);
copy.setDBName(dbName);
copy.setTable(table);
copy.setIndexed(indexed);
copy.setPrincipal(principal);
copy.setStd(std);
copy.setOtherData(otherData);
return copy;
}
@Override
public boolean equals(Object obj){
if (!(obj instanceof TAPColumn))
return false;
TAPColumn col = (TAPColumn)obj;
return col.getTable().equals(table) && col.getADQLName().equals(adqlName);
}
@Override
public String toString(){
return ((table != null) ? (((table.getADQLSchemaName() != null) ? table.getADQLSchemaName() : "") + table.getADQLName() + ".") : "") + getADQLName();
}
}