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 java.sql.SQLException;
import java.util.HashMap;
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 Schema entity belonging to a {@link TapSchema}.
* @author Sonia Zorba {@literal <zorba at oats.inaf.it>}
*/
public class Schema extends ChildEntity<TapSchema> implements EntitiesContainer<Table> {
public final static String SCHEMA_NAME_KEY = "schema_name";
public final static String DBNAME = "dbname";
private static final long serialVersionUID = 8828583158332877855L;
private static final Logger LOG = LoggerFactory.getLogger(Schema.class);
private final Map<String, Table> tables;
private Map<String, String> tablesTypes;
/**
* Only for serialization.
*/
private Schema() {
super();
tables = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
}
/**
* Default constructor.
*
* @param tapSchema the {@code TapSchema} owning this schema.
* @param name the name of this schema.
* @throws SQLException if there a problem while retrieving information
* about schema tables.
*/
public Schema(TapSchema tapSchema, String name) throws SQLException {
super(tapSchema, tapSchema.getTableModel(TapSchema.SCHEMAS_TABLE), tapSchema.getSchemaMetadata(name));
DBBroker broker = tapSchema.getDBBroker(name);
tables = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
tablesTypes = broker.getAllTableTypes(getRealSchemaName());
for (String tableName : broker.getAllTablesNames(getRealSchemaName())) {
tables.put(tableName, null);
}
LOG.debug("Schema {} contains {} tables", name, tables.size());
setStatus(Status.LOADED);
}
/**
* Returns the name of the schema as seen by the database. The real schema
* name can be different from the exposed schema name if the schema renaming
* feature has been set. Schema renaming is supported by taplib adding an
* additional column {@code dbname} to the TAP_SCHEMA {@code schema},
* {@code tables} and {@code columns} tables. Not all the TASMAN schema
* definitions includes the {@code dbname} column.
*/
public final String getRealSchemaName() {
if (tapSchema.getDBName() != null && this.getName().equals(tapSchema.getName())) {
return tapSchema.getDBName();
}
if (tapSchema.getIvoaSchemaDBName() != null && this.getName().equals(tapSchema.getIvoaSchemaName())) {
return tapSchema.getIvoaSchemaDBName();
}
return getName();
}
/**
* {@inheritDoc} The value in the {@code schema_name} column.
*/
@Override
public String getName() {
return getValue(SCHEMA_NAME_KEY, String.class);
}
/**
* {@inheritDoc}
*
* @param tableSimpleName the name of the table, without the schema name.
*/
@Override
public Table addChild(String tableSimpleName) throws SQLException {
String schemaName = getName();
LOG.debug("Adding table {} into schema {}", tableSimpleName, schemaName);
if (!tables.containsKey(tableSimpleName)) {
return null;
} else {
Table table = tables.get(tableSimpleName);
if (table == null) {
table = new Table(tapSchema, this, tableSimpleName);
tapSchema.checkKeys();
tables.put(tableSimpleName, table);
table.setStatus(Status.ADDED_NOT_PERSISTED);
} else {
switch (table.getStatus()) {
case TO_REMOVE:
table.setStatus(Status.ADDED_PERSISTED);
break;
case REMOVED_NOT_PERSISTED:
table.setStatus(Status.ADDED_NOT_PERSISTED);
break;
default:
throw new IllegalArgumentException("Invalid table status. The status for " + table.getCompleteName() + " is " + table.getStatus());
}
}
tapSchema.checkKeys();
return table;
}
}
/**
* {@inheritDoc}
*/
@Override
public void removeChild(String tableSimpleName) {
String schemaName = getName();
LOG.debug("Removing table {} from schema {}", tableSimpleName, schemaName);
if (!tables.containsKey(tableSimpleName)) {
throw new IllegalArgumentException("The table " + tableSimpleName + " doesn't exist into the schema " + schemaName + ". Are you sure you are using the simple table name?");
}
Table table = tables.get(tableSimpleName);
if (table == null) {
throw new IllegalArgumentException("The table " + tableSimpleName + " has never been loaded into the schema " + schemaName + ". Are you sure you are using the simple table name?");
}
if (table.getStatus() == Status.LOADED || table.getStatus() == Status.TO_REMOVE) {
throw new IllegalArgumentException("Invalid table status. The status for " + table.getCompleteName() + " is " + table.getStatus());
}
if (table.getStatus() == Status.ADDED_NOT_PERSISTED) {
table.setStatus(Status.REMOVED_NOT_PERSISTED);
} else if (table.getStatus() == Status.ADDED_PERSISTED) {
table.setStatus(Status.TO_REMOVE);
}
tapSchema.checkKeys();
}
/**
* {@inheritDoc}
*/
@Override
public Table getChild(String childName, Status... statuses) {
return TSMUtil.getChild(tables, childName, statuses);
}
/**
* {@inheritDoc}
*/
@Override
public List<Table> getChildren(Status... statuses) {
return TSMUtil.getChildrenByStatus(tables.values(), statuses);
}
/**
* {@inheritDoc}
*/
@Override
public List<String> getAddableChildrenNames() {
return TSMUtil.getAddableChildrenNames(tables);
}
@Override
public boolean isAddable(String childName) {
return tables.containsKey(childName);
}
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
/**
* {@inheritDoc}
*/
@Override
public List<Table> getAddedChildren() {
return getChildren(Status.ADDED_PERSISTED, Status.ADDED_NOT_PERSISTED);
}
/**
* {@inheritDoc}
*/
@Override
public List<Table> getAddedOrRemovedChildren() {
return getChildren(Status.ADDED_PERSISTED, Status.ADDED_NOT_PERSISTED, Status.TO_REMOVE, Status.REMOVED_NOT_PERSISTED);
}
@Override
public int hashCode() {
int hash = 5;
hash = 53 * hash + Objects.hashCode(this.getName());
return hash;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Schema other = (Schema) obj;
return Objects.equals(this.getName(), other.getName());
}
/**
* This method has to be used after TAP_SCHEMA modifications are committed
* to the database, in order to remove from the memory the tables with
* status {@code Status.TO_REMOVE} or {@code Status.REMOVED_NOT_PERSISTED}.
*/
public void cleanTable(String tableSimpleName) {
if (!tables.containsKey(tableSimpleName)) {
throw new IllegalArgumentException("Schema " + getName() + "doesn't contain the table " + tableSimpleName);
}
tables.put(tableSimpleName, null);
}
/**
* {@inheritDoc}
*/
@Override
public TapSchema getParent() {
return tapSchema;
}
/**
* Returns the metadata {@code Map} for a {@link Table} having this schema
* as parent.
*
* @param tableSimpleName the name of the table without its schema name.
* @return a {@code Map} having table property names as keys and table
* property values as values.
*/
public Map<String, Object> getTableMetadata(String tableSimpleName) {
Map<String, Object> metadata = new HashMap<>();
metadata.put(Table.SCHEMA_NAME_KEY, getName());
metadata.put(Table.TABLE_NAME_KEY, getName() + "." + tableSimpleName);
metadata.put(Table.TABLE_TYPE_KEY, tablesTypes.get(tableSimpleName));
return metadata;
}