/* * _____________________________________________________________________________ * * 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; /** * The main implementation of {@link Table}. * * @author Sonia Zorba {@literal } */ public class Table extends ChildEntity implements EntitiesContainer { 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> columnsMetadata; private Map columns; private String simpleName; private Schema parentSchema; // WARNING: this is different from tableModel inherited field. private TableModel tableTableModel; private Table() { // for serialization super(); } 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 cm : columnsMetadata.values()) { boolean indexed = (boolean) cm.get(Column.INDEXED_KEY); cm.put(Column.INDEXED_KEY, indexed ? 1 : 0); } } } 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()); tableTableModel = getTableTableModel(); columnsMetadata = broker.getAllColumnsMetadata(schema.getRealSchemaName(), tableSimpleName, tableTableModel, tapSchema.getDataTypeMode()); fixIndexedMetadataValues(); for (Map.Entry> 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); } /** * Only the table name. */ @Override public String getName() { return simpleName; } /** * {@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; } /** * {@inheritDoc } */ @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; } } /** * {@inheritDoc } */ @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(); } /** * {@inheritDoc } */ @Override public Column getChild(String childName, Status... statuses) { return TSMUtil.getChild(columns, childName, statuses); } /** * {@inheritDoc } */ @Override public List getChildren(Status... statuses) { return TSMUtil.getChildrenByStatus(columns.values(), statuses); } /** * {@inheritDoc } */ @Override public List getAddableChildrenNames() { return TSMUtil.getAddableChildrenNames(columns); } @Override public boolean isAddable(String childName) { return columns.containsKey(childName); } @Override public List getAddedChildren() { return getChildren(Status.ADDED_PERSISTED, Status.ADDED_NOT_PERSISTED); } @Override public List 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; } public Map getColumnMetadata(String columnName) { return columnsMetadata.get(columnName); } }