diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/Column.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/Column.java index 73648d92978ab2ad4417d398b4a440d07c05bf7e..5d3e208495790706d75bffa91c199deadecc1091 100644 --- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/Column.java +++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/Column.java @@ -49,7 +49,13 @@ public class Column extends ChildEntity<Table> { public final static String COLUMN_INDEX = "column_index"; // TAP version >= 1.1 public final static String DBNAME = "dbname"; - // Original datatype (computed from information_schema data), used for consistency checking + /** + * Original datatype (computed from information_schema data), used for + * consistency checking inside the method + * {@link #it.inaf.ia2.tsm.datalayer.DBBroker.getAllColumnsMetadata()} + * + * @see it.inaf.ia2.tsm.ConsistencyChecks + */ public final static String ORIGINAL_DATATYPE_KEY = "original_datatype"; private static final long serialVersionUID = 9175956487892235521L; diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/Key.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/Key.java index 1e65b1d2ee37ce895b7e66586876d7c26575b868..3c652ea5e114bed9e679d442e0555b7d52dd2df3 100644 --- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/Key.java +++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/Key.java @@ -206,7 +206,33 @@ public class Key extends TapSchemaEntity implements Serializable { @Override public String toString() { - return TSMUtil.printKeyInfo(this); + StringBuilder sb = new StringBuilder(); + + sb.append(String.format("[%s] %s(", getId(), getFromTableCompleteName())); + + boolean first = true; + for (KeyColumn keyColumn : keyColumns) { + if (!first) { + sb.append(","); + } + first = false; + sb.append(keyColumn.getFromColumn()); + } + + sb.append(String.format(") -> %s(", getTargetTableCompleteName())); + + first = true; + for (KeyColumn keyColumn : keyColumns) { + if (!first) { + sb.append(","); + } + first = false; + sb.append(keyColumn.getTargetColumn()); + } + + sb.append(")"); + + return sb.toString(); } @Override diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/KeyHolder.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/KeyHolder.java index e554a5b00caa87121a8fa71480fe5735afb83144..4e8f576cd10eb7625905d01f6f8cd6181540ea21 100644 --- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/KeyHolder.java +++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/KeyHolder.java @@ -25,9 +25,11 @@ package it.inaf.ia2.tsm; import java.io.Serializable; /** - * Model used during consistency checking phase to represents a - * - * + * Model used during consistency checking phase to represents a key that has + * been stored into the TAP_SCHEMA but is not currently existing according to + * the information read from the database metadata. + * + * @see it.inaf.ia2.tsm.ConsistencyChecks * @author Sonia Zorba {@literal <zorba at oats.inaf.it>} */ public class KeyHolder implements Serializable { @@ -52,18 +54,32 @@ public class KeyHolder implements Serializable { return keyId; } + /** + * Returns the complete name of table (schema name plus table name) owning + * the foreign key. + */ public String getFromTable() { return fromTable; } + /** + * Returns the columns composing the foreign key. + */ public String[] getFromColumns() { return fromColumns; } + /** + * Returns the complete name of table (schema name plus table name) owning + * the primary key. + */ public String getTargetTable() { return targetTable; } + /** + * Returns the columns composing the primary key. + */ public String[] getTargetColumns() { return targetColumns; } diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/Schema.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/Schema.java index 227576d1c997f326a3972aa60fb413dc1b255905..6ba852005220273abc5f4396c9c673fa16c618aa 100644 --- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/Schema.java +++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/Schema.java @@ -33,7 +33,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - * The main implementation of {@link Schema}. + * Represents a Schema entity belonging to a {@link TapSchema}. * * @author Sonia Zorba {@literal <zorba at oats.inaf.it>} */ @@ -48,12 +48,22 @@ public class Schema extends ChildEntity<TapSchema> implements EntitiesContainer< private final Map<String, Table> tables; private Map<String, String> tablesTypes; + /** + * Only for serialization. + */ private Schema() { - // for serialization 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)); @@ -70,6 +80,14 @@ public class Schema extends ChildEntity<TapSchema> implements EntitiesContainer< 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(); @@ -89,6 +107,8 @@ public class Schema extends ChildEntity<TapSchema> implements EntitiesContainer< } /** + * {@inheritDoc} + * * @param tableSimpleName the name of the table, without the schema name. */ @Override @@ -185,7 +205,6 @@ public class Schema extends ChildEntity<TapSchema> implements EntitiesContainer< return TSMUtil.getAddableChildrenNames(tables); } - /** * {@inheritDoc} */ @@ -249,6 +268,14 @@ public class Schema extends ChildEntity<TapSchema> implements EntitiesContainer< 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()); diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/TSMUtil.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/TSMUtil.java index 451f3bd2322bf5cf6eb39b753795258c0f33999f..4b13b6f654177d6cbc74c5cf39b20d2253555839 100644 --- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/TSMUtil.java +++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/TSMUtil.java @@ -22,20 +22,17 @@ */ package it.inaf.ia2.tsm; -import it.inaf.ia2.tsm.datalayer.DatabaseType; -import it.inaf.ia2.tsm.datalayer.DBWrapper; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; -import javax.sql.DataSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - * Utility class that contains some static methods to manage various operations + * Utility class containing some static methods to manage various operations * with the TAP_SCHEMA entities. * * @author Sonia Zorba {@literal <zorba at oats.inaf.it>} @@ -132,143 +129,6 @@ public class TSMUtil { return ret; } - /** - * Same as {@link DLUtil.getObject(ResultSet, String, Class<T>)}. - */ - public static <T> T getObject(ResultSet rs, int i, Class<T> type) throws SQLException { - T ret; - if (type == String.class) { - ret = (T) rs.getString(i); - } else if (type == Integer.class) { - ret = (T) (Integer) rs.getInt(i); - } else if (type == Long.class) { - ret = (T) (Long) rs.getLong(i); - } else if (type == Boolean.class) { - ret = (T) (Boolean) rs.getBoolean(i); - } else { - throw new UnsupportedOperationException("Type " + type.getCanonicalName() + " not supported by " + TSMUtil.class.getCanonicalName() + " getObject() method"); - } - - if (rs.wasNull()) { - return null; - } - return ret; - } - - protected static DataSource getSchemaDataSource(DBWrapper dbWrapper, TapSchema tapSchema, String schemaName) { - return schemaName.equals(tapSchema.getName()) ? dbWrapper.getTapSchemaDataSource() : dbWrapper.getSourceDataSource(); - } - - protected static DatabaseType getSchemaDatabaseType(DBWrapper dbWrapper, TapSchema tapSchema, String schemaName) { - return schemaName.equals(tapSchema.getName()) ? dbWrapper.getTapSchemaDatabaseType() : dbWrapper.getSourceDatabaseType(); - } - - protected static boolean isTapSchema(TapSchema tapSchema, String schemaName) { - return schemaName.equals(tapSchema.getName()); - } - - protected static UnsupportedOperationException getUnsupportedOperationException(String version, String unsupportedFeature) { - return new UnsupportedOperationException("Version \"" + version + "\" doesn't support " + unsupportedFeature); - } - - protected static String escapeName(String name, DatabaseType dbType) { - char escapeChar; - switch (dbType) { - case MYSQL: - escapeChar = '`'; - break; - case POSTGRES: - escapeChar = '"'; - break; - default: - throw new UnsupportedOperationException("Database type " + dbType + " not supported"); - } - - return String.format("%s%s%s", escapeChar, name, escapeChar); - } - - protected static String getTapSchemaTableNameFromEntity(TapSchemaEntity entity) { - if (entity instanceof Schema) { - return TapSchema.SCHEMAS_TABLE; - } else if (entity instanceof Table) { - return TapSchema.TABLES_TABLE; - } else if (entity instanceof Column) { - return TapSchema.COLUMNS_TABLE; - } else if (entity instanceof Key) { - return TapSchema.KEYS_TABLE; - } else if (entity instanceof KeyColumn) { - return TapSchema.KEY_COLUMNS_TABLE; - } - LOG.warn("getTapSchemaTableNameFromEntity returns null for {}" + entity.getClass().getCanonicalName()); - return null; - } - - public static String getNaturalLanguageName(TapSchemaEntity entity) { - if (entity instanceof Schema) { - return "schema"; - } else if (entity instanceof Table) { - return "table"; - } else if (entity instanceof Column) { - return "column"; - } else if (entity instanceof Key) { - return "key"; - } else if (entity instanceof KeyColumn) { - return "key_column"; - } else { - throw new UnsupportedOperationException("entity class " + entity.getClass().getCanonicalName() + " not supported yet"); - } - } - - public static String getName(TapSchemaEntity entity) { - if (entity instanceof Schema) { - return ((Schema) entity).getName(); - } else if (entity instanceof Table) { - return ((Table) entity).getCompleteName(); - } else if (entity instanceof Column) { - Column column = (Column) entity; - return column.getParent().getCompleteName() + "." + column.getName(); - } else if (entity instanceof Key) { - return printKeyInfo((Key) entity); - } else if (entity instanceof KeyColumn) { - KeyColumn keyColumn = (KeyColumn) entity; - return String.format("%s -> %s [key: %s]", - keyColumn.getFromColumn(), keyColumn.getTargetColumn(), - printKeyInfo(keyColumn.getParent())); - } else { - throw new UnsupportedOperationException("entity class " + entity.getClass().getCanonicalName() + " not supported yet"); - } - } - - public static String printKeyInfo(Key key) { - StringBuilder sb = new StringBuilder(); - - sb.append(String.format("[%s] %s(", key.getId(), key.getFromTableCompleteName())); - - boolean first = true; - for (KeyColumn keyColumn : key.getKeyColumns()) { - if (!first) { - sb.append(","); - } - first = false; - sb.append(keyColumn.getFromColumn()); - } - - sb.append(String.format(") -> %s(", key.getTargetTableCompleteName())); - - first = true; - for (KeyColumn keyColumn : key.getKeyColumns()) { - if (!first) { - sb.append(","); - } - first = false; - sb.append(keyColumn.getTargetColumn()); - } - - sb.append(")"); - - return sb.toString(); - } - /** * Utility class for joining a collection of object properties. */ diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/Table.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/Table.java index 2c682618544f329d415584abd698e1a657ad5df2..7dab2cf52c52d58271e80e22dc3ef99e78ab4fda 100644 --- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/Table.java +++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/Table.java @@ -304,9 +304,9 @@ public class Table extends ChildEntity<Schema> implements EntitiesContainer<Colu } /** - * Returns the metadata about a column children of this table. Metadata are - * column properties the value of which can be retrieved from the database - * metadata (or information_schema). + * 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 diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/TapSchema.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/TapSchema.java index 61de723ccbba3160822ccf6ddcd9b8f41fc087b3..29da3082f360df46c0b093a53e5e3a4d9b99e3be 100644 --- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/TapSchema.java +++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/TapSchema.java @@ -43,10 +43,13 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** + * Contains both data models of the entities exposed by the TAP_SCHEMA and + * method for managing them and edit the TAP_SCHEMA content. + * * @author Sonia Zorba {@literal <zorba at oats.inaf.it>} */ public class TapSchema implements EntitiesContainer<Schema>, Serializable { - + public static final String STANDARD_TAP_SCHEMA_NAME = "TAP_SCHEMA"; public static final String STANDARD_IVOA_SCHEMA_NAME = "ivoa"; @@ -56,16 +59,16 @@ public class TapSchema implements EntitiesContainer<Schema>, Serializable { public static final String COLUMNS_TABLE = "columns"; public static final String KEYS_TABLE = "keys"; public static final String KEY_COLUMNS_TABLE = "key_columns"; - + public static final String DESCRIPTION_KEY = "description"; - + private static final long serialVersionUID = 1678083091602571256L; - + private static final Logger LOG = LoggerFactory.getLogger(TapSchema.class); - + private final Map<String, Schema> schemas; private final Set<Key> allKeys; - + private boolean loading; private DBWrapper dbWrapper; private String dbName; @@ -75,47 +78,67 @@ public class TapSchema implements EntitiesContainer<Schema>, Serializable { private boolean exists; private TapSchemaSettings settings; private DataTypeMode dataTypeMode; - + private transient DBBroker sourceDBBroker; private transient DBBroker tapSchemaDBBroker; - + private ConsistencyChecks consistencyChecks; - + + /** + * Returns the {@link DBBroker} for the database containing the astronomical + * data and the ObsCore (called the <em>source</em> in TASMAN jargon). + * + * @see it.inaf.ia2.tsm.datalayer.DBWrapper + */ public final DBBroker getSourceDBBroker() { if (sourceDBBroker == null) { sourceDBBroker = DBBrokerFactory.getDBBroker(dbWrapper.getSourceDataSourceWrapper(), dataTypeMode); } return sourceDBBroker; } - + + /** + * Returns the {@link DBBroker} for the database containing the TAP_SCHEMA + * schema. + * + * @see it.inaf.ia2.tsm.datalayer.DBWrapper + */ public final DBBroker getTapSchemaDBBroker() { if (tapSchemaDBBroker == null) { tapSchemaDBBroker = DBBrokerFactory.getDBBroker(dbWrapper.getTapSchemaDataSourceWrapper(), dataTypeMode); } return tapSchemaDBBroker; } - + + /** + * Only for serialization. + */ private TapSchema() { - // for serialization schemas = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); allKeys = new HashSet<>(); } - + + /** + * Default constructor. + * + * @param exists true if the TAP_SCHEMA has already been created, false if + * must be created when the {@link #save() method is called}. + */ public TapSchema(DBWrapper dbWrapper, TapSchemaSettings settings, boolean exists) throws SQLException { this(); - + this.dbWrapper = dbWrapper; this.exists = exists; this.settings = settings; // Don't change the instructions order! loadDBName(); loadName(); - + dataTypeMode = getTapSchemaModel().getDataTypeMode(); - + load(); } - + private void loadDBName() { // Detect if the TAP_SCHEMA version supports dbmodel SchemaModel tapSchemaModel = SchemaModels.getTapSchemaModel(settings.getTapSchemaVersion()); @@ -129,7 +152,7 @@ public class TapSchema implements EntitiesContainer<Schema>, Serializable { } } } - + private void loadName() { if (dbName != null) { name = STANDARD_TAP_SCHEMA_NAME; @@ -142,9 +165,15 @@ public class TapSchema implements EntitiesContainer<Schema>, Serializable { ivoaSchemaName = settings.getIvoaSchemaName(); } } - + + /** + * Loads the TAP_SCHEMA information from the database. This method is called + * in the constructor, but it can be called in every moment for reloading + * database metadata (this is useful if some modifications have been + * performed to the source schemata structure). + */ public final void load() throws SQLException { - + loading = true; // Initializing schemas map schemas.clear(); @@ -155,16 +184,19 @@ public class TapSchema implements EntitiesContainer<Schema>, Serializable { if (settings.isHasObscore() && ivoaSchemaDBName != null) { schemas.put(getIvoaSchemaName(), null); } - + if (exists) { consistencyChecks = TapSchemaLoader.loadExistingTapSchema((this)); } - + loading = false; - + checkKeys(); } - + + /** + * Returns the {@link DBBroker} related to a given schema. + */ public DBBroker getDBBroker(String schemaName) { if (schemaName.equals(getName())) { return getTapSchemaDBBroker(); @@ -174,28 +206,36 @@ public class TapSchema implements EntitiesContainer<Schema>, Serializable { } /** - * The name of the TAP_SCHEMA schema. + * Returns the name of the TAP_SCHEMA schema, as exposed by itself. */ public final String getName() { return name; } /** - * The version selected for this TAP_SCHEMA. + * Return the versions selected for this TAP_SCHEMA. */ public String getVersion() { return settings.getTapSchemaVersion(); } - + + /** + * Returns the {@link DataTypeMode} used by this TAP_SCHEMA. + */ public DataTypeMode getDataTypeMode() { return dataTypeMode; } - + private void loadSchemaKeysMetadata(String schemaName) throws SQLException { allKeys.addAll(getDBBroker(schemaName) .getKeys(this, schemaName, getRealSchemaName(schemaName))); } - + + /** + * Returns all {@link Key} entities loaded by this instance; this include + * both visible and hidden keys (that are keys that must be exposed by the + * TAP_SCHEMA and keys that mustn't). + */ public Set<Key> getAllKeys() { return allKeys; } @@ -206,15 +246,15 @@ public class TapSchema implements EntitiesContainer<Schema>, Serializable { @Override public final Schema addChild(String schemaName) throws SQLException { LOG.debug("Adding schema {}", schemaName); - + Schema schema; - + if (!schemas.containsKey(schemaName)) { schema = null; } else { - + schema = schemas.get(schemaName); - + if (schema == null) { schema = new Schema(this, schemaName); schema.setStatus(Status.ADDED_NOT_PERSISTED); @@ -232,10 +272,10 @@ public class TapSchema implements EntitiesContainer<Schema>, Serializable { throw new IllegalArgumentException("Cannot add the schema " + schemaName + ". Invalid status. Schema status is " + schema.getStatus()); } } - + checkKeys(); } - + return schema; } @@ -245,22 +285,22 @@ public class TapSchema implements EntitiesContainer<Schema>, Serializable { @Override public void removeChild(String schemaName) { LOG.debug("Removing schema {}", schemaName); - + if (!schemas.containsKey(schemaName)) { throw new IllegalArgumentException("The database doesn't contains a schema named " + schemaName); } - + Schema schema = schemas.get(schemaName); if (schema == null || schema.getStatus() == Status.LOADED) { throw new IllegalArgumentException("Cannot remove the schema " + schemaName + ". It has never been added."); } - + if (schema.getStatus() == Status.ADDED_NOT_PERSISTED) { schema.setStatus(Status.REMOVED_NOT_PERSISTED); } else if (schema.getStatus() == Status.ADDED_PERSISTED) { schema.setStatus(Status.TO_REMOVE); } - + checkKeys(); } @@ -287,7 +327,10 @@ public class TapSchema implements EntitiesContainer<Schema>, Serializable { public List<String> getAddableChildrenNames() { return TSMUtil.getAddableChildrenNames(schemas); } - + + /** + * {@inheritDoc} + */ @Override public boolean isAddable(String childName) { return schemas.containsKey(childName); @@ -320,14 +363,23 @@ public class TapSchema implements EntitiesContainer<Schema>, Serializable { } schemas.put(schemaName, null); } - + + /** + * Returns the {@link SchemaModel} for the {@code ivoa} schema if the + * {@code ObsCore} table must be managed by this {@code TapSchema}, returns + * null otherwise. + */ public SchemaModel getIvoaSchemaModel() { if (settings.isHasObscore()) { return SchemaModels.getIvoaSchemaModel(settings.getObscoreVersion()); } return null; } - + + /** + * Add an entire schema to the TAP_SCHEMA, including all all its tables and + * columns children. + */ public void addEntireSchema(String schemaName) throws SQLException { Schema schema = addChild(schemaName); for (String tableName : schema.getAddableChildrenNames()) { @@ -342,9 +394,9 @@ public class TapSchema implements EntitiesContainer<Schema>, Serializable { * Save or update the TAP_SCHEMA changes into the database. */ public void save() throws SQLException { - + DBBroker broker = getTapSchemaDBBroker(); - + if (!exists) { SchemaModel tapSchemaModel = getTapSchemaModel(); broker.createTapSchemaStructure(getRealName(), tapSchemaModel); @@ -352,21 +404,21 @@ public class TapSchema implements EntitiesContainer<Schema>, Serializable { // Adding TAP_SCHEMA into TAP_SCHEMA addEntireSchema(getName()); fillColumnProperties(tapSchemaModel, getName()); - + if (settings.isHasObscore()) { createAndAddIvoaSchema(); } } - + fillKeyIds(); - + broker.save(this); exists = true; // Clean inconsistency consistencyChecks = null; } - + public void createAndAddIvoaSchema() throws SQLException { SchemaModel ivoaSchemaModel = getIvoaSchemaModel(); @@ -381,10 +433,10 @@ public class TapSchema implements EntitiesContainer<Schema>, Serializable { } /** - * Retrieve the maximum key id from all the schemas that are added into the + * Retrieve the maximum key id from all the keys that are added into the * TAP_SCHEMA. * - * @return the maximum key, if it exists, zero otherwise. + * @return the maximum key id, if it exists, zero otherwise. */ private int getMaxKeyId() { int maxKeyId = 0; @@ -398,16 +450,16 @@ public class TapSchema implements EntitiesContainer<Schema>, Serializable { } return maxKeyId; } - + private void fillKeyIds() { - + List<Key> newKeys = new ArrayList<>(); for (Key key : allKeys) { if (key.isVisible() && key.getId() == null) { newKeys.add(key); } } - + int maxKeyId = getMaxKeyId(); for (Key newKey : newKeys) { maxKeyId++; @@ -422,12 +474,12 @@ public class TapSchema implements EntitiesContainer<Schema>, Serializable { */ public final void checkKeys() { if (!loading) { - + for (Key key : allKeys) { // Check if key should be exposed in TAP_SCHEMA boolean keyVisible = true; - + for (KeyColumn keyColumn : key.getKeyColumns()) { String schemaName = keyColumn.getParent().getFromSchemaName(); String tableName = keyColumn.getParent().getFromTableSimpleName(); @@ -436,7 +488,7 @@ public class TapSchema implements EntitiesContainer<Schema>, Serializable { keyVisible = false; break; } - + schemaName = keyColumn.getParent().getTargetSchemaName(); tableName = keyColumn.getParent().getTargetTableSimpleName(); columnName = keyColumn.getTargetColumn(); @@ -457,11 +509,11 @@ public class TapSchema implements EntitiesContainer<Schema>, Serializable { */ @Override public String toString() { - + StringBuilder sb = new StringBuilder("\n"); - + sb.append(String.format(">> TAP_SCHEMA %s <<\n", getName())); - + for (Schema schema : getChildren()) { sb.append("--"); sb.append(schema.getName()); @@ -474,9 +526,9 @@ public class TapSchema implements EntitiesContainer<Schema>, Serializable { sb.append(table.getName()); sb.append(String.format(" [%s]", table.getStatus())); sb.append("\n"); - + String padder = i < tables.size() - 1 ? " | " : " "; - + for (Column column : table.getChildren()) { sb.append(padder); sb.append("|--"); @@ -484,20 +536,23 @@ public class TapSchema implements EntitiesContainer<Schema>, Serializable { sb.append(String.format(" [%s]", column.getStatus())); sb.append("\n"); } - + sb.append("\n"); } } - + sb.append("** Keys **\n"); for (Key key : getVisibileKeys()) { sb.append(key); sb.append("\n"); } - + return sb.toString(); } - + + /** + * Tells if a schema has to be exposed by the TAP_SCHEMA. + */ public boolean isSchemaVisible(String schemaName) { Schema schema = schemas.get(schemaName); if (schema == null) { @@ -506,62 +561,82 @@ public class TapSchema implements EntitiesContainer<Schema>, Serializable { return schema.getStatus() == Status.ADDED_PERSISTED || schema.getStatus() == Status.ADDED_NOT_PERSISTED; } - + + /** + * Tells if a table has to be exposed by the TAP_SCHEMA. + */ public boolean isTableVisible(String schemaName, String tableName) { if (!isSchemaVisible(schemaName)) { return false; } - + Table table = schemas.get(schemaName).getChild(tableName); if (table == null) { return false; } - + if (table.getStatus() == Status.ADDED_PERSISTED || table.getStatus() == Status.ADDED_NOT_PERSISTED) { return isSchemaVisible(schemaName); } - + return false; } - + + /** + * Tells if a column has to be exposed by the TAP_SCHEMA. + */ public boolean isColumnVisible(String schemaName, String tableName, String columnName) { if (!isTableVisible(schemaName, tableName)) { return false; } - + Column column = schemas.get(schemaName).getChild(tableName).getChild(columnName); if (column == null) { return false; } - + if (column.getStatus() == Status.ADDED_PERSISTED || column.getStatus() == Status.ADDED_NOT_PERSISTED) { return isTableVisible(schemaName, tableName); } - + return false; } /** - * Define if the TAP_SCHEMA schema was already written into the database. + * Tells if the TAP_SCHEMA schema was already written into the database or + * it has to be created when the {@link #save()} method will be called. */ public boolean exists() { return exists; } - + + /** + * Returns the result of the consistency checking performed during the + * TAP_SCHEMA loading. + */ public ConsistencyChecks getConsistencyChecks() { return consistencyChecks; } - + + /** + * Returns the {@link SchemaModel} for the TAP_SCHEMA schema. + */ public final SchemaModel getTapSchemaModel() { return SchemaModels.getTapSchemaModel(getVersion()); } - + + /** + * Returns the {@link TableModel} for a TAP_SCHEMA table. + */ public final TableModel getTableModel(String tableName) { return getTapSchemaModel().getTable(tableName); } - + + /** + * Returns the metadata of a schema managed by this TAP_SCHEMA. + */ public Map<String, Object> getSchemaMetadata(String schemaName) { Map<String, Object> metadata = new HashMap<>(); metadata.put(Schema.SCHEMA_NAME_KEY, schemaName); @@ -572,7 +647,10 @@ public class TapSchema implements EntitiesContainer<Schema>, Serializable { metadata.put(Schema.DBNAME, dbNameMetadata); return metadata; } - + + /** + * Returns all the keys that are currently exposed by this TAP_SCHEMA. + */ public List<Key> getVisibileKeys() { List<Key> visibleKeys = new ArrayList<>(); for (Key key : allKeys) { @@ -582,27 +660,26 @@ public class TapSchema implements EntitiesContainer<Schema>, Serializable { } return visibleKeys; } - + private Integer getIntAsBool(Boolean value) { if (value == null) { return null; } return value ? 1 : 0; } - + + /** + * Tells if the {@code ObsCore} table should be managed or not. + */ public boolean isHasObscore() { return settings.isHasObscore(); } - /** - * Fill descriptions of the TAP_SCHEMA schema entities for a given - * SchemaModel (TAP_SCHEMA or ivoa). - */ private void fillColumnProperties(SchemaModel schemaModel, String schemaName) { // check only on std, but valid also for principal (it depends on TS version) boolean useIntegerAsBool = getTapSchemaModel().getTable(COLUMNS_TABLE).get(Column.STD_KEY).getJavaType() == Integer.class; - + Schema schema = getChild(schemaName); schema.setValue(DESCRIPTION_KEY, schemaModel.getDescription()); for (TableModel tableModel : schemaModel.getTables()) { @@ -618,7 +695,7 @@ public class TapSchema implements EntitiesContainer<Schema>, Serializable { column.setValue(Column.UCD_KEY, columnModel.getUcd()); column.setValue(Column.UNIT_KEY, columnModel.getUnit()); column.setValue(Column.UTYPE_KEY, columnModel.getUtype()); - + Object compatibleStd = useIntegerAsBool ? getIntAsBool(columnModel.isStandard()) : columnModel.isStandard(); Object compatiblePrincipal = useIntegerAsBool ? getIntAsBool(columnModel.isPrincipal()) : columnModel.isPrincipal(); column.setValue(Column.STD_KEY, compatibleStd); @@ -626,33 +703,57 @@ public class TapSchema implements EntitiesContainer<Schema>, Serializable { } } } - + + /** + * Fills descriptions of the TAP_SCHEMA schema entities for a given + * SchemaModel (TAP_SCHEMA or ivoa). + */ public void fillColumnsProperties(SchemaModel schemaModel) { fillColumnProperties(schemaModel, schemaModel.getName()); } /** - * Allows to name the TAP_SCHEMA using the standard name, but referring to a - * differently named schema. This value is null if the TAP_SCHEMA version - * doesn't support the dbname column or if the schema name is already the - * standard value. + * Returns the TAP_SCHEMA schema {@code dbname} property, used to allow the + * schema renaming supported by taplib (in this way the TAP_SCHEMA could be + * exposed using the standard name, even if it is stored with a different + * named into the database). This value is null if the TAP_SCHEMA version + * doesn't support the {@code dbname} column or if the schema name is + * already the standard value. */ public String getDBName() { return dbName; } - + + /** + * Returns the ivoa schema {@code dbname} property, used to allow the schema + * renaming supported by taplib. + * + * @see #getDBName() + */ public String getIvoaSchemaDBName() { return ivoaSchemaDBName; } - + + /** + * Returns the name of the {@code ivoa} schema, as exposed by the + * TAP_SCHEMA. + */ public String getIvoaSchemaName() { return ivoaSchemaName; } - + + /** + * Returns the real name of the TAP_SCHEMA schema, as seen by the database + * (useful when schema renaming has been configured). + */ public String getRealName() { return getRealSchemaName(getName()); } - + + /** + * Returns the real name of a schema exposed by the TAP_SCHEMA, as seen by + * the database (useful when schema renaming has been configured). + */ public String getRealSchemaName(String schemaName) { if (dbName != null && STANDARD_TAP_SCHEMA_NAME.equals(schemaName)) { return dbName; diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/TapSchemaMender.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/TapSchemaMender.java index 13346e0485b973cdddb97b347ce22c50bad85e06..5eb31934f8a6e135b9caace8e77c9b567e492ff6 100644 --- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/TapSchemaMender.java +++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/TapSchemaMender.java @@ -32,7 +32,7 @@ import java.util.Map; import java.util.Set; /** - * This fixes TAP_SCHEMA inconsistencies. + * Handles fixes of TAP_SCHEMA inconsistencies. * * @author Sonia Zorba {@literal <zorba at oats.inaf.it>} */ @@ -46,6 +46,9 @@ public class TapSchemaMender { consistencyChecks = tapSchema.getConsistencyChecks(); } + /** + * Fixes inconsistencies of a just loaded TAP_SCHEMA. + */ public static void amendTapSchema(TapSchema tapSchema) throws SQLException { new TapSchemaMender(tapSchema).amendTapSchema(); } diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/TapSchemaSettings.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/TapSchemaSettings.java index 386a991da86c4b3ccc52c4fc2bc720772a5a840d..6fd520be7ff96a621495045a5060009926f321ee 100644 --- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/TapSchemaSettings.java +++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/TapSchemaSettings.java @@ -25,6 +25,7 @@ package it.inaf.ia2.tsm; import java.io.Serializable; /** + * Contains all the settings specified for a TAP_SCHEMA. * * @author Sonia Zorba {@literal <zorba at oats.inaf.it>} */ @@ -43,14 +44,28 @@ public class TapSchemaSettings implements Serializable { ivoaSchemaName = TapSchema.STANDARD_IVOA_SCHEMA_NAME; } + /** + * TASMAN supports multiple TAP_SCHEMA versions; schemata structure change + * from one version to another and the definition of this structure is + * stored into XML files inside the {@code schema_definition} resource + * folder. + */ public String getTapSchemaVersion() { return tapSchemaVersion; } + /** + * @see #getTapSchemaVersion() + */ public void setTapSchemaVersion(String tapSchemaVersion) { this.tapSchemaVersion = tapSchemaVersion; } + /** + * Returns the name of the TAP_SCHEMA schema, as saved into the database. + * The name can be different from the exposed name if schema renaming is + * enabled. + */ public String getTapSchemaName() { return tapSchemaName; } @@ -59,6 +74,9 @@ public class TapSchemaSettings implements Serializable { this.tapSchemaName = tapSchemaName; } + /** + * Tells if the {@code ObsCore} table should be managed by TASMAN. + */ public boolean isHasObscore() { return hasObscore; } @@ -75,6 +93,10 @@ public class TapSchemaSettings implements Serializable { this.obscoreVersion = obscoreVersion; } + /** + * Returns the name of the ivoa schema, as saved into the database. The name + * can be different from the exposed name if schema renaming is enabled. + */ public String getIvoaSchemaName() { return ivoaSchemaName; } diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/UpdateOperations.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/UpdateOperations.java index 9df0f31a8dbb020e2a795f0c5e3491d9a5066460..852a0c8b61a2e19a198e8f68fb090d71e3b8aa96 100644 --- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/UpdateOperations.java +++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/UpdateOperations.java @@ -28,12 +28,11 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - * List of operations that have to be performed by the - * {@link it.inaf.ia2.tsm.TapSchema#save()} method, - * in terms of adding, updating or removing - * {@link it.inaf.ia2.tsm.TapSchemaEntity} entities. Could be used - * stand-alone to obtain a preview of the operations that will be performed on - * the database. + * Models the list of operations that have to be performed by the + * {@link it.inaf.ia2.tsm.TapSchema#save()} method, in terms of adding, updating + * or removing {@link it.inaf.ia2.tsm.TapSchemaEntity} entities. Could also be + * used stand-alone to obtain a preview of the operations that will be performed + * on the database. * * @author Sonia Zorba {@literal <zorba at oats.inaf.it>} */ @@ -41,8 +40,6 @@ public class UpdateOperations { private static final Logger LOG = LoggerFactory.getLogger(UpdateOperations.class); - private final TapSchema tapSchema; - private final List<Schema> schemasToRemove; private final List<Schema> schemasToAdd; private final List<Schema> schemasToUpdate; @@ -71,9 +68,6 @@ public class UpdateOperations { } public UpdateOperations(TapSchema tapSchema) { - - this.tapSchema = tapSchema; - schemasToRemove = new ArrayList<>(); schemasToAdd = new ArrayList<>(); schemasToUpdate = new ArrayList<>(); diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/WrongDataType.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/WrongDataType.java index 7de2eb38cb0268dcbf07140f768b606f8e7c8c3c..bc459d2042f88063aaa3340f0f4e9fefb79ef7cb 100644 --- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/WrongDataType.java +++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/WrongDataType.java @@ -27,8 +27,8 @@ import java.io.Serializable; /** * Models an inconsistency in a column definition detected in an existing * column. This happens when the column datatype read from the database metadata - * is different from which is expected according the {@link ColumnModel} - * defining that column. To fix this issue an {@code ALTER TABLE} is necessary. + * is different from what is expected according the {@link ColumnModel} defining + * that column. To fix this issue an {@code ALTER TABLE} is necessary. * * @author Sonia Zorba {@literal <zorba at oats.inaf.it>} */ diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/ADQL.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/ADQL.java index 38392e36af4d16c20255924624e2e202e8c497cb..1e6ee1f96dc6b839f68ad99353f8e7d2e8163505 100644 --- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/ADQL.java +++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/ADQL.java @@ -28,7 +28,7 @@ package it.inaf.ia2.tsm.datalayer; * @author Sonia Zorba {@literal <zorba at oats.inaf.it>} */ public enum ADQL { - + VARCHAR, CHAR, BOOLEAN, @@ -46,13 +46,21 @@ public enum ADQL { POINT; /** - * For not standard types + * Returns a string representing a datatype which can't be interpreted as an + * ADQL datatype (that is in case of not standard data types). Removes + * possible size appended at the end of datatype. */ public static String getDataType(String dataType) { // removing size from datatype. return dataType.toUpperCase().replaceAll("\\(.+\\)", ""); } - + + /** + * Tells if a datatype has a variable length. + * + * @param adql value of the datatype using ADQL syntax + * @return true if the datatype has a variable length, false otherwise. + */ public static boolean isVariable(ADQL adql) { return adql.equals(VARCHAR) || adql.equals(VARBINARY) || adql.equals(CLOB) || adql.equals(BLOB); } diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/Credentials.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/Credentials.java index 35695c942af3d4fbf06393da2b7fcf0f3e45af29..97b1bfae0be54a4bb3420b58d991d3a35d99643f 100644 --- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/Credentials.java +++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/Credentials.java @@ -90,6 +90,9 @@ public class Credentials implements Serializable { this.port = port; } + /** + * The username used for connecting to the database. + */ @XmlAttribute(name = "username", required = true) public String getUsername() { return this.username; @@ -99,6 +102,9 @@ public class Credentials implements Serializable { this.username = username; } + /** + * The password used for connecting to the database. + */ @XmlAttribute(name = "password", required = true) public String getPassword() { return this.password; @@ -109,7 +115,7 @@ public class Credentials implements Serializable { } /** - * The kind of RDBMS used. + * The kind of RDBMS used (e.<!-- -->g.<!-- --> MySQL, PostgreSQL, etc). */ @XmlAttribute(name = "database-type", required = true) public DatabaseType getDatabaseType() { @@ -121,7 +127,7 @@ public class Credentials implements Serializable { } /** - * <strong>Only for POSTGRES</strong>. The database to use in the + * <strong>Only for PostgreSQL</strong>. The database to use in the * connection. The default value is "postgres". */ @XmlAttribute(name = "database") @@ -130,7 +136,7 @@ public class Credentials implements Serializable { } /** - * <strong>Only for POSTGRES</strong>. The database to use in the + * <strong>Only for PostgreSQL</strong>. The database to use in the * connection. */ public void setDatabase(String database) { @@ -138,8 +144,8 @@ public class Credentials implements Serializable { } /** - * Set default values for <code>databaseType</code>, <code>database</code> - * and <code>port</code> properties. + * Set default values for {@code databaseType}, {@code database} and + * {@code port} fields. */ public final void setDefaults() { if (databaseType == DatabaseType.MYSQL) { @@ -151,19 +157,6 @@ public class Credentials implements Serializable { } } - /** - * The class name of the RDBMS driver. - */ - public String getDatabaseDriverClass() { - switch (getDatabaseType()) { - case MYSQL: - return "com.mysql.jdbc.Driver"; - case POSTGRES: - return "org.postgresql.Driver"; - } - return null; - } - @Override public String toString() { return String.format("[%s] type=%s, hostname=%s, port=%s, username=%s, password=%s, database=%s", diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/DBBroker.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/DBBroker.java index 1c723f361300053ced074b8abad3d717276a251a..0c20470a5c19ab0df016d90059bbe375a0d4ccab 100644 --- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/DBBroker.java +++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/DBBroker.java @@ -37,25 +37,77 @@ import java.util.Map; import java.util.Set; /** + * This interface can be seen as a DAO (Data Access Object pattern), however it + * has been called more generically a "broker to the database", because it + * doesn't map exactly the CRUD operations, indeed it contains some specific + * methods for interacting to the databases (executing SQL statement) and + * retrieving/storing data regarding TAP SCHEMA. Generic operations are + * implemented inside the abstract class {@link DBBrokerTemplate}. The latter is + * then extended by specific MySQL and Postgres Implementations. * * @author Sonia Zorba {@literal <zorba at oats.inaf.it>} */ public interface DBBroker { + /** + * Returns the name of all schemata contained into the source database. + */ List<String> getAllSchemaNames() throws SQLException; + /** + * Returns the name of all schemata which structure is compatible with a + * TAP_SCHEMA schema structure. + */ List<String> getAllTAPSchemaNames(List<String> allSchemas) throws SQLException; + /** + * Try to guess the version of an existing TAP_SCHEMA analyzing its shallow + * structure (e.<!-- -->g.<!-- --> the presence of the set of columns + * defined into the related XML model). + * + * @return the name of the guessed TAP_SCHEMA version. + */ String detectVersion(String tapSchemaName) throws SQLException; + /** + * Returns a list of all the schemata exposed by an existing TAP_SCHEMA. + * Queries the {@code TAP_SCHEMA.schemas} schema. + */ List<String> getExposedSchemas(String tapSchemaName) throws SQLException; + /** + * Returns all the tables owned by a schema, given its name. + */ List<String> getAllTablesNames(String schemaName) throws SQLException; + /** + * Returns the table type ("table" or "view") for all the tables owned by a + * schema, given its name. + * + * @return a {@code Map} having table names as keys and table types as + * values. + */ Map<String, String> getAllTableTypes(String schemaName) throws SQLException; + /** + * Returns the list of the names of the columns contained in a given table. + */ List<String> getAllColumnsNames(String schemaName, String tableName) throws SQLException; + /** + * Returns the metadata of all the columns contained in a given table. + * + * @param schemaName the name of the schema. + * @param tableSimpleName the name of the table. + * @param tableModel the {@link TableModel} of the owner column if it is a + * TAP_SCHEMA table or the ObsCore table, null otherwise. This is used for + * consistency checking on these tables datatype. + * @param dataTypeMode the {@link DataTypeMode} used in the selected + * TAP_SCHEMA version; this is used only if the previous parameter is not + * null. + * @return a {@code Map} having the column names as keys and the column + * metadata as values. + */ Map<String, Map<String, Object>> getAllColumnsMetadata(String schemaName, String tableSimpleName, TableModel tableModel, DataTypeMode dataTypeMode) throws SQLException; List<Key> getKeys(TapSchema tapSchema, String schemaName, String realSchemaName) throws SQLException; diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/DBWrapper.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/DBWrapper.java index bddca27e8cc149820dcca2bf7dcdfc0f108e90ea..70a63857b9d0323fa580ed488757f6c06713a432 100644 --- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/DBWrapper.java +++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/DBWrapper.java @@ -31,12 +31,16 @@ import org.slf4j.LoggerFactory; /** * This class is used to silently manage the possibility to have separate data - * sources for the TAP_SCHEMA schema and it source schema (the schema from which - * it takes the information).<br> - * An API user asks, for example, {@link getSourceDataSource()}, and the - * <code>DBWrapper</code> returns the correct <code>DataSource</code>, both if - * it is separated from the TAP_SCHEMA <code>DataSource</code> or if they are - * the same object. + * sources for the TAP_SCHEMA schema and its <em>source</em> schema (the schema + * from which it takes the information, that is the schema containing the + * astronomical data). Also the {@code ivoa} schema, containing the + * {@code ObsCore} table, is stored into the source database (because one could + * perform SQL JOINS between astronomical data schemata and the ObsCore table). + * <p> + * An user asks, for example, {@link getSourceDataSource()}, and the + * {@code DBWrapper} returns the correct {@code DataSource}, both if it is + * separated from the TAP_SCHEMA {@code DataSource} or if they are the same + * object. * * @author Sonia Zorba {@literal <zorba at oats.inaf.it>} */ @@ -45,10 +49,10 @@ public class DBWrapper implements Serializable { private static final long serialVersionUID = 1721030677924066695L; private final static Logger LOG = LoggerFactory.getLogger(DBWrapper.class); - // Same credentials + // Same credentials (this is null if the credentials are separated) private DataSourceWrapper dataSourceWrapper; - // Separated credentials + // Separated credentials (these are null if the credentials are the same) private DataSourceWrapper sourceDataSourceWrapper; private DataSourceWrapper tapSchemaDataSourceWrapper; @@ -121,19 +125,22 @@ public class DBWrapper implements Serializable { } /** - * @return true if the TAP_SCHEMA <code>DataSource</code> is different from - * its source <code>DataSource</code>, false otherwise. + * Tells if the {@code DataSource}s for the TAP_SCHEMA and its source are + * different. + * + * @return true if the TAP_SCHEMA {@code DataSource} is different from its + * source {@code DataSource}, false otherwise. */ public boolean isSeparatedSources() { return dataSourceWrapper == null; } /** - * Test both the connection to the TAP_SCHEMA <code>DataSource</code> and - * its source <code>DataSource</code>. + * Test both the connection to the TAP_SCHEMA {@code DataSource} and its + * source {@code DataSource}. * * @throws SQLException if it is not possible to connect to the - * <code>DataSource</code>. + * {@code DataSource}. */ public void testConnections() throws SQLException { Connection connection;