Newer
Older
/*
* _____________________________________________________________________________
*
* INAF - OATS National Institute for Astrophysics - Astronomical Observatory of
* Trieste INAF - IA2 Italian Center for Astronomical Archives
* _____________________________________________________________________________
*
* Copyright (C) 2016 Istituto Nazionale di Astrofisica
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License Version 3 as published by the
* Free Software Foundation.
*
* This program 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 General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package it.inaf.ia2.tsm;
import it.inaf.ia2.tsm.datalayer.DBBroker;
import it.inaf.ia2.tsm.model.TableModel;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.TreeMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Represents a Table entity belonging to a {@link TapSchema}.
*
* @author Sonia Zorba {@literal <zorba at oats.inaf.it>}
*/
public class Table extends ChildEntity<Schema> implements EntitiesContainer<Column> {
public final static String SCHEMA_NAME_KEY = "schema_name";
public final static String TABLE_NAME_KEY = "table_name";
public final static String TABLE_TYPE_KEY = "table_type";
public final static String DBNAME = "dbname";
private static final long serialVersionUID = 8265331530960896871L;
private static final Logger LOG = LoggerFactory.getLogger(Table.class);
private Map<String, Map<String, Object>> columnsMetadata;
private Map<String, Column> columns;
private String simpleName;
private Schema parentSchema;
// WARNING: this is different from tableModel inherited field.
private TableModel tableTableModel;
private Table() {
super();
}
/**
* If this table is one of the TAP_SCHEMA tables or it is the ObsCore table
* this method returns the related {@link TableModel}. This method is used
* inside the constructor to set the {@link #tableTableModel} field.
* <strong>WARNING</strong>: this has a different meaning compared to the
* inherited {@link #getTableModel()} method.
*/
private TableModel getTableTableModel() {
if (tapSchema.getName().equals(parentSchema.getName())) {
return tapSchema.getTapSchemaModel().getTable(simpleName);
if (tapSchema.isHasObscore() && parentSchema.getName().equals(TapSchema.STANDARD_IVOA_SCHEMA_NAME)
&& simpleName.equals("obscore")) {
return tapSchema.getIvoaSchemaModel().getTable(simpleName);
}
return null;
}
/**
* Special behavior for retro-compatibility with oldest TAP_SCHEMA versions
* in which the indexed column was represented using 1 and 0 instead boolean
* values.
*/
private void fixIndexedMetadataValues() {
boolean useIntForBool = tapSchema.getTapSchemaModel()
.getTable(TapSchema.COLUMNS_TABLE)
.get(Column.INDEXED_KEY).getJavaType() == Integer.class;
if (useIntForBool) {
for (Map<String, Object> cm : columnsMetadata.values()) {
boolean indexed = (boolean) cm.get(Column.INDEXED_KEY);
cm.put(Column.INDEXED_KEY, indexed ? 1 : 0);
}
}
}
/**
* Default constructor.
*
* @see TapSchemaEntity
* @param tapSchema the {@code TapSchema} owning this table.
* @param schema the {@code Schema} owning this table.
* @param tableSimpleName the name of the table without its schema name.
* @throws SQLException if there are problems while retrieving columns
* metadata.
*/
protected Table(TapSchema tapSchema, Schema schema, String tableSimpleName) throws SQLException {
super(tapSchema, tapSchema.getTableModel(TapSchema.TABLES_TABLE), schema.getTableMetadata(tableSimpleName));
parentSchema = schema;
this.simpleName = tableSimpleName;
columns = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
DBBroker broker = tapSchema.getDBBroker(schema.getName());
columnsMetadata = broker.getAllColumnsMetadata(schema.getRealSchemaName(), tableSimpleName, tableTableModel, tapSchema.getDataTypeMode());
for (Map.Entry<String, Map<String, Object>> entry : columnsMetadata.entrySet()) {
// Adding table names to columns metadata
entry.getValue().put(Column.TABLE_NAME_KEY, schema.getName() + "." + tableSimpleName);
// Initializing columns map
columns.put(entry.getKey(), null);
}
setStatus(Status.LOADED);
}
/**
* Returns only the table name (without the schema name).
*/
@Override
public String getName() {
return simpleName;
}
/**
* Returns the complete table name: {@code schema_name.table_name}.
*/
public String getCompleteName() {
return getValue(TABLE_NAME_KEY, String.class);
}
private boolean isMandatory(String columnName) {
if (tableTableModel != null) {
return tableTableModel.get(columnName).isMandatory();
}
return false;
}
*/
@Override
public Column addChild(String columnName) {
String tableCompleteName = getCompleteName();
LOG.debug("Adding column {} into table {}", columnName, tableCompleteName);
if (!columns.containsKey(columnName)) {
return null;
} else {
Column column = columns.get(columnName);
if (column == null) {
column = new Column(tapSchema, this, columnName, isMandatory(columnName));
columns.put(columnName, column);
column.setStatus(Status.ADDED_NOT_PERSISTED);
} else {
switch (column.getStatus()) {
case REMOVED_NOT_PERSISTED: // undo removal
column.setStatus(Status.ADDED_NOT_PERSISTED);
break;
case TO_REMOVE: // undo removal
column.setStatus(Status.ADDED_PERSISTED);
break;
default:
throw new IllegalArgumentException("Cannot add column " + columnName + " in table " + tableCompleteName + ". Invalid column status: " + column.getStatus());
}
}
tapSchema.checkKeys();
return column;
}
}
/**
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
*/
@Override
public void removeChild(String columnName) {
String tableCompleteName = getCompleteName();
LOG.debug("Removing column {} from table {}", columnName, tableCompleteName);
if (!columns.containsKey(columnName)) {
throw new IllegalArgumentException("Column " + columnName + " doesn't exists in table " + tableCompleteName);
}
Column column = columns.get(columnName);
switch (column.getStatus()) {
case ADDED_NOT_PERSISTED:
column.setStatus(Status.REMOVED_NOT_PERSISTED);
break;
case ADDED_PERSISTED:
column.setStatus(Status.TO_REMOVE);
break;
default:
throw new IllegalArgumentException("Cannot remove column " + columnName + " in table " + tableCompleteName + ". Invalid column status: " + column.getStatus());
}
tapSchema.checkKeys();
}
/**
*/
@Override
public Column getChild(String childName, Status... statuses) {
return TSMUtil.getChild(columns, childName, statuses);
}
/**
*/
@Override
public List<Column> getChildren(Status... statuses) {
return TSMUtil.getChildrenByStatus(columns.values(), statuses);
}
/**
*/
@Override
public List<String> getAddableChildrenNames() {
return TSMUtil.getAddableChildrenNames(columns);
}
@Override
public boolean isAddable(String childName) {
return columns.containsKey(childName);
}
@Override
public List<Column> getAddedChildren() {
return getChildren(Status.ADDED_PERSISTED, Status.ADDED_NOT_PERSISTED);
}
@Override
public List<Column> getAddedOrRemovedChildren() {
return getChildren(Status.ADDED_PERSISTED, Status.ADDED_NOT_PERSISTED, Status.TO_REMOVE, Status.REMOVED_NOT_PERSISTED);
}
@Override
public int hashCode() {
int hash = 7;
hash = 29 * hash + Objects.hashCode(this.getCompleteName());
return hash;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Table other = (Table) obj;
return Objects.equals(this.getCompleteName(), other.getCompleteName());
}
protected void afterUpdate() {
for (Column column : columns.values()) {
if (column.getStatus() == Status.ADDED_NOT_PERSISTED) {
column.setStatus(Status.ADDED_PERSISTED);
} else if (column.getStatus() != Status.ADDED_PERSISTED) {
column.setStatus(Status.LOADED);
}
}
}
@Override
public Schema getParent() {
return parentSchema;
}
* Returns the metadata about a column having this table as parent. Metadata
* are column properties the value of which can be retrieved from the
* database metadata (or information_schema).
*
* @param columnName the name of the column of which retrieve the metadata.
* @return a {@code Map} the keys of which are property names and the values
* of which are property values retrieved from database metadata.
*/
public Map<String, Object> getColumnMetadata(String columnName) {
return columnsMetadata.get(columnName);
}
}