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 96cf36cda44a777db5ec33f4fa520628cdeed57f..c17bc66b05883a16fe6112a821d63c1dd2bba4f3 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 @@ -22,6 +22,8 @@ */ package it.inaf.ia2.tsm; +import it.inaf.ia2.tsm.model.TableModel; +import it.inaf.ia2.tsm.model.TypesMapping; import java.util.Objects; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -63,6 +65,22 @@ public class Column extends ChildEntity<Table> { setStatus(Status.LOADED); } + private void overrideDataTypeFromModels() { + + Schema parentSchema = parentTable.getParent(); + String type = null; + + if (tapSchema.getName().equals(parentSchema.getName())) { + TableModel tableModel = tapSchema.getTapSchemaModel().get(parentTable.getName()); + type = tableModel.get(getName()).getType(); + } + + if (type != null) { + String compatibleType = TypesMapping.getCompatibleADQLType(type, tapSchema.getVersion()); + getProperty(DATATYPE_KEY).init(compatibleType); + } + } + public Key getForeignKey() { if (!foreignKeySearched) { // lazy loading (but the foreignKey value can be null, so we use this boolean) diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/EntityProperty.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/EntityProperty.java index beade83be0c2fd0d88c701b08f6a783a8d9af5e6..0a5ff261eda1c781ca971ec3577b315dc182a370 100644 --- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/EntityProperty.java +++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/EntityProperty.java @@ -22,7 +22,7 @@ */ package it.inaf.ia2.tsm; -import it.inaf.ia2.tsm.model.PropertyModel; +import it.inaf.ia2.tsm.model.ColumnModel; import java.io.Serializable; /** @@ -35,7 +35,7 @@ public class EntityProperty<T> implements Serializable { private static final long serialVersionUID = 6735553751078589085L; - private PropertyModel propertyModel; + private ColumnModel propertyModel; private Class<T> type; private T originalValue; private T value; @@ -44,7 +44,7 @@ public class EntityProperty<T> implements Serializable { private EntityProperty() { } - public EntityProperty(PropertyModel propertyModel, T defaultValue) { + public EntityProperty(ColumnModel propertyModel, T defaultValue) { this.propertyModel = propertyModel; this.type = propertyModel.getJavaType(); this.init(defaultValue); 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 83f24761313c1fee582211a371b5976226a8a703..64dc3fafe62c3e5306683a2beb49a54ee1577890 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 @@ -23,6 +23,7 @@ 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; @@ -56,6 +57,17 @@ public class Table extends ChildEntity<Schema> implements EntitiesContainer<Colu super(); } + private TableModel getModel() { + if (tapSchema.getName().equals(parentSchema.getName())) { + return tapSchema.getTapSchemaModel().get(simpleName); + } + if (tapSchema.isHasObscore() && parentSchema.getName().equals("ivoa") + && simpleName.equals("obscore")) { + return tapSchema.getIvoaSchemaModel().get(simpleName); + } + return null; + } + protected Table(TapSchema tapSchema, Schema schema, String tableSimpleName) throws SQLException { super(tapSchema, tapSchema.getTableModel(TapSchema.TABLES_TABLE), schema.getTableMetadata(tableSimpleName)); @@ -65,7 +77,7 @@ public class Table extends ChildEntity<Schema> implements EntitiesContainer<Colu columns = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); DBBroker broker = tapSchema.getDBBroker(schema.getName()); - columnsMetadata = broker.getAllColumnsMetadata(schema.getName(), tableSimpleName); + columnsMetadata = broker.getAllColumnsMetadata(schema.getName(), tableSimpleName, getModel(), tapSchema.getVersion()); 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); 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 740b28d84762a28815e4bb3c92ef2bf1ea48ea30..8de787d24d37bf274192d25986237f0703407fb0 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 @@ -25,7 +25,7 @@ package it.inaf.ia2.tsm; import it.inaf.ia2.tsm.datalayer.DBBroker; import it.inaf.ia2.tsm.datalayer.DBBrokerFactory; import it.inaf.ia2.tsm.datalayer.DBWrapper; -import it.inaf.ia2.tsm.model.PropertyModel; +import it.inaf.ia2.tsm.model.ColumnModel; import it.inaf.ia2.tsm.model.TableModel; import it.inaf.ia2.tsm.model.SchemaModel; import it.inaf.ia2.tsm.model.SchemaModels; @@ -427,7 +427,7 @@ public class TapSchema implements EntitiesContainer<Schema>, Serializable { schemas.put(schemaName, null); } - private SchemaModel getIvoaSchemaModel() { + public SchemaModel getIvoaSchemaModel() { if (obscore) { return SchemaModels.getIvoaSchemaModel(obscoreVersion); } @@ -686,6 +686,10 @@ public class TapSchema implements EntitiesContainer<Schema>, Serializable { return value ? 1 : 0; } + public boolean isHasObscore() { + return obscore; + } + /** * Fill descriptions of the TAP_SCHEMA schema entities for a given * SchemaModel (TAP_SCHEMA or ivoa). @@ -700,7 +704,7 @@ public class TapSchema implements EntitiesContainer<Schema>, Serializable { for (TableModel tableModel : schemaModel.getTables().values()) { Table table = schema.getChild(tableModel.getName()); table.setValue(DESCRIPTION_KEY, tableModel.getDescription()); - for (PropertyModel propertyModel : tableModel.getProperties().values()) { + for (ColumnModel propertyModel : tableModel.getColumns()) { Column column = table.getChild(propertyModel.getName()); column.setValue(DESCRIPTION_KEY, propertyModel.getDescription()); column.setValue(Column.UCD_KEY, propertyModel.getUcd()); diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/TapSchemaEntity.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/TapSchemaEntity.java index 825d53e40b0e74d9e1aed26cd051346e4d6d1848..b1f684e04739a210c6a698623a1d578d4ba4e29c 100644 --- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/TapSchemaEntity.java +++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/TapSchemaEntity.java @@ -22,7 +22,7 @@ */ package it.inaf.ia2.tsm; -import it.inaf.ia2.tsm.model.PropertyModel; +import it.inaf.ia2.tsm.model.ColumnModel; import it.inaf.ia2.tsm.model.TableModel; import java.io.Serializable; import java.util.ArrayList; @@ -64,7 +64,7 @@ public abstract class TapSchemaEntity implements Serializable { } private void fillProperties() { - for (PropertyModel propModel : tableModel.getProperties().values()) { + for (ColumnModel propModel : tableModel.getColumns()) { Object defaultValue = null; if (propModel.getLoaderKey() != null) { defaultValue = metadata.get(propModel.getLoaderKey()); 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 e9b3543d3c5c6e4bd73b2b014bb7a80a6dd074ee..558df20f3b64948815e885c834e41990ab5253c2 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 @@ -52,7 +52,7 @@ public interface DBBroker { List<String> getAllColumnsNames(String schemaName, String tableName) throws SQLException; - Map<String, Map<String, Object>> getAllColumnsMetadata(String schemaName, String tableSimpleName) throws SQLException; + Map<String, Map<String, Object>> getAllColumnsMetadata(String schemaName, String tableSimpleName, TableModel tableModel, String tapSchemaVersion) throws SQLException; List<Key> getKeys(TapSchema tapSchema, String schemaName) throws SQLException; diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/DBBrokerTemplate.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/DBBrokerTemplate.java index 31cd078c2dd3ef80c25ded8723d3c2766c9fbd43..2218db2db6c0139b4b5848b002f22de1eca88d0c 100644 --- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/DBBrokerTemplate.java +++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/DBBrokerTemplate.java @@ -32,7 +32,7 @@ import it.inaf.ia2.tsm.Table; import it.inaf.ia2.tsm.TapSchema; import it.inaf.ia2.tsm.TapSchemaEntity; import it.inaf.ia2.tsm.UpdateOperations; -import it.inaf.ia2.tsm.model.PropertyModel; +import it.inaf.ia2.tsm.model.ColumnModel; import it.inaf.ia2.tsm.model.TableModel; import it.inaf.ia2.tsm.model.SchemaModel; import it.inaf.ia2.tsm.model.SchemaModels; @@ -403,12 +403,12 @@ public abstract class DBBrokerTemplate implements DBBroker { StringBuilder querySb = new StringBuilder("SELECT "); boolean first = true; - for (PropertyModel pm : tableModel.getProperties().values()) { + for (ColumnModel cm : tableModel.getColumns()) { if (!first) { querySb.append(", "); } first = false; - querySb.append(escape(pm.getName())); + querySb.append(escape(cm.getName())); } querySb.append(" FROM "); @@ -431,9 +431,9 @@ public abstract class DBBrokerTemplate implements DBBroker { while (rs.next()) { Map<String, Object> item = new HashMap<>(); - for (PropertyModel pm : tableModel.getProperties().values()) { - Object value = TSMUtil.getObject(rs, pm.getName(), pm.getJavaType()); - item.put(pm.getName(), value); + for (ColumnModel cm : tableModel.getColumns()) { + Object value = TSMUtil.getObject(rs, cm.getName(), cm.getJavaType()); + item.put(cm.getName(), value); } items.add(item); @@ -655,10 +655,10 @@ public abstract class DBBrokerTemplate implements DBBroker { } private boolean match(TableModel tableModel, List<String> columns) { - if (tableModel.getProperties().size() != columns.size()) { + if (tableModel.getColumns().size() != columns.size()) { return false; } - for (PropertyModel propertyModel : tableModel.getProperties().values()) { + for (ColumnModel propertyModel : tableModel.getColumns()) { String columnName = propertyModel.getName(); if (!columns.contains(columnName)) { return false; @@ -767,6 +767,30 @@ public abstract class DBBrokerTemplate implements DBBroker { return allColumns; } + protected abstract Map<String, Map<String, Object>> getAllColumnsOriginalMetadata(String schemaName, String tableName) throws SQLException; + + @Override + public Map<String, Map<String, Object>> getAllColumnsMetadata(String schemaName, String tableName, TableModel tableModel, String tapSchemaVersion) throws SQLException { + + Map<String, Map<String, Object>> metadata = getAllColumnsOriginalMetadata(schemaName, tableName); + + // Overriding data type from models + if (tableModel != null) { + for (Map.Entry<String, Map<String, Object>> entry : metadata.entrySet()) { + String columnName = entry.getKey(); + String declaredDataType = tableModel.get(columnName).getType(); + String compatibleType = TypesMapping.getCompatibleADQLType(declaredDataType, tapSchemaVersion); + Integer size = (Integer) entry.getValue().get(Column.SIZE_KEY); + if (size != null) { + compatibleType += String.format("(%s)", size); + } + entry.getValue().put(Column.DATATYPE_KEY, compatibleType); + } + } + + return metadata; + } + protected String getTapSchemaVersion() { return tapSchemaVersion; } diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/mysql/MySQLDBBroker.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/mysql/MySQLDBBroker.java index f3b8475b490a605e83cabf016c60a583ce5638fd..d4d3123063dace2e910cc4d3e62b27f592f1aa2e 100644 --- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/mysql/MySQLDBBroker.java +++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/mysql/MySQLDBBroker.java @@ -27,7 +27,7 @@ import it.inaf.ia2.tsm.Key; import it.inaf.ia2.tsm.TapSchema; import it.inaf.ia2.tsm.datalayer.ADQL; import it.inaf.ia2.tsm.datalayer.DBBrokerTemplate; -import it.inaf.ia2.tsm.model.PropertyModel; +import it.inaf.ia2.tsm.model.ColumnModel; import it.inaf.ia2.tsm.model.TableModel; import it.inaf.ia2.tsm.model.TypesMapping; import java.sql.Connection; @@ -85,7 +85,7 @@ public class MySQLDBBroker extends DBBrokerTemplate { } @Override - public Map<String, Map<String, Object>> getAllColumnsMetadata(String schemaName, String tableName) throws SQLException { + public Map<String, Map<String, Object>> getAllColumnsOriginalMetadata(String schemaName, String tableName) throws SQLException { Map<String, Map<String, Object>> allColumnsMetadata = new HashMap<>(); @@ -155,22 +155,22 @@ public class MySQLDBBroker extends DBBrokerTemplate { querySb.append(" (\n"); boolean first = true; - for (PropertyModel pm : tableModel.getProperties().values()) { + for (ColumnModel cm : tableModel.getColumns()) { if (!first) { querySb.append(",\n"); } first = false; - querySb.append(pm.getName()); + querySb.append(cm.getName()); querySb.append(" "); - String mySQLType = TypesMapping.getMySQLTypeFromADQLType(pm.getType()); + String mySQLType = TypesMapping.getMySQLTypeFromADQLType(cm.getType()).toUpperCase(); querySb.append(mySQLType); - if (pm.getType().equals(ADQL.VARCHAR.name()) || pm.getType().equals(ADQL.CHAR.name())) { - appendSize(querySb, pm.getSize()); + if (mySQLType.equals("VARCHAR") || mySQLType.equals("CHAR")) { + appendSize(querySb, cm.getSize()); } - if (pm.isNullable()) { + if (cm.isNullable()) { querySb.append(" NULL"); } else { querySb.append(" NOT NULL"); diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/pgsql/PostgresDBBroker.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/pgsql/PostgresDBBroker.java index 7c9b26e7a6c8dde90b95f7e329605341f628ae09..cf7b01798f8da24d6ad01be01a88a4abf256aa29 100644 --- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/pgsql/PostgresDBBroker.java +++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/datalayer/pgsql/PostgresDBBroker.java @@ -27,7 +27,7 @@ import it.inaf.ia2.tsm.Key; import it.inaf.ia2.tsm.TapSchema; import it.inaf.ia2.tsm.datalayer.ADQL; import it.inaf.ia2.tsm.datalayer.DBBrokerTemplate; -import it.inaf.ia2.tsm.model.PropertyModel; +import it.inaf.ia2.tsm.model.ColumnModel; import it.inaf.ia2.tsm.model.TableModel; import it.inaf.ia2.tsm.model.TypesMapping; import java.sql.Connection; @@ -48,66 +48,65 @@ import org.slf4j.LoggerFactory; * @author Sonia Zorba {@literal <zorba at oats.inaf.it>} */ public class PostgresDBBroker extends DBBrokerTemplate { - + private final static Logger LOG = LoggerFactory.getLogger(PostgresDBBroker.class); - + private final String pgDatabaseName; - + public PostgresDBBroker(DataSource dataSource, String pgDatabaseName, String tapSchemaVersion) { super(dataSource, '"', tapSchemaVersion); this.pgDatabaseName = pgDatabaseName; } - + @Override protected void createTable(String schemaName, TableModel tableModel, Connection conn) throws SQLException { StringBuilder querySb = new StringBuilder(); - + querySb.append("CREATE TABLE IF NOT EXISTS "); querySb.append(escape(schemaName)); querySb.append("."); querySb.append(escape(tableModel.getName())); querySb.append(" (\n"); - + boolean first = true; - for (PropertyModel pm : tableModel.getProperties().values()) { + for (ColumnModel cm : tableModel.getColumns()) { if (!first) { querySb.append(",\n"); } first = false; - - querySb.append(pm.getName()); + + querySb.append(cm.getName()); querySb.append(" "); - - String pgsqlType = TypesMapping.getPostgresSQLTypeFromADQLType(pm.getType()); + + String pgsqlType = TypesMapping.getPostgresSQLTypeFromADQLType(cm.getType()).toLowerCase(); querySb.append(pgsqlType); - if (pm.getType().equals(ADQL.VARCHAR.name()) - || pm.getType().equals(ADQL.CHAR.name())) { - appendSize(querySb, pm.getSize()); + if (pgsqlType.equals("character varying") || pgsqlType.equals("character")) { + appendSize(querySb, cm.getSize()); } - - if (pm.isNullable()) { + + if (cm.isNullable()) { querySb.append(" NULL"); } else { querySb.append(" NOT NULL"); } } - + querySb.append(")"); - + String query = querySb.toString(); - + try (Statement stat = conn.createStatement()) { LOG.debug("Executing query: {}", query); stat.executeUpdate(query); } } - + @Override protected String getAddPrimaryKeyQuery(String tapSchemaName, String tableName, String[] keyColumns) { return String.format("ALTER TABLE ONLY %s.%s ADD CONSTRAINT %s_pkey PRIMARY KEY (%s)", escape(tapSchemaName), escape(tableName), tableName, buildColumnsList(keyColumns)); } - + @Override protected String getAddForeignKeyQuery(String tapSchemaName, String tableName, String[] fromKeyColumns, String targetTableName, String[] toKeyColumns) { // Building univocal constraint name @@ -120,12 +119,12 @@ public class PostgresDBBroker extends DBBrokerTemplate { escape(tapSchemaName), escape(tableName), constraintNameSb.toString(), buildColumnsList(fromKeyColumns), escape(tapSchemaName), escape(targetTableName), buildColumnsList(toKeyColumns)); } - + @Override protected String getCreateDatabaseQuery(String databaseName) { return "CREATE SCHEMA IF NOT EXISTS " + escape(databaseName); } - + @Override protected String getSchemaTablesQuery(String schemaName) { return String.format("SELECT tablename FROM pg_catalog.pg_tables where schemaname = '%s'", schemaName); @@ -145,14 +144,14 @@ public class PostgresDBBroker extends DBBrokerTemplate { } return sb.toString(); } - + @Override - public Map<String, Map<String, Object>> getAllColumnsMetadata(String schemaName, String tableSimpleName) throws SQLException { - + public Map<String, Map<String, Object>> getAllColumnsOriginalMetadata(String schemaName, String tableSimpleName) throws SQLException { + Map<String, Map<String, Object>> allColumnsMetadata = new HashMap<>(); - + StringBuilder querySb = new StringBuilder(); - + querySb.append("SELECT c.column_name, c.data_type, pg_catalog.format_type(a.atttypid, a.atttypmod), r.contype AS column_type, c.character_maximum_length, c.numeric_precision, a.attndims AS arraydim\n"); querySb.append("FROM information_schema.columns c\n"); querySb.append("JOIN pg_catalog.pg_tables t ON c.table_schema = t.schemaname AND c.table_name = t.tablename\n"); @@ -163,16 +162,16 @@ public class PostgresDBBroker extends DBBrokerTemplate { querySb.append("' AND t.tablename = '"); querySb.append(tableSimpleName); querySb.append("'"); - + String query = querySb.toString(); LOG.debug("Executing query {}", query); - + try (Connection conn = dataSource.getConnection(); Statement statement = conn.createStatement(); ResultSet resultSet = statement.executeQuery(query)) { - + while (resultSet.next()) { - + Map<String, Object> cm = new HashMap<>(); // Column name @@ -193,11 +192,11 @@ public class PostgresDBBroker extends DBBrokerTemplate { } cm.put(Column.PRIMARY_KEY, primaryKey); cm.put(Column.INDEXED_KEY, indexed); - + Integer size = null; int arraydimension = 0; String datatype; - + String type = resultSet.getString("data_type").toUpperCase(); boolean isArray = false; if ("ARRAY".equals(type)) { @@ -209,7 +208,7 @@ public class PostgresDBBroker extends DBBrokerTemplate { // numbers inside brakets, so this case will be approximated to *x* arraydimension = resultSet.getInt("arraydim"); } - + datatype = TypesMapping.getADQLTypeFromPostgresType(type, getTapSchemaVersion()); if (!isArray && (datatype.equals(ADQL.VARCHAR.name()) || datatype.equals(ADQL.CHAR.name()))) { size = resultSet.getInt("character_maximum_length"); @@ -218,10 +217,10 @@ public class PostgresDBBroker extends DBBrokerTemplate { // Adding size at the end of datatype datatype += String.format("(%s)", size); } - + cm.put(Column.DATATYPE_KEY, datatype); cm.put(Column.SIZE_KEY, size); - + String arraySize = null; if (isArray) { arraySize = formatArraySize(arraydimension); @@ -232,21 +231,21 @@ public class PostgresDBBroker extends DBBrokerTemplate { arraySize += "*"; } } - + cm.put(Column.ARRAYSIZE_KEY, arraySize); - + allColumnsMetadata.put(columnName, cm); } } - + return allColumnsMetadata; } - + @Override public List<Key> getKeys(TapSchema tapSchema, String schemaName) throws SQLException { - + StringBuilder queryKeysSb = new StringBuilder(); - + queryKeysSb.append("SELECT\n"); queryKeysSb.append("conname AS constraint_name,\n"); queryKeysSb.append("conrelid::regclass AS from_table, \n"); @@ -259,33 +258,33 @@ public class PostgresDBBroker extends DBBrokerTemplate { queryKeysSb.append("OR (confrelid::regclass || '' LIKE '"); queryKeysSb.append(schemaName); queryKeysSb.append(".%'))"); - + String queryKeys = queryKeysSb.toString(); - + try (Connection connection = dataSource.getConnection(); Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery(queryKeys)) { - + LOG.debug("Executing query {}", queryKeys); - + List<Key> keys = new ArrayList<>(); while (resultSet.next()) { - + String constraintName = resultSet.getString("constraint_name"); - + String fromTableCompleteName = resultSet.getString("from_table"); String targetTableCompleteName = resultSet.getString("target_table"); - + String fromSchema = fromTableCompleteName.split(Pattern.quote("."))[0]; String targetSchema = targetTableCompleteName.split(Pattern.quote("."))[0]; - + Map<String, Object> keyMetadata = new HashMap<>(); keyMetadata.put(Key.FROM_TABLE_KEY, fromTableCompleteName); keyMetadata.put(Key.TARGET_TABLE_KEY, targetTableCompleteName); - + Key key = new Key(tapSchema, keyMetadata); keys.add(key); - + StringBuilder queryFromKCSb = new StringBuilder(); queryFromKCSb.append("SELECT\n"); queryFromKCSb.append("c.column_name AS key_column\n"); @@ -303,7 +302,7 @@ public class PostgresDBBroker extends DBBrokerTemplate { // conkey conrelid String queryFromKC = queryFromKCSb.toString(); - + StringBuilder queryTargetKCSb = new StringBuilder(); queryTargetKCSb.append("SELECT\n"); queryTargetKCSb.append("c.column_name AS key_column\n"); @@ -321,16 +320,16 @@ public class PostgresDBBroker extends DBBrokerTemplate { // as above, but with confkey and confrelid and different c.table_schema where condition String queryTargetKC = queryTargetKCSb.toString(); - + try (Statement statFromKC = connection.createStatement(); Statement statTargetKC = connection.createStatement()) { - + try (ResultSet rsFromKC = statFromKC.executeQuery(queryFromKC); ResultSet rsTargetKC = statTargetKC.executeQuery(queryTargetKC)) { - + LOG.debug("Executing query {}", queryFromKC); LOG.debug("Executing query {}", queryTargetKC); - + while (rsFromKC.next()) { if (rsTargetKC.next()) { key.addKeyColumn( @@ -342,11 +341,11 @@ public class PostgresDBBroker extends DBBrokerTemplate { } } } - + return keys; } } - + @Override protected String getTableTypesQuery(String schemaName) { StringBuilder sb = new StringBuilder(); @@ -362,18 +361,18 @@ public class PostgresDBBroker extends DBBrokerTemplate { sb.append("'"); return sb.toString(); } - + @Override protected String getColumnNamesQuery(String tapSchemaName, String tableName) { return String.format("SELECT column_name FROM information_schema.columns WHERE table_schema = '%s' AND table_name = '%s'", tapSchemaName, tableName); } - + @Override protected String getAllSchemaNamesQuery() { return "SELECT schema_name FROM information_schema.schemata"; } - + @Override protected String getAllTablesNamesQuery(String schemaName) { return String.format("SELECT tablename FROM pg_catalog.pg_tables where schemaname = '%s'", schemaName); diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/PropertyModel.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/ColumnModel.java similarity index 98% rename from TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/PropertyModel.java rename to TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/ColumnModel.java index d41f6f7a90e46a8cd3a8c137af4f27aaf41773d6..3a7346b1822fa4661a4c24dbc1ad4c4421bf058d 100644 --- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/PropertyModel.java +++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/ColumnModel.java @@ -30,7 +30,7 @@ import javax.xml.bind.annotation.XmlTransient; * * @author Sonia Zorba {@literal <zorba at oats.inaf.it>} */ -public class PropertyModel implements Serializable { +public class ColumnModel implements Serializable { private static final long serialVersionUID = -982004697900839996L; @@ -49,7 +49,7 @@ public class PropertyModel implements Serializable { private String unit; private boolean principal; - public PropertyModel() { + public ColumnModel() { // default values updatable = true; nullable = true; diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/TableXMLModel.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/ModelLoadingException.java similarity index 56% rename from TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/TableXMLModel.java rename to TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/ModelLoadingException.java index 090899436592e279cc831f60bc1ab3f933fe9927..d50d2475b2f6207e94ed3e9e0cab632b12e2d43b 100644 --- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/TableXMLModel.java +++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/ModelLoadingException.java @@ -22,46 +22,19 @@ */ package it.inaf.ia2.tsm.model; -import java.util.List; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlElementWrapper; - /** * * @author Sonia Zorba {@literal <zorba at oats.inaf.it>} */ -public class TableXMLModel { - - private String name; - private String description; - private List<PropertyModel> add; +public class ModelLoadingException extends RuntimeException { - @XmlAttribute(name = "name") - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - @XmlAttribute(name = "description") - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } + private static final long serialVersionUID = -2602498963656896783L; - @XmlElementWrapper(name = "add") - @XmlElement(name = "property") - public List<PropertyModel> getAdd() { - return add; + public ModelLoadingException(String message) { + super(message); } - public void setAdd(List<PropertyModel> add) { - this.add = add; + public ModelLoadingException(Throwable t) { + super(t); } } diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/SchemaModel.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/SchemaModel.java index 59499c0bb23ead0f00c185181b6d158f0823a82d..b5162f32104b9ea49edec63e8904a57ac0479e5f 100644 --- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/SchemaModel.java +++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/SchemaModel.java @@ -25,43 +25,70 @@ package it.inaf.ia2.tsm.model; import java.io.Serializable; import java.util.HashMap; import java.util.Map; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElements; +import javax.xml.bind.annotation.XmlRootElement; /** * * @author Sonia Zorba {@literal <zorba at oats.inaf.it>} */ +@XmlRootElement(name = "schema") public class SchemaModel implements Serializable { private static final long serialVersionUID = 1087876778125446000L; private final Map<String, TableModel> tables; + private String name; private String version; + private String extendsFrom; private String description; - private SchemaModel() { + public SchemaModel() { tables = new HashMap<>(); } - public SchemaModel(SchemaXMLModel xmlModel) { - this(); - this.name = xmlModel.getName(); - this.version = xmlModel.getVersion(); - this.description = xmlModel.getDescription(); - } - + @XmlAttribute(name = "name") public String getName() { return name; } + public void setName(String name) { + this.name = name; + } + + @XmlAttribute(name = "version") public String getVersion() { return version; } + public void setVersion(String version) { + this.version = version; + } + + @XmlAttribute(name = "extends") + public String getExtendsFrom() { + return extendsFrom; + } + + public void setExtendsFrom(String extendsFrom) { + this.extendsFrom = extendsFrom; + } + + @XmlAttribute(name = "description") public String getDescription() { return description; } + public void setDescription(String description) { + this.description = description; + } + + @XmlElements({ + @XmlElement(name = "table") + }) public Map<String, TableModel> getTables() { return tables; } diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/SchemaModels.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/SchemaModels.java index 6458b40344bd9af22c2376aa0bce737d4f387919..be1ea870e8fbe8dd48a4c78ce7976ba562366db3 100644 --- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/SchemaModels.java +++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/SchemaModels.java @@ -26,11 +26,9 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; -import javax.xml.bind.JAXB; /** * @@ -51,93 +49,35 @@ public class SchemaModels { static { try { - String[] xmlModelFileNames = getXMLModelFileNames(); - List<SchemaXMLModel> xmlModels = getXmlModels(xmlModelFileNames); + Properties properties = getCoreProperties(); - Map<String, SchemaXMLModel> tapSchemaXmlModelsMap = getXmlModelMapByVersionAndName(xmlModels, TAP_SCHEMA_NAME); - Map<String, SchemaXMLModel> ivoaSchemaXmlModelsMap = getXmlModelMapByVersionAndName(xmlModels, IVOA_SCHEMA_NAME); + String[] tapSchemaModelFiles = getXMLModelFileNames(properties, "tap_schema_models"); + String[] ivoaModelFiles = getXMLModelFileNames(properties, "ivoa_schema_models"); - TAP_SCHEMA_MODELS = getModelMapByVersion(tapSchemaXmlModelsMap); - IVOA_SCHEMA_MODELS = getModelMapByVersion(ivoaSchemaXmlModelsMap); + TAP_SCHEMA_MODELS = new XMLModelsLoader(tapSchemaModelFiles).load(); + IVOA_SCHEMA_MODELS = new XMLModelsLoader(ivoaModelFiles).load(); } catch (IOException e) { throw new ExceptionInInitializerError(e); } } - private static String[] getXMLModelFileNames() throws IOException { + private static Properties getCoreProperties() throws IOException { + Properties props = new Properties(); try (InputStream in = SchemaModels.class.getClassLoader().getResourceAsStream("core.properties")) { - - Properties props = new Properties(); props.load(in); - - String[] fileNames = props.getProperty("schema_definition_files").split(","); - - String[] modelFiles = new String[fileNames.length]; - for (int i = 0; i < fileNames.length; i++) { - modelFiles[i] = String.format("%s%s%s", SCHEMA_DEFINITION_FOLDER, File.separator, fileNames[i]); - } - - return modelFiles; } + return props; } - private static List<SchemaXMLModel> getXmlModels(String[] xmlModelFileNames) throws IOException { - List<SchemaXMLModel> xmlModels = new ArrayList<>(); + private static String[] getXMLModelFileNames(Properties props, String propertyKey) throws IOException { + String[] fileNames = props.getProperty(propertyKey).split(","); - for (String modelFile : xmlModelFileNames) { - try (InputStream in = SchemaModels.class.getClassLoader().getResourceAsStream(modelFile)) { - SchemaXMLModel model = JAXB.unmarshal(in, SchemaXMLModel.class); - xmlModels.add(model); - } + String[] modelFiles = new String[fileNames.length]; + for (int i = 0; i < fileNames.length; i++) { + modelFiles[i] = String.format("%s%s%s", SCHEMA_DEFINITION_FOLDER, File.separator, fileNames[i].trim()); } - return xmlModels; - } - - private static void loadSchemaModel(SchemaModel model, SchemaXMLModel xmlModel, Map<String, SchemaXMLModel> xmlModels) { - - for (TableXMLModel tableXmlModel : xmlModel.getTables()) { - String tableName = tableXmlModel.getName(); - TableModel tableModel = model.get(tableName); - if (tableModel == null) { - tableModel = new TableModel(tableXmlModel); - } - for (PropertyModel property : tableXmlModel.getAdd()) { - if (tableModel.getProperties().get(property.getName()) == null) { - // Add property only if it didn't exist in child structure - // this allows to override properties in children - tableModel.getProperties().put(property.getName(), property); - } - } - model.getTables().put(tableName, tableModel); - } - - if (xmlModel.getExtendsFrom() != null) { - SchemaXMLModel parentModel = xmlModels.get(xmlModel.getExtendsFrom()); - loadSchemaModel(model, parentModel, xmlModels); - } - } - - private static Map<String, SchemaXMLModel> getXmlModelMapByVersionAndName(List<SchemaXMLModel> xmlModels, String schemaName) { - Map<String, SchemaXMLModel> map = new HashMap<>(); - - for (SchemaXMLModel xmlModel : xmlModels) { - if (schemaName.equals(xmlModel.getName())) { - map.put(xmlModel.getVersion(), xmlModel); - } - } - - return map; - } - - private static Map<String, SchemaModel> getModelMapByVersion(Map<String, SchemaXMLModel> xmlModels) { - Map<String, SchemaModel> map = new HashMap<>(); - for (SchemaXMLModel xmlModel : xmlModels.values()) { - SchemaModel model = new SchemaModel(xmlModel); - loadSchemaModel(model, xmlModel, xmlModels); - map.put(model.getVersion(), model); - } - return map; + return modelFiles; } public static SchemaModel getTapSchemaModel(String version) { diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/SchemaXMLModel.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/SchemaXMLModel.java deleted file mode 100644 index 6f7e1103d917a4f5b0c45f9e8ec27fb68b72caa4..0000000000000000000000000000000000000000 --- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/SchemaXMLModel.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * _____________________________________________________________________________ - * - * INAF - OATS National Institute for Astrophysics - Astronomical Observatory of - * Trieste INAF - IA2 Italian Center for Astronomical Archives - * _____________________________________________________________________________ - * - * Copyright (C) 2017 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.model; - -import java.util.List; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlElements; -import javax.xml.bind.annotation.XmlRootElement; - -/** - * - * @author Sonia Zorba {@literal <zorba at oats.inaf.it>} - */ -@XmlRootElement(name = "schema") -public class SchemaXMLModel { - - - private String name; - private String version; - private String description; - private String extendsFrom; - private List<TableXMLModel> tables; - - @XmlAttribute(name = "name") - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - @XmlAttribute(name = "version") - public String getVersion() { - return version; - } - - public void setVersion(String version) { - this.version = version; - } - - @XmlAttribute(name = "description") - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - @XmlAttribute(name = "extends") - public String getExtendsFrom() { - return extendsFrom; - } - - public void setExtendsFrom(String extendsFrom) { - this.extendsFrom = extendsFrom; - } - - @XmlElements({ - @XmlElement(name = "table") - }) - public List<TableXMLModel> getTables() { - return tables; - } - - public void setTables(List<TableXMLModel> tables) { - this.tables = tables; - } -} diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/TableModel.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/TableModel.java index b926357a800651afab12df019494012eeacbb17d..41ee999e874e4dad43c9ac79227dd96278b21e6b 100644 --- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/TableModel.java +++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/TableModel.java @@ -23,8 +23,12 @@ package it.inaf.ia2.tsm.model; import java.io.Serializable; -import java.util.HashMap; -import java.util.Map; +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElements; +import javax.xml.bind.annotation.XmlTransient; /** * @@ -34,33 +38,45 @@ public class TableModel implements Serializable { private static final long serialVersionUID = 5142593924738484037L; - private final Map<String, PropertyModel> properties; + private final List<ColumnModel> columns; private String name; private String description; - private TableModel() { - this.properties = new HashMap<>(); - } - - public TableModel(TableXMLModel xmlModel) { - this(); - this.name = xmlModel.getName(); - this.description = xmlModel.getDescription(); + public TableModel() { + this.columns = new ArrayList<>(); } + @XmlAttribute(name = "name") public String getName() { return name; } - public Map<String, PropertyModel> getProperties() { - return properties; + public void setName(String name) { + this.name = name; } - public PropertyModel get(String columnName) { - return properties.get(columnName); + @XmlElements({ + @XmlElement(name = "column") + }) + public List<ColumnModel> getColumns() { + return columns; } + @XmlAttribute(name = "description") public String getDescription() { return description; } + + public void setDescription(String description) { + this.description = description; + } + + public ColumnModel get(String columnName) { + for (ColumnModel column : columns) { + if (columnName.equals(column.getName())) { + return column; + } + } + return null; + } } diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/TypesMapping.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/TypesMapping.java index 0e18be9a0f7a75d42813a4b9b33e21a2ca77b0bb..cf341f51405e67674a8df2aa300038f6becc156b 100644 --- a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/TypesMapping.java +++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/TypesMapping.java @@ -75,14 +75,14 @@ public class TypesMapping { return typeMapping; } } - throw new IllegalArgumentException("Unable to retrieve mapping for ADQL type " + adqlType); + return null; } /** * returns an ADQL type String compatible with older TAP_SCHEMA versions * (for older versions "adql:" prefix is needed). */ - private static String getCompatibleADQLType(String adqlType, String tapSchemaVersion) { + public static String getCompatibleADQLType(String adqlType, String tapSchemaVersion) { if (tapSchemaVersion.startsWith("1.0")) { return ADQL_PREFIX + adqlType; } @@ -90,15 +90,27 @@ public class TypesMapping { } public static Class getClassFromAdqlType(String adqlType) { - return getTypeMappingFromADQLType(adqlType).getJavaType(); + TypeMapping typeMapping = getTypeMappingFromADQLType(adqlType); + if (typeMapping == null) { + return String.class; + } + return typeMapping.getJavaType(); } public static String getMySQLTypeFromADQLType(String adqlType) { - return getTypeMappingFromADQLType(adqlType).getMySQLType(); + TypeMapping typeMapping = getTypeMappingFromADQLType(adqlType); + if (typeMapping == null) { + return "VARCHAR"; + } + return typeMapping.getMySQLType(); } public static String getPostgresSQLTypeFromADQLType(String adqlType) { - return getTypeMappingFromADQLType(adqlType).getPgsqlType(); + TypeMapping typeMapping = getTypeMappingFromADQLType(adqlType); + if (typeMapping == null) { + return "character varying"; + } + return typeMapping.getPgsqlType(); } private static String getADQLTypeFromPostgresType(String pgsqlType) { diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/XMLMerger.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/XMLMerger.java new file mode 100644 index 0000000000000000000000000000000000000000..a90212e8e9047bfb72f7c1b019bd3eea74e319ed --- /dev/null +++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/XMLMerger.java @@ -0,0 +1,175 @@ +/* + * _____________________________________________________________________________ + * + * INAF - OATS National Institute for Astrophysics - Astronomical Observatory of + * Trieste INAF - IA2 Italian Center for Astronomical Archives + * _____________________________________________________________________________ + * + * Copyright (C) 2017 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.model; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Attr; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +/** + * + * @author Sonia Zorba {@literal <zorba at oats.inaf.it>} + */ +public class XMLMerger { + + private static final Logger LOG = LoggerFactory.getLogger(XMLMerger.class); + + private final Document parentDoc; + private final Document childDoc; + + XMLMerger(Document parentDoc, Document childDoc) throws ParserConfigurationException { + // Cloning parent document + this.parentDoc = cloneDocument(parentDoc); + this.childDoc = childDoc; + } + + private Document cloneDocument(Document document) throws ParserConfigurationException { + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder = dbf.newDocumentBuilder(); + Document clonedDocument = builder.newDocument(); + Node originalRoot = document.getDocumentElement(); + Node clonedRoot = clonedDocument.importNode(originalRoot, true); + clonedDocument.appendChild(clonedRoot); + return clonedDocument; + } + + public Document getMergedDocument() { + + Element root = parentDoc.getDocumentElement(); + Element inheritingRoot = childDoc.getDocumentElement(); + + // Adding attributes for root node + addAttributes(root, inheritingRoot); + // visit recursively + visitAndModifyTree(root, inheritingRoot); + + return parentDoc; + } + + private List<Element> getChildElements(Element parent) { + List<Element> elements = new ArrayList<>(); + NodeList nodes = parent.getChildNodes(); + for (int i = 0; i < nodes.getLength(); i++) { + Node node = nodes.item(i); + if (node instanceof Element) { + elements.add((Element) node); + } + } + return elements; + } + + private void visitAndModifyTree(Element inheritedParentEl, Element inheritingParentEl) { + if (inheritedParentEl != null) { + for (Element inheritingChildEl : getChildElements(inheritingParentEl)) { + Element inheritedElement = checkElement(inheritedParentEl, inheritingChildEl); + visitAndModifyTree(inheritedElement, inheritingChildEl); + } + } + } + + private Element checkElement(Element inheritedParent, Element child) { + + String name = child.getAttribute("name"); + Element inheritedElement = findElementByNameAttribute(inheritedParent, name); + + if (child.getNodeName().equals("remove")) { + if (inheritedElement != null) { + // Remove node by name + inheritedParent.removeChild(inheritedElement); + } else { + LOG.warn("Unable to remove element {}: no such element in parent", name); + } + } else { + if (inheritedElement == null) { + // Add new node + Node importedChild = parentDoc.importNode(child, true); + inheritedParent.appendChild(importedChild); + } else { + // Apply inheritance (override node) + applyElementInheritance(inheritedElement, child); + } + } + + return inheritedElement; + } + + private Element findElementByNameAttribute(Element parent, String name) { + for (Element element : getChildElements(parent)) { + if (name.equals(element.getAttribute("name"))) { + return element; + } + } + return null; + } + + private void addAttributes(Element inheritedElement, Element inheritingElement) { + NamedNodeMap attrs = inheritingElement.getAttributes(); + for (int i = 0; i < attrs.getLength(); i++) { + Node node = attrs.item(i); + if (node instanceof Attr) { + Attr attr = (Attr) node; + inheritedElement.setAttribute(attr.getName(), attr.getValue()); + } + } + } + + private void applyElementInheritance(Element inheritedElement, Element inheritingElement) { + + addAttributes(inheritedElement, inheritingElement); + + for (Element child : getChildElements(inheritingElement)) { + List<Element> subChildren = getChildElements(child); + // apply element-to-element override only in leaf nodes + if (subChildren.isEmpty()) { + Element childToReplace = findElement(inheritedElement, child); + Node importedChild = parentDoc.importNode(child, true); + if (childToReplace == null) { + if (!child.getNodeName().equals("remove")) { + inheritedElement.appendChild(importedChild); + } + } else { + inheritedElement.replaceChild(importedChild, childToReplace); + } + } + } + } + + private Element findElement(Element parent, Element childToFind) { + for (Element element : getChildElements(parent)) { + if (element.getNodeName().equals(childToFind.getNodeName())) { + return element; + } + } + return null; + } +} diff --git a/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/XMLModelsLoader.java b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/XMLModelsLoader.java new file mode 100644 index 0000000000000000000000000000000000000000..017f8afc0f0e7de9a46d678d9f6ef339b2cce330 --- /dev/null +++ b/TASMAN-core/src/main/java/it/inaf/ia2/tsm/model/XMLModelsLoader.java @@ -0,0 +1,184 @@ +/* + * _____________________________________________________________________________ + * + * INAF - OATS National Institute for Astrophysics - Astronomical Observatory of + * Trieste INAF - IA2 Italian Center for Astronomical Archives + * _____________________________________________________________________________ + * + * Copyright (C) 2017 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.model; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import javax.xml.bind.JAXB; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.dom.DOMSource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.xml.sax.SAXException; + +/** + * + * @author Sonia Zorba {@literal <zorba at oats.inaf.it>} + */ +public class XMLModelsLoader { + + private static final Logger LOG = LoggerFactory.getLogger(XMLModelsLoader.class); + + private final String[] xmlModelFileNames; + // key: doc version + private final Map<String, Document> documents; + private final Map<String, String> inheritanceGraph; + private final Map<Integer, List<Document>> inheritanceLevels; + + public XMLModelsLoader(String[] xmlModelFileNames) { + this.xmlModelFileNames = xmlModelFileNames; + this.documents = new HashMap<>(); + inheritanceGraph = new HashMap<>(); + inheritanceLevels = new HashMap<>(); + } + + public Map<String, SchemaModel> load() { + return load(XMLModelsLoader.class.getClassLoader()); + } + + public Map<String, SchemaModel> load(ClassLoader classLoader) { + + try { + + loadDocumentsMap(classLoader); + + // It is necessary to apply inheritance in specific level order. (Example: + // if v2 extends from v1 and v1 extends from v0 it is necessary to merge v1 + // with v0 first and then merge the result with v2). + // So this inheritance data structures are built. + buildInheritanceGraph(); + buildInheritanceLevels(); + + for (int i = 0; i < inheritanceLevels.size(); i++) { + for (Document doc : inheritanceLevels.get(i)) { + applyInheritance(doc, null); + } + } + + return getModelsMap(); + + } catch (IOException | ParserConfigurationException | SAXException e) { + throw new ModelLoadingException(e); + } + } + + private void loadDocumentsMap(ClassLoader classLoader) throws IOException, SAXException, ParserConfigurationException { + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder = dbf.newDocumentBuilder(); + + for (String xmlModelFileName : xmlModelFileNames) { + try (InputStream in = classLoader.getResourceAsStream(xmlModelFileName)) { + Document doc = builder.parse(in); + Element root = doc.getDocumentElement(); + String version = root.getAttribute("version"); + // TODO: XML Model validation + + // Documents loaded in a single XMLModelsLoader instance must + // have different versions. + assert documents.get(version) == null; + documents.put(version, doc); + } + } + } + + private void buildInheritanceGraph() { + for (Document document : documents.values()) { + Element root = document.getDocumentElement(); + String version = root.getAttribute("version"); + String extendsFrom = root.getAttribute("extends"); + if (extendsFrom == null || extendsFrom.isEmpty()) { + extendsFrom = null; + } + inheritanceGraph.put(version, extendsFrom); + } + } + + private void buildInheritanceLevels() { + for (Document document : documents.values()) { + String version = document.getDocumentElement().getAttribute("version"); + int level = getInheritanceLevel(version, 0); + List<Document> levelDocs = inheritanceLevels.get(level); + if (levelDocs == null) { + levelDocs = new ArrayList<>(); + inheritanceLevels.put(level, levelDocs); + } + levelDocs.add(document); + } + } + + private int getInheritanceLevel(String version, int count) { + String inheritsFrom = inheritanceGraph.get(version); + if (inheritsFrom == null) { + return count; + } else { + return getInheritanceLevel(inheritsFrom, count + 1); + } + } + + private void applyInheritance(Document doc, Set<String> applied) throws ParserConfigurationException { + String version = doc.getDocumentElement().getAttribute("version"); + String inheritFrom = inheritanceGraph.get(version); + if (inheritFrom != null) { + if (applied == null) { + applied = new HashSet<>(); + } + if (!applied.contains(inheritFrom)) { + Document inheritedDocument = documents.get(inheritFrom); + XMLMerger merger = new XMLMerger(inheritedDocument, doc); + Document merged = merger.getMergedDocument(); + documents.put(version, merged); + applied.add(inheritFrom); + applyInheritance(merged, applied); + } + } + } + + /** + * Public exposed only for testing. + */ + public Map<String, Document> getDocuments() { + return documents; + } + + private Map<String, SchemaModel> getModelsMap() { + Map<String, SchemaModel> models = new HashMap<>(); + + for (Map.Entry<String, Document> entry : documents.entrySet()) { + DOMSource source = new DOMSource(entry.getValue().getDocumentElement()); + SchemaModel model = JAXB.unmarshal(source, SchemaModel.class); + models.put(entry.getKey(), model); + } + + return models; + } +} diff --git a/TASMAN-core/src/main/resources/core.properties b/TASMAN-core/src/main/resources/core.properties index 6defa839f02585e6060b3f543af51bce3549f8a7..04ce0c68cf2d0fe3bea40de4d4b41c90718f49b1 100644 --- a/TASMAN-core/src/main/resources/core.properties +++ b/TASMAN-core/src/main/resources/core.properties @@ -3,4 +3,5 @@ # Comma separated list of files inside schema_definition folder. # (It is necessary to put this list here because, unfortunately, there is no # easy way to read an entire resource folder using the ClassLoader API). -schema_definition_files = ivoa-1_1.xml,tap_schema-1-IA2.xml,tap_schema-1.xml,tap_schema-1_1.xml +tap_schema_models = tap_schema-1-IA2.xml,tap_schema-1.xml,tap_schema-1_1.xml +ivoa_schema_models = ivoa-1_1.xml diff --git a/TASMAN-core/src/main/resources/schema_definition/ivoa-1_1.xml b/TASMAN-core/src/main/resources/schema_definition/ivoa-1_1.xml index 6f3e50d4f6246c408c70f77bc97be27275b36e42..0e740183f14180d7b9790d05701d64b5a8ca0e7f 100644 --- a/TASMAN-core/src/main/resources/schema_definition/ivoa-1_1.xml +++ b/TASMAN-core/src/main/resources/schema_definition/ivoa-1_1.xml @@ -23,734 +23,732 @@ Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. --> <schema name="ivoa" version="1.1"> <table name="obscore"> - <add> - <property> - <name>dataproduct_type</name> - <type>VARCHAR</type> - <size>255</size> - <updatable>true</updatable> - <description>Logical data product type (image etc.)</description> - <standard>true</standard> - <mandatory>true</mandatory> - <utype>ObsDataset.dataProductType</utype> - <ucd>meta.id</ucd> - <principal>true</principal> - </property> - <property> - <name>dataproduct_subtype</name> - <type>VARCHAR</type> - <size>255</size> - <updatable>true</updatable> - <description>Data product specific type</description> - <standard>true</standard> - <mandatory>false</mandatory> - <utype>ObsDataset.dataProductSubtype</utype> - <ucd>meta.id</ucd> - <principal>true</principal> - </property> - <property> - <name>calib_level</name> - <type>INTEGER</type> - <updatable>true</updatable> - <nullable>false</nullable> - <description>Calibration level {0, 1, 2, 3, 4}</description> - <standard>true</standard> - <mandatory>true</mandatory> - <utype>ObsDataset.calibLevel</utype> - <ucd>meta.code;obs.calib</ucd> - <principal>true</principal> - </property> - <property> - <name>obs_collection</name> - <type>VARCHAR</type> - <size>255</size> - <updatable>true</updatable> - <nullable>false</nullable> - <description>Name of the data collection</description> - <standard>true</standard> - <mandatory>true</mandatory> - <utype>DataID.collection</utype> - <ucd>meta.id</ucd> - <principal>true</principal> - </property> - <property> - <name>obs_id</name> - <type>VARCHAR</type> - <size>255</size> - <updatable>true</updatable> - <nullable>false</nullable> - <description>Internal ID given by the ObsTAP service</description> - <standard>true</standard> - <mandatory>true</mandatory> - <utype>DataID.observationID</utype> - <ucd>meta.id</ucd> - <principal>true</principal> - </property> - <property> - <name>obs_title</name> - <type>VARCHAR</type> - <size>255</size> - <updatable>true</updatable> - <description>Brief description of dataset in free format</description> - <standard>true</standard> - <mandatory>false</mandatory> - <utype>DataID.title</utype> - <ucd>meta.title;obs</ucd> - <principal>true</principal> - </property> - <property> - <name>obs_creation_date</name> - <type>TIMESTAMP</type> - <updatable>true</updatable> - <description>Date when the dataset was created</description> - <standard>true</standard> - <mandatory>false</mandatory> - <utype>DataID.date</utype> - <ucd>time;meta.dataset</ucd> - <principal>true</principal> - </property> - <property> - <name>obs_creator_name</name> - <type>VARCHAR</type> - <size>255</size> - <updatable>true</updatable> - <description>Name of the creator of the data</description> - <standard>true</standard> - <mandatory>false</mandatory> - <utype>DataID.creator</utype> - <ucd>meta.id</ucd> - <principal>true</principal> - </property> - <property> - <name>obs_creator_did</name> - <type>VARCHAR</type> - <size>255</size> - <updatable>true</updatable> - <description>IVOA dataset identifier given by the creator</description> - <standard>true</standard> - <mandatory>false</mandatory> - <utype>DataID.creatorDID</utype> - <ucd>meta.id</ucd> - <principal>false</principal> - </property> - <property> - <name>obs_release_date</name> - <type>TIMESTAMP</type> - <updatable>true</updatable> - <description>Observation release date (ISO 8601)</description> - <standard>true</standard> - <mandatory>false</mandatory> - <utype>Curation.releaseDate</utype> - <ucd>time.release</ucd> - <principal>true</principal> - </property> - <property> - <name>publisher_id</name> - <type>VARCHAR</type> - <size>255</size> - <updatable>true</updatable> - <description>IVOA-ID for the Publisher</description> - <standard>true</standard> - <mandatory>false</mandatory> - <utype>Curation.publisherID</utype> - <ucd>meta.ref.uri;meta.curation</ucd> - <principal>true</principal> - </property> - <property> - <name>bib_reference</name> - <type>VARCHAR</type> - <size>255</size> - <updatable>true</updatable> - <description>Service bibliographic reference</description> - <standard>true</standard> - <mandatory>false</mandatory> - <utype>Curation.reference</utype> - <ucd>meta.bib</ucd> - <principal>false</principal> - </property> - <property> - <name>data_rights</name> - <type>VARCHAR</type> - <size>255</size> - <updatable>true</updatable> - <description>Public/Secure/Proprietary</description> - <standard>true</standard> - <mandatory>false</mandatory> - <utype>Curation.rights</utype> - <ucd>meta.code</ucd> - <principal>false</principal> - </property> - <property> - <name>obs_publisher_did</name> - <type>VARCHAR</type> - <size>255</size> - <updatable>true</updatable> - <nullable>false</nullable> - <description>Dataset identifier given by the publisher</description> - <standard>true</standard> - <mandatory>true</mandatory> - <utype>Curation.publisherDID</utype> - <ucd>meta.ref.uri;meta.curation</ucd> - <principal>true</principal> - </property> - <property> - <name>access_url</name> - <type>CLOB</type> - <size>255</size> - <updatable>true</updatable> - <description>URL used to access (download) dataset</description> - <standard>true</standard> - <mandatory>true</mandatory> - <utype>Access.reference</utype> - <ucd>meta.ref.url</ucd> - <principal>true</principal> - </property> - <property> - <name>access_format</name> - <type>VARCHAR</type> - <size>255</size> - <updatable>true</updatable> - <description>Content format of the dataset</description> - <standard>true</standard> - <mandatory>true</mandatory> - <utype>Access.format</utype> - <ucd>meta.code.mime</ucd> - <principal>true</principal> - </property> - <property> - <name>access_estsize</name> - <type>BIGINT</type> - <updatable>true</updatable> - <description>Estimated size of dataset in kilo bytes</description> - <standard>true</standard> - <unit>kbyte</unit> - <mandatory>true</mandatory> - <utype>Access.size</utype> - <unit>kbyte</unit> - <ucd>phys.size;meta.file</ucd> - <principal>true</principal> - </property> - <property> - <name>target_name</name> - <type>VARCHAR</type> - <size>255</size> - <updatable>true</updatable> - <description>Astronomical object observed, if any</description> - <standard>true</standard> - <mandatory>true</mandatory> - <utype>Target.name</utype> - <ucd>meta.id;src</ucd> - <principal>true</principal> - </property> - <property> - <name>target_class</name> - <type>VARCHAR</type> - <size>255</size> - <updatable>true</updatable> - <description>Class of the Target object as in SSA</description> - <standard>true</standard> - <mandatory>false</mandatory> - <utype>Target.class</utype> - <ucd>src.class</ucd> - <principal>true</principal> - </property> - <property> - <name>s_ra</name> - <type>DOUBLE</type> - <updatable>true</updatable> - <description>Central Spatial Position in ICRS Right ascension</description> - <standard>true</standard> - <unit>deg</unit> - <mandatory>true</mandatory> - <utype>Char.SpatialAxis.Coverage.Location.Coord.Position2D.Value2.C1</utype> - <unit>deg</unit> - <ucd>pos.eq.ra</ucd> - <principal>true</principal> - </property> - <property> - <name>s_dec</name> - <type>DOUBLE</type> - <updatable>true</updatable> - <description>Central Spatial Position in ICRS Declination</description> - <standard>true</standard> - <unit>deg</unit> - <mandatory>true</mandatory> - <utype>Char.SpatialAxis.Coverage.Location.Coord.Position2D.Value2.C2</utype> - <unit>deg</unit> - <ucd>pos.eq.dec</ucd> - <principal>true</principal> - </property> - <property> - <name>s_fov</name> - <type>DOUBLE</type> - <updatable>true</updatable> - <description>Estimated size of the covered region as the diameter of a containing circle</description> - <standard>true</standard> - <unit>deg</unit> - <mandatory>true</mandatory> - <utype>Char.SpatialAxis.Coverage.Bounds.Extent.diameter</utype> - <unit>deg</unit> - <ucd>phys.angSize;instr.fov</ucd> - <principal>true</principal> - </property> - <property> - <name>s_region</name> - <type>VARCHAR</type> - <size>255</size> - <updatable>true</updatable> - <description>Sky region covered by the data product (expressed in ICRS frame)</description> - <standard>true</standard> - <mandatory>true</mandatory> - <utype>Char.SpatialAxis.Coverage.Support.Area</utype> - <ucd>pos.outline;obs.field</ucd> - <principal>true</principal> - </property> - <property> - <name>s_xel1</name> - <type>BIGINT</type> - <updatable>true</updatable> - <description>Number of elements along the first coordinate of the spatial axis</description> - <standard>true</standard> - <mandatory>true</mandatory> - <utype>Char.SpatialAxis.numBins1</utype> - <ucd>meta.number</ucd> - <principal>true</principal> - </property> - <property> - <name>s_xel2</name> - <type>BIGINT</type> - <updatable>true</updatable> - <description>Number of elements along the second coordinate of the spatial axis</description> - <standard>true</standard> - <mandatory>true</mandatory> - <utype>Char.SpatialAxis.numBins2</utype> - <ucd>meta.number</ucd> - <principal>true</principal> - </property> - <property> - <name>s_ucd</name> - <type>VARCHAR</type> - <size>255</size> - <updatable>true</updatable> - <description>UCD for the nature of the spatial axis (pos or u,v data)</description> - <standard>true</standard> - <mandatory>false</mandatory> - <utype>Char.SpatialAxis.ucd</utype> - <ucd>meta.ucd</ucd> - <principal>true</principal> - </property> - <property> - <name>s_unit</name> - <type>VARCHAR</type> - <size>255</size> - <updatable>true</updatable> - <description>Unit used for spatial axis</description> - <standard>true</standard> - <mandatory>false</mandatory> - <utype>Char.SpatialAxis.unit</utype> - <ucd>meta.unit</ucd> - <principal>true</principal> - </property> - <property> - <name>s_resolution</name> - <type>DOUBLE</type> - <updatable>true</updatable> - <description>Spatial resolution of data as FWHM of PSF</description> - <standard>true</standard> - <mandatory>true</mandatory> - <utype>Char.SpatialAxis.Resolution.refval.value</utype> - <unit>arcsec</unit> - <ucd>pos.angResolution</ucd> - <principal>true</principal> - </property> - <property> - <name>s_resolution_min</name> - <type>DOUBLE</type> - <updatable>true</updatable> - <description>Resolution min value on spatial axis (FHWM of PSF)</description> - <standard>true</standard> - <mandatory>false</mandatory> - <utype>Char.SpatialAxis.Resolution.Bounds.Limits.LoLimit</utype> - <unit>arcsec</unit> - <ucd>pos.angResolution;stat.min</ucd> - <principal>true</principal> - </property> - <property> - <name>s_resolution_max</name> - <type>DOUBLE</type> - <updatable>true</updatable> - <description>Resolution max value on spatial axis</description> - <standard>true</standard> - <mandatory>false</mandatory> - <utype>Char.SpatialAxis .Resolution.Bounds.Limits.HiLimit</utype> - <unit>arcsec</unit> - <ucd>pos.angResolution;stat.max</ucd> - <principal>true</principal> - </property> - <property> - <name>s_calib_status</name> - <type>VARCHAR</type> - <size>255</size> - <updatable>true</updatable> - <description>Type of calibration along the spatial axis</description> - <standard>true</standard> - <mandatory>false</mandatory> - <utype>Char.SpatialAxis.calibrationStatus</utype> - <ucd>meta.code.qual</ucd> - <principal>true</principal> - </property> - <property> - <name>s_stat_error</name> - <type>DOUBLE</type> - <updatable>true</updatable> - <description>Astrometric precision along the spatial axis</description> - <standard>true</standard> - <unit>arcsec</unit> - <mandatory>false</mandatory> - <utype>Char.SpatialAxis.Accuracy.StatError.Refval.value</utype> - <unit>arcsec</unit> - <ucd>stat.error;pos.eq</ucd> - <principal>false</principal> - </property> - <property> - <name>s_pixel_scale</name> - <type>DOUBLE</type> - <updatable>true</updatable> - <description>Sampling period in world coordinate units along the spatial axis</description> - <standard>true</standard> - <mandatory>false</mandatory> - <utype>Char.SpatialAxis.Sampling.RefVal.SamplingPeriod</utype> - <unit>arcsec</unit> - <ucd>phys.angSize;instr.pixel</ucd> - <principal>true</principal> - </property> - <property> - <name>t_min</name> - <type>DOUBLE</type> - <updatable>true</updatable> - <description>Start time in MJD</description> - <standard>true</standard> - <unit>d</unit> - <mandatory>true</mandatory> - <utype>Char.TimeAxis.Coverage.Bounds.Limits.StartTime</utype> - <ucd>time.start;obs.exposure</ucd> - <principal>true</principal> - </property> - <property> - <name>t_max</name> - <type>DOUBLE</type> - <updatable>true</updatable> - <description>Stop time in MJD</description> - <standard>true</standard> - <unit>d</unit> - <mandatory>true</mandatory> - <utype>Char.TimeAxis.Coverage.Bounds.Limits.StopTime</utype> - <ucd>time.end;obs.exposure</ucd> - <principal>true</principal> - </property> - <property> - <name>t_exptime</name> - <type>DOUBLE</type> - <updatable>true</updatable> - <description>Total exposure time</description> - <standard>true</standard> - <unit>s</unit> - <mandatory>true</mandatory> - <utype>Char.TimeAxis.Coverage.Support.Extent</utype> - <ucd>time.duration;obs.exposure</ucd> - <principal>true</principal> - </property> - <property> - <name>t_resolution</name> - <type>DOUBLE</type> - <updatable>true</updatable> - <description>Temporal resolution FWHM</description> - <standard>true</standard> - <unit>s</unit> - <mandatory>true</mandatory> - <utype>Char.TimeAxis.Resolution.Refval.valueResolution.Refval.value</utype> - <ucd>time.resolution</ucd> - <principal>true</principal> - </property> - <property> - <name>t_calib_status</name> - <type>VARCHAR</type> - <size>255</size> - <updatable>true</updatable> - <description>Type of time coordinate calibration</description> - <standard>true</standard> - <mandatory>false</mandatory> - <utype>Char.TimeAxis.calibrationStatus</utype> - <ucd>meta.code.qual</ucd> - <principal>false</principal> - </property> - <property> - <name>t_stat_error</name> - <type>DOUBLE</type> - <updatable>true</updatable> - <description>Time coord statistical error</description> - <standard>true</standard> - <mandatory>false</mandatory> - <utype>Char.TimeAxis.Accuracy.StatError.Refval.value</utype> - <unit>s</unit> - <ucd>stat.error;time</ucd> - <principal>false</principal> - </property> - <property> - <name>t_xel</name> - <type>BIGINT</type> - <updatable>true</updatable> - <description>Number of elements along the time axis</description> - <standard>true</standard> - <mandatory>true</mandatory> - <utype>Char.TimeAxis.numBins</utype> - <ucd>meta.number</ucd> - <principal>true</principal> - </property> - <property> - <name>t_refpos</name> - <type>VARCHAR</type> - <size>255</size> - <updatable>true</updatable> - <description>Time Axis Reference Position as defined in STC REC</description> - <standard>true</standard> - <mandatory>false</mandatory> - <utype>Char.TimeAxis.ReferencePosition</utype> - </property> - <property> - <name>em_min</name> - <type>DOUBLE</type> - <updatable>true</updatable> - <description>Start in spectral coordinates</description> - <standard>true</standard> - <unit>m</unit> - <mandatory>true</mandatory> - <utype>Char.SpectralAxis.Coverage.Bounds.Limits.LoLimit</utype> - <ucd>em.wl;stat.min</ucd> - <principal>true</principal> - </property> - <property> - <name>em_max</name> - <type>DOUBLE</type> - <updatable>true</updatable> - <description>Stop in spectral coordinates</description> - <standard>true</standard> - <unit>m</unit> - <mandatory>true</mandatory> - <utype>Char.SpectralAxis.Coverage.Bounds.Limits.HiLimit</utype> - <ucd>em.wl;stat.max</ucd> - <principal>true</principal> - </property> - <property> - <name>em_res_power</name> - <type>DOUBLE</type> - <updatable>true</updatable> - <description>Value of the resolving power along the spectral axis. (R)</description> - <standard>true</standard> - <mandatory>true</mandatory> - <utype>Char.SpectralAxis.Resolution.ResolPower.refVal</utype> - <ucd>spect.resolution</ucd> - <principal>true</principal> - </property> - <property> - <name>em_res_power_min</name> - <type>DOUBLE</type> - <updatable>true</updatable> - <description>Resolving power min value on spectral axis</description> - <standard>true</standard> - <mandatory>false</mandatory> - <utype>Char.SpectralAxis.Resolution.ResolPower.LoLimit</utype> - <ucd>spect.resolution;stat.min</ucd> - <principal>true</principal> - </property> - <property> - <name>em_res_power_max</name> - <type>DOUBLE</type> - <updatable>true</updatable> - <description>Resolving power max value on spectral axis</description> - <standard>true</standard> - <mandatory>false</mandatory> - <utype>Char.SpectralAxis.Resolution.ResolPower.HiLimit</utype> - <ucd>spect.resolution;stat.max</ucd> - <principal>true</principal> - </property> - <property> - <name>em_resolution</name> - <type>DOUBLE</type> - <updatable>true</updatable> - <description>Value of Resolution along the spectral axis</description> - <standard>true</standard> - <mandatory>false</mandatory> - <utype>Char.SpectralAxis.Resolution.Refval.value</utype> - <unit>m</unit> - <ucd>spect.resolution;stat.mean</ucd> - <principal>true</principal> - </property> - <property> - <name>em_stat_error</name> - <type>DOUBLE</type> - <updatable>true</updatable> - <description>Spectral coord statistical error</description> - <standard>true</standard> - <mandatory>false</mandatory> - <utype>Char.SpectralAxis.Accuracy.StatError.Refval.value</utype> - <unit>m</unit> - <ucd>stat.error;em</ucd> - <principal>false</principal> - </property> - <property> - <name>em_xel</name> - <type>BIGINT</type> - <updatable>true</updatable> - <description>Number of elements along the spectral axis</description> - <standard>true</standard> - <mandatory>true</mandatory> - <utype>Char.SpectralAxis.numBins</utype> - <ucd>meta.number</ucd> - </property> - <property> - <name>em_ucd</name> - <type>VARCHAR</type> - <size>255</size> - <updatable>true</updatable> - <description>Nature of the spectral axis</description> - <standard>true</standard> - <mandatory>false</mandatory> - <utype>Char.SpectralAxis.ucd</utype> - <ucd>meta.ucd</ucd> - <principal>true</principal> - </property> - <property> - <name>em_unit</name> - <type>VARCHAR</type> - <size>255</size> - <updatable>true</updatable> - <description>Units along the spectral axis</description> - <standard>true</standard> - <mandatory>false</mandatory> - <utype>Char.SpectralAxis.unit</utype> - <ucd>meta.unit</ucd> - <principal>true</principal> - </property> - <property> - <name>em_calib_status</name> - <type>VARCHAR</type> - <size>255</size> - <updatable>true</updatable> - <description>Type of spectral coord calibration</description> - <standard>true</standard> - <mandatory>false</mandatory> - <utype>Char.SpectralAxis.calibrationStatus</utype> - <ucd>meta.code.qual</ucd> - <principal>false</principal> - </property> - <property> - <name>o_ucd</name> - <type>VARCHAR</type> - <size>255</size> - <updatable>true</updatable> - <description>UCD of the observable axis (e.g. phot.flux.density, phot.count, etc.)</description> - <standard>true</standard> - <mandatory>true</mandatory> - <utype>Char.ObservableAxis.ucd</utype> - <ucd>meta.ucd</ucd> - <principal>true</principal> - </property> - <property> - <name>o_unit</name> - <type>VARCHAR</type> - <size>255</size> - <updatable>true</updatable> - <description>Units used for the observable values</description> - <standard>true</standard> - <mandatory>false</mandatory> - <utype>Char.ObservableAxis.unit</utype> - <ucd>meta.unit</ucd> - <principal>true</principal> - </property> - <property> - <name>o_calib_status</name> - <type>VARCHAR</type> - <size>255</size> - <updatable>true</updatable> - <description>Type of calibration for the observable coordinate</description> - <standard>true</standard> - <mandatory>false</mandatory> - <utype>Char.ObservableAxis.calibrationStatus</utype> - <ucd>meta.code.qual</ucd> - <principal>true</principal> - </property> - <property> - <name>o_stat_error</name> - <type>DOUBLE</type> - <updatable>true</updatable> - <description>Statistical error on the Observable axis</description> - <standard>true</standard> - <mandatory>false</mandatory> - <utype>Char.ObservableAxis.Accuracy.StatError.Refval.value</utype> - <!-- units specified by o_unit --> - <ucd>stat.error;phot.flux</ucd> - <principal>false</principal> - </property> - <property> - <name>pol_states</name> - <type>VARCHAR</type> - <size>255</size> - <updatable>true</updatable> - <description>List of polarization states present in the data file or NULL if not applicable</description> - <standard>true</standard> - <mandatory>true</mandatory> - <utype>Char.PolarizationAxis.stateList</utype> - <ucd>meta.code;phys.polarization</ucd> - <principal>true</principal> - </property> - <property> - <name>pol_xel</name> - <type>BIGINT</type> - <updatable>true</updatable> - <description>Number of elements along the polarization axis</description> - <standard>true</standard> - <mandatory>true</mandatory> - <utype>Char.PolarizationAxis.numBins</utype> - <ucd>meta.number</ucd> - <principal>true</principal> - </property> - <property> - <name>facility_name</name> - <type>VARCHAR</type> - <size>255</size> - <updatable>true</updatable> - <description>Name of the facility used for this observation</description> - <standard>true</standard> - <mandatory>true</mandatory> - <utype>Provenance.ObsConfig.Facility.name</utype> - <ucd>meta.id;instr.tel</ucd> - <principal>true</principal> - </property> - <property> - <name>instrument_name</name> - <type>VARCHAR</type> - <size>255</size> - <updatable>true</updatable> - <description>The name of the instrument used for the observation</description> - <standard>true</standard> - <mandatory>true</mandatory> - <utype>Provenance.ObsConfig.Instrument.name</utype> - <ucd>meta.id;instr</ucd> - <principal>true</principal> - </property> - <property> - <name>proposal_id</name> - <type>VARCHAR</type> - <size>255</size> - <updatable>true</updatable> - <description>Identifier of proposal to which observation belongs</description> - <standard>false</standard> - <mandatory>true</mandatory> - <utype>Provenance.Proposal.identifier</utype> - <ucd>meta.id; obs.proposal</ucd> - <principal>false</principal> - </property> - </add> + <column> + <name>dataproduct_type</name> + <type>VARCHAR</type> + <size>255</size> + <updatable>true</updatable> + <description>Logical data product type (image etc.)</description> + <standard>true</standard> + <mandatory>true</mandatory> + <utype>ObsDataset.dataProductType</utype> + <ucd>meta.id</ucd> + <principal>true</principal> + </column> + <column> + <name>dataproduct_subtype</name> + <type>VARCHAR</type> + <size>255</size> + <updatable>true</updatable> + <description>Data product specific type</description> + <standard>true</standard> + <mandatory>false</mandatory> + <utype>ObsDataset.dataProductSubtype</utype> + <ucd>meta.id</ucd> + <principal>true</principal> + </column> + <column> + <name>calib_level</name> + <type>INTEGER</type> + <updatable>true</updatable> + <nullable>false</nullable> + <description>Calibration level {0, 1, 2, 3, 4}</description> + <standard>true</standard> + <mandatory>true</mandatory> + <utype>ObsDataset.calibLevel</utype> + <ucd>meta.code;obs.calib</ucd> + <principal>true</principal> + </column> + <column> + <name>obs_collection</name> + <type>VARCHAR</type> + <size>255</size> + <updatable>true</updatable> + <nullable>false</nullable> + <description>Name of the data collection</description> + <standard>true</standard> + <mandatory>true</mandatory> + <utype>DataID.collection</utype> + <ucd>meta.id</ucd> + <principal>true</principal> + </column> + <column> + <name>obs_id</name> + <type>VARCHAR</type> + <size>255</size> + <updatable>true</updatable> + <nullable>false</nullable> + <description>Internal ID given by the ObsTAP service</description> + <standard>true</standard> + <mandatory>true</mandatory> + <utype>DataID.observationID</utype> + <ucd>meta.id</ucd> + <principal>true</principal> + </column> + <column> + <name>obs_title</name> + <type>VARCHAR</type> + <size>255</size> + <updatable>true</updatable> + <description>Brief description of dataset in free format</description> + <standard>true</standard> + <mandatory>false</mandatory> + <utype>DataID.title</utype> + <ucd>meta.title;obs</ucd> + <principal>true</principal> + </column> + <column> + <name>obs_creation_date</name> + <type>TIMESTAMP</type> + <updatable>true</updatable> + <description>Date when the dataset was created</description> + <standard>true</standard> + <mandatory>false</mandatory> + <utype>DataID.date</utype> + <ucd>time;meta.dataset</ucd> + <principal>true</principal> + </column> + <column> + <name>obs_creator_name</name> + <type>VARCHAR</type> + <size>255</size> + <updatable>true</updatable> + <description>Name of the creator of the data</description> + <standard>true</standard> + <mandatory>false</mandatory> + <utype>DataID.creator</utype> + <ucd>meta.id</ucd> + <principal>true</principal> + </column> + <column> + <name>obs_creator_did</name> + <type>VARCHAR</type> + <size>255</size> + <updatable>true</updatable> + <description>IVOA dataset identifier given by the creator</description> + <standard>true</standard> + <mandatory>false</mandatory> + <utype>DataID.creatorDID</utype> + <ucd>meta.id</ucd> + <principal>false</principal> + </column> + <column> + <name>obs_release_date</name> + <type>TIMESTAMP</type> + <updatable>true</updatable> + <description>Observation release date (ISO 8601)</description> + <standard>true</standard> + <mandatory>false</mandatory> + <utype>Curation.releaseDate</utype> + <ucd>time.release</ucd> + <principal>true</principal> + </column> + <column> + <name>publisher_id</name> + <type>VARCHAR</type> + <size>255</size> + <updatable>true</updatable> + <description>IVOA-ID for the Publisher</description> + <standard>true</standard> + <mandatory>false</mandatory> + <utype>Curation.publisherID</utype> + <ucd>meta.ref.uri;meta.curation</ucd> + <principal>true</principal> + </column> + <column> + <name>bib_reference</name> + <type>VARCHAR</type> + <size>255</size> + <updatable>true</updatable> + <description>Service bibliographic reference</description> + <standard>true</standard> + <mandatory>false</mandatory> + <utype>Curation.reference</utype> + <ucd>meta.bib</ucd> + <principal>false</principal> + </column> + <column> + <name>data_rights</name> + <type>VARCHAR</type> + <size>255</size> + <updatable>true</updatable> + <description>Public/Secure/Proprietary</description> + <standard>true</standard> + <mandatory>false</mandatory> + <utype>Curation.rights</utype> + <ucd>meta.code</ucd> + <principal>false</principal> + </column> + <column> + <name>obs_publisher_did</name> + <type>VARCHAR</type> + <size>255</size> + <updatable>true</updatable> + <nullable>false</nullable> + <description>Dataset identifier given by the publisher</description> + <standard>true</standard> + <mandatory>true</mandatory> + <utype>Curation.publisherDID</utype> + <ucd>meta.ref.uri;meta.curation</ucd> + <principal>true</principal> + </column> + <column> + <name>access_url</name> + <type>CLOB</type> + <size>255</size> + <updatable>true</updatable> + <description>URL used to access (download) dataset</description> + <standard>true</standard> + <mandatory>true</mandatory> + <utype>Access.reference</utype> + <ucd>meta.ref.url</ucd> + <principal>true</principal> + </column> + <column> + <name>access_format</name> + <type>VARCHAR</type> + <size>255</size> + <updatable>true</updatable> + <description>Content format of the dataset</description> + <standard>true</standard> + <mandatory>true</mandatory> + <utype>Access.format</utype> + <ucd>meta.code.mime</ucd> + <principal>true</principal> + </column> + <column> + <name>access_estsize</name> + <type>BIGINT</type> + <updatable>true</updatable> + <description>Estimated size of dataset in kilo bytes</description> + <standard>true</standard> + <unit>kbyte</unit> + <mandatory>true</mandatory> + <utype>Access.size</utype> + <unit>kbyte</unit> + <ucd>phys.size;meta.file</ucd> + <principal>true</principal> + </column> + <column> + <name>target_name</name> + <type>VARCHAR</type> + <size>255</size> + <updatable>true</updatable> + <description>Astronomical object observed, if any</description> + <standard>true</standard> + <mandatory>true</mandatory> + <utype>Target.name</utype> + <ucd>meta.id;src</ucd> + <principal>true</principal> + </column> + <column> + <name>target_class</name> + <type>VARCHAR</type> + <size>255</size> + <updatable>true</updatable> + <description>Class of the Target object as in SSA</description> + <standard>true</standard> + <mandatory>false</mandatory> + <utype>Target.class</utype> + <ucd>src.class</ucd> + <principal>true</principal> + </column> + <column> + <name>s_ra</name> + <type>DOUBLE</type> + <updatable>true</updatable> + <description>Central Spatial Position in ICRS Right ascension</description> + <standard>true</standard> + <unit>deg</unit> + <mandatory>true</mandatory> + <utype>Char.SpatialAxis.Coverage.Location.Coord.Position2D.Value2.C1</utype> + <unit>deg</unit> + <ucd>pos.eq.ra</ucd> + <principal>true</principal> + </column> + <column> + <name>s_dec</name> + <type>DOUBLE</type> + <updatable>true</updatable> + <description>Central Spatial Position in ICRS Declination</description> + <standard>true</standard> + <unit>deg</unit> + <mandatory>true</mandatory> + <utype>Char.SpatialAxis.Coverage.Location.Coord.Position2D.Value2.C2</utype> + <unit>deg</unit> + <ucd>pos.eq.dec</ucd> + <principal>true</principal> + </column> + <column> + <name>s_fov</name> + <type>DOUBLE</type> + <updatable>true</updatable> + <description>Estimated size of the covered region as the diameter of a containing circle</description> + <standard>true</standard> + <unit>deg</unit> + <mandatory>true</mandatory> + <utype>Char.SpatialAxis.Coverage.Bounds.Extent.diameter</utype> + <unit>deg</unit> + <ucd>phys.angSize;instr.fov</ucd> + <principal>true</principal> + </column> + <column> + <name>s_region</name> + <type>REGION</type> + <size>255</size> + <updatable>true</updatable> + <description>Sky region covered by the data product (expressed in ICRS frame)</description> + <standard>true</standard> + <mandatory>true</mandatory> + <utype>Char.SpatialAxis.Coverage.Support.Area</utype> + <ucd>pos.outline;obs.field</ucd> + <principal>true</principal> + </column> + <column> + <name>s_xel1</name> + <type>BIGINT</type> + <updatable>true</updatable> + <description>Number of elements along the first coordinate of the spatial axis</description> + <standard>true</standard> + <mandatory>true</mandatory> + <utype>Char.SpatialAxis.numBins1</utype> + <ucd>meta.number</ucd> + <principal>true</principal> + </column> + <column> + <name>s_xel2</name> + <type>BIGINT</type> + <updatable>true</updatable> + <description>Number of elements along the second coordinate of the spatial axis</description> + <standard>true</standard> + <mandatory>true</mandatory> + <utype>Char.SpatialAxis.numBins2</utype> + <ucd>meta.number</ucd> + <principal>true</principal> + </column> + <column> + <name>s_ucd</name> + <type>VARCHAR</type> + <size>255</size> + <updatable>true</updatable> + <description>UCD for the nature of the spatial axis (pos or u,v data)</description> + <standard>true</standard> + <mandatory>false</mandatory> + <utype>Char.SpatialAxis.ucd</utype> + <ucd>meta.ucd</ucd> + <principal>true</principal> + </column> + <column> + <name>s_unit</name> + <type>VARCHAR</type> + <size>255</size> + <updatable>true</updatable> + <description>Unit used for spatial axis</description> + <standard>true</standard> + <mandatory>false</mandatory> + <utype>Char.SpatialAxis.unit</utype> + <ucd>meta.unit</ucd> + <principal>true</principal> + </column> + <column> + <name>s_resolution</name> + <type>DOUBLE</type> + <updatable>true</updatable> + <description>Spatial resolution of data as FWHM of PSF</description> + <standard>true</standard> + <mandatory>true</mandatory> + <utype>Char.SpatialAxis.Resolution.refval.value</utype> + <unit>arcsec</unit> + <ucd>pos.angResolution</ucd> + <principal>true</principal> + </column> + <column> + <name>s_resolution_min</name> + <type>DOUBLE</type> + <updatable>true</updatable> + <description>Resolution min value on spatial axis (FHWM of PSF)</description> + <standard>true</standard> + <mandatory>false</mandatory> + <utype>Char.SpatialAxis.Resolution.Bounds.Limits.LoLimit</utype> + <unit>arcsec</unit> + <ucd>pos.angResolution;stat.min</ucd> + <principal>true</principal> + </column> + <column> + <name>s_resolution_max</name> + <type>DOUBLE</type> + <updatable>true</updatable> + <description>Resolution max value on spatial axis</description> + <standard>true</standard> + <mandatory>false</mandatory> + <utype>Char.SpatialAxis.Resolution.Bounds.Limits.HiLimit</utype> + <unit>arcsec</unit> + <ucd>pos.angResolution;stat.max</ucd> + <principal>true</principal> + </column> + <column> + <name>s_calib_status</name> + <type>VARCHAR</type> + <size>255</size> + <updatable>true</updatable> + <description>Type of calibration along the spatial axis</description> + <standard>true</standard> + <mandatory>false</mandatory> + <utype>Char.SpatialAxis.calibrationStatus</utype> + <ucd>meta.code.qual</ucd> + <principal>true</principal> + </column> + <column> + <name>s_stat_error</name> + <type>DOUBLE</type> + <updatable>true</updatable> + <description>Astrometric precision along the spatial axis</description> + <standard>true</standard> + <unit>arcsec</unit> + <mandatory>false</mandatory> + <utype>Char.SpatialAxis.Accuracy.StatError.Refval.value</utype> + <unit>arcsec</unit> + <ucd>stat.error;pos.eq</ucd> + <principal>false</principal> + </column> + <column> + <name>s_pixel_scale</name> + <type>DOUBLE</type> + <updatable>true</updatable> + <description>Sampling period in world coordinate units along the spatial axis</description> + <standard>true</standard> + <mandatory>false</mandatory> + <utype>Char.SpatialAxis.Sampling.RefVal.SamplingPeriod</utype> + <unit>arcsec</unit> + <ucd>phys.angSize;instr.pixel</ucd> + <principal>true</principal> + </column> + <column> + <name>t_min</name> + <type>DOUBLE</type> + <updatable>true</updatable> + <description>Start time in MJD</description> + <standard>true</standard> + <unit>d</unit> + <mandatory>true</mandatory> + <utype>Char.TimeAxis.Coverage.Bounds.Limits.StartTime</utype> + <ucd>time.start;obs.exposure</ucd> + <principal>true</principal> + </column> + <column> + <name>t_max</name> + <type>DOUBLE</type> + <updatable>true</updatable> + <description>Stop time in MJD</description> + <standard>true</standard> + <unit>d</unit> + <mandatory>true</mandatory> + <utype>Char.TimeAxis.Coverage.Bounds.Limits.StopTime</utype> + <ucd>time.end;obs.exposure</ucd> + <principal>true</principal> + </column> + <column> + <name>t_exptime</name> + <type>DOUBLE</type> + <updatable>true</updatable> + <description>Total exposure time</description> + <standard>true</standard> + <unit>s</unit> + <mandatory>true</mandatory> + <utype>Char.TimeAxis.Coverage.Support.Extent</utype> + <ucd>time.duration;obs.exposure</ucd> + <principal>true</principal> + </column> + <column> + <name>t_resolution</name> + <type>DOUBLE</type> + <updatable>true</updatable> + <description>Temporal resolution FWHM</description> + <standard>true</standard> + <unit>s</unit> + <mandatory>true</mandatory> + <utype>Char.TimeAxis.Resolution.Refval.valueResolution.Refval.value</utype> + <ucd>time.resolution</ucd> + <principal>true</principal> + </column> + <column> + <name>t_calib_status</name> + <type>VARCHAR</type> + <size>255</size> + <updatable>true</updatable> + <description>Type of time coordinate calibration</description> + <standard>true</standard> + <mandatory>false</mandatory> + <utype>Char.TimeAxis.calibrationStatus</utype> + <ucd>meta.code.qual</ucd> + <principal>false</principal> + </column> + <column> + <name>t_stat_error</name> + <type>DOUBLE</type> + <updatable>true</updatable> + <description>Time coord statistical error</description> + <standard>true</standard> + <mandatory>false</mandatory> + <utype>Char.TimeAxis.Accuracy.StatError.Refval.value</utype> + <unit>s</unit> + <ucd>stat.error;time</ucd> + <principal>false</principal> + </column> + <column> + <name>t_xel</name> + <type>BIGINT</type> + <updatable>true</updatable> + <description>Number of elements along the time axis</description> + <standard>true</standard> + <mandatory>true</mandatory> + <utype>Char.TimeAxis.numBins</utype> + <ucd>meta.number</ucd> + <principal>true</principal> + </column> + <column> + <name>t_refpos</name> + <type>VARCHAR</type> + <size>255</size> + <updatable>true</updatable> + <description>Time Axis Reference Position as defined in STC REC</description> + <standard>true</standard> + <mandatory>false</mandatory> + <utype>Char.TimeAxis.ReferencePosition</utype> + </column> + <column> + <name>em_min</name> + <type>DOUBLE</type> + <updatable>true</updatable> + <description>Start in spectral coordinates</description> + <standard>true</standard> + <unit>m</unit> + <mandatory>true</mandatory> + <utype>Char.SpectralAxis.Coverage.Bounds.Limits.LoLimit</utype> + <ucd>em.wl;stat.min</ucd> + <principal>true</principal> + </column> + <column> + <name>em_max</name> + <type>DOUBLE</type> + <updatable>true</updatable> + <description>Stop in spectral coordinates</description> + <standard>true</standard> + <unit>m</unit> + <mandatory>true</mandatory> + <utype>Char.SpectralAxis.Coverage.Bounds.Limits.HiLimit</utype> + <ucd>em.wl;stat.max</ucd> + <principal>true</principal> + </column> + <column> + <name>em_res_power</name> + <type>DOUBLE</type> + <updatable>true</updatable> + <description>Value of the resolving power along the spectral axis. (R)</description> + <standard>true</standard> + <mandatory>true</mandatory> + <utype>Char.SpectralAxis.Resolution.ResolPower.refVal</utype> + <ucd>spect.resolution</ucd> + <principal>true</principal> + </column> + <column> + <name>em_res_power_min</name> + <type>DOUBLE</type> + <updatable>true</updatable> + <description>Resolving power min value on spectral axis</description> + <standard>true</standard> + <mandatory>false</mandatory> + <utype>Char.SpectralAxis.Resolution.ResolPower.LoLimit</utype> + <ucd>spect.resolution;stat.min</ucd> + <principal>true</principal> + </column> + <column> + <name>em_res_power_max</name> + <type>DOUBLE</type> + <updatable>true</updatable> + <description>Resolving power max value on spectral axis</description> + <standard>true</standard> + <mandatory>false</mandatory> + <utype>Char.SpectralAxis.Resolution.ResolPower.HiLimit</utype> + <ucd>spect.resolution;stat.max</ucd> + <principal>true</principal> + </column> + <column> + <name>em_resolution</name> + <type>DOUBLE</type> + <updatable>true</updatable> + <description>Value of Resolution along the spectral axis</description> + <standard>true</standard> + <mandatory>false</mandatory> + <utype>Char.SpectralAxis.Resolution.Refval.value</utype> + <unit>m</unit> + <ucd>spect.resolution;stat.mean</ucd> + <principal>true</principal> + </column> + <column> + <name>em_stat_error</name> + <type>DOUBLE</type> + <updatable>true</updatable> + <description>Spectral coord statistical error</description> + <standard>true</standard> + <mandatory>false</mandatory> + <utype>Char.SpectralAxis.Accuracy.StatError.Refval.value</utype> + <unit>m</unit> + <ucd>stat.error;em</ucd> + <principal>false</principal> + </column> + <column> + <name>em_xel</name> + <type>BIGINT</type> + <updatable>true</updatable> + <description>Number of elements along the spectral axis</description> + <standard>true</standard> + <mandatory>true</mandatory> + <utype>Char.SpectralAxis.numBins</utype> + <ucd>meta.number</ucd> + </column> + <column> + <name>em_ucd</name> + <type>VARCHAR</type> + <size>255</size> + <updatable>true</updatable> + <description>Nature of the spectral axis</description> + <standard>true</standard> + <mandatory>false</mandatory> + <utype>Char.SpectralAxis.ucd</utype> + <ucd>meta.ucd</ucd> + <principal>true</principal> + </column> + <column> + <name>em_unit</name> + <type>VARCHAR</type> + <size>255</size> + <updatable>true</updatable> + <description>Units along the spectral axis</description> + <standard>true</standard> + <mandatory>false</mandatory> + <utype>Char.SpectralAxis.unit</utype> + <ucd>meta.unit</ucd> + <principal>true</principal> + </column> + <column> + <name>em_calib_status</name> + <type>VARCHAR</type> + <size>255</size> + <updatable>true</updatable> + <description>Type of spectral coord calibration</description> + <standard>true</standard> + <mandatory>false</mandatory> + <utype>Char.SpectralAxis.calibrationStatus</utype> + <ucd>meta.code.qual</ucd> + <principal>false</principal> + </column> + <column> + <name>o_ucd</name> + <type>VARCHAR</type> + <size>255</size> + <updatable>true</updatable> + <description>UCD of the observable axis (e.g. phot.flux.density, phot.count, etc.)</description> + <standard>true</standard> + <mandatory>true</mandatory> + <utype>Char.ObservableAxis.ucd</utype> + <ucd>meta.ucd</ucd> + <principal>true</principal> + </column> + <column> + <name>o_unit</name> + <type>VARCHAR</type> + <size>255</size> + <updatable>true</updatable> + <description>Units used for the observable values</description> + <standard>true</standard> + <mandatory>false</mandatory> + <utype>Char.ObservableAxis.unit</utype> + <ucd>meta.unit</ucd> + <principal>true</principal> + </column> + <column> + <name>o_calib_status</name> + <type>VARCHAR</type> + <size>255</size> + <updatable>true</updatable> + <description>Type of calibration for the observable coordinate</description> + <standard>true</standard> + <mandatory>false</mandatory> + <utype>Char.ObservableAxis.calibrationStatus</utype> + <ucd>meta.code.qual</ucd> + <principal>true</principal> + </column> + <column> + <name>o_stat_error</name> + <type>DOUBLE</type> + <updatable>true</updatable> + <description>Statistical error on the Observable axis</description> + <standard>true</standard> + <mandatory>false</mandatory> + <utype>Char.ObservableAxis.Accuracy.StatError.Refval.value</utype> + <!-- units specified by o_unit --> + <ucd>stat.error;phot.flux</ucd> + <principal>false</principal> + </column> + <column> + <name>pol_states</name> + <type>VARCHAR</type> + <size>255</size> + <updatable>true</updatable> + <description>List of polarization states present in the data file or NULL if not applicable</description> + <standard>true</standard> + <mandatory>true</mandatory> + <utype>Char.PolarizationAxis.stateList</utype> + <ucd>meta.code;phys.polarization</ucd> + <principal>true</principal> + </column> + <column> + <name>pol_xel</name> + <type>BIGINT</type> + <updatable>true</updatable> + <description>Number of elements along the polarization axis</description> + <standard>true</standard> + <mandatory>true</mandatory> + <utype>Char.PolarizationAxis.numBins</utype> + <ucd>meta.number</ucd> + <principal>true</principal> + </column> + <column> + <name>facility_name</name> + <type>VARCHAR</type> + <size>255</size> + <updatable>true</updatable> + <description>Name of the facility used for this observation</description> + <standard>true</standard> + <mandatory>true</mandatory> + <utype>Provenance.ObsConfig.Facility.name</utype> + <ucd>meta.id;instr.tel</ucd> + <principal>true</principal> + </column> + <column> + <name>instrument_name</name> + <type>VARCHAR</type> + <size>255</size> + <updatable>true</updatable> + <description>The name of the instrument used for the observation</description> + <standard>true</standard> + <mandatory>true</mandatory> + <utype>Provenance.ObsConfig.Instrument.name</utype> + <ucd>meta.id;instr</ucd> + <principal>true</principal> + </column> + <column> + <name>proposal_id</name> + <type>VARCHAR</type> + <size>255</size> + <updatable>true</updatable> + <description>Identifier of proposal to which observation belongs</description> + <standard>false</standard> + <mandatory>true</mandatory> + <utype>Provenance.Proposal.identifier</utype> + <ucd>meta.id; obs.proposal</ucd> + <principal>false</principal> + </column> </table> </schema> diff --git a/TASMAN-core/src/main/resources/schema_definition/tap_schema-1-IA2.xml b/TASMAN-core/src/main/resources/schema_definition/tap_schema-1-IA2.xml index 148c41ea875f60b2737bb9b25516dd104c74d68c..a78aa207a00897c2859f4c72544ee7159230accc 100644 --- a/TASMAN-core/src/main/resources/schema_definition/tap_schema-1-IA2.xml +++ b/TASMAN-core/src/main/resources/schema_definition/tap_schema-1-IA2.xml @@ -23,59 +23,49 @@ Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. --> <schema name="tap_schema" version="1.0-IA2" extends="1.0"> <table name="schemas"> - <add> - <property> - <name>schemaID</name> - <type>BIGINT</type> - <updatable>true</updatable> - <standard>false</standard> - </property> - </add> + <column> + <name>schemaID</name> + <type>BIGINT</type> + <updatable>true</updatable> + <standard>false</standard> + </column> </table> <table name="tables"> - <add> - <property> - <name>tableID</name> - <type>BIGINT</type> - <updatable>true</updatable> - <standard>false</standard> - </property> - </add> + <column> + <name>tableID</name> + <type>BIGINT</type> + <updatable>true</updatable> + <standard>false</standard> + </column> </table> <table name="columns"> - <add> - <property> - <name>columnID</name> - <type>BIGINT</type> - <updatable>true</updatable> - <standard>false</standard> - </property> - <property> - <name>id</name> - <type>INTEGER</type> - <updatable>true</updatable> - <standard>false</standard> - </property> - </add> + <column> + <name>columnID</name> + <type>BIGINT</type> + <updatable>true</updatable> + <standard>false</standard> + </column> + <column> + <name>id</name> + <type>INTEGER</type> + <updatable>true</updatable> + <standard>false</standard> + </column> </table> <table name="keys"> - <add> - <property> - <name>keyID</name> - <type>BIGINT</type> - <updatable>true</updatable> - <standard>false</standard> - </property> - </add> + <column> + <name>keyID</name> + <type>BIGINT</type> + <updatable>true</updatable> + <standard>false</standard> + </column> </table> <table name="key_columns"> - <add> - <property> - <name>key_columnID</name> - <type>BIGINT</type> - <updatable>true</updatable> - <standard>false</standard> - </property> - </add> + <column> + <name>key_columnID</name> + <type>BIGINT</type> + <updatable>true</updatable> + <standard>false</standard> + </column> </table> </schema> diff --git a/TASMAN-core/src/main/resources/schema_definition/tap_schema-1.xml b/TASMAN-core/src/main/resources/schema_definition/tap_schema-1.xml index e8594537ba8db3cbdb3806734d487a768f390d58..fe4786f370c301c4868e2856a0558c9b03eae028 100644 --- a/TASMAN-core/src/main/resources/schema_definition/tap_schema-1.xml +++ b/TASMAN-core/src/main/resources/schema_definition/tap_schema-1.xml @@ -23,261 +23,251 @@ Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. --> <schema name="tap_schema" version="1.0" description="a special schema to describe a TAP tableset"> <table name="schemas" description="description of schemas in this tableset"> - <add> - <property> - <name>schema_name</name> - <type>VARCHAR</type> - <size>64</size> - <updatable>false</updatable> - <nullable>false</nullable> - <key>schema_name</key> - <description>schema name for reference to TAP_SCHEMA.schemas</description> - <standard>true</standard> - </property> - <property> - <name>utype</name> - <type>VARCHAR</type> - <size>255</size> - <updatable>true</updatable> - <description>lists the utypes of schemas in the tableset</description> - <standard>true</standard> - </property> - <property> - <name>description</name> - <type>VARCHAR</type> - <size>255</size> - <updatable>true</updatable> - <description>describes schemas in the tableset</description> - <standard>true</standard> - </property> - </add> + <column> + <name>schema_name</name> + <type>VARCHAR</type> + <size>64</size> + <updatable>false</updatable> + <nullable>false</nullable> + <key>schema_name</key> + <description>schema name for reference to TAP_SCHEMA.schemas</description> + <standard>true</standard> + </column> + <column> + <name>utype</name> + <type>VARCHAR</type> + <size>255</size> + <updatable>true</updatable> + <description>lists the utypes of schemas in the tableset</description> + <standard>true</standard> + </column> + <column> + <name>description</name> + <type>VARCHAR</type> + <size>255</size> + <updatable>true</updatable> + <description>describes schemas in the tableset</description> + <standard>true</standard> + </column> </table> <table name="tables" description="description of tables in this tableset"> - <add> - <property> - <name>schema_name</name> - <type>VARCHAR</type> - <size>64</size> - <updatable>false</updatable> - <nullable>false</nullable> - <key>schema_name</key> - <description>the schema this table belongs to</description> - <standard>true</standard> - </property> - <property> - <name>table_name</name> - <type>VARCHAR</type> - <size>128</size> - <updatable>false</updatable> - <nullable>false</nullable> - <key>table_name</key> - <description>the fully qualified table name</description> - <standard>true</standard> - </property> - <property> - <name>table_type</name> - <size>8</size> - <type>VARCHAR</type> - <updatable>false</updatable> - <key>table_type</key> - <description>one of: table view</description> - <standard>true</standard> - </property> - <property> - <name>utype</name> - <type>VARCHAR</type> - <size>255</size> - <updatable>true</updatable> - <description>lists the utype of tables in the tableset</description> - <standard>true</standard> - </property> - <property> - <name>description</name> - <type>VARCHAR</type> - <size>255</size> - <updatable>true</updatable> - <description>describes tables in the tableset</description> - <standard>true</standard> - </property> - </add> + <column> + <name>schema_name</name> + <type>VARCHAR</type> + <size>64</size> + <updatable>false</updatable> + <nullable>false</nullable> + <key>schema_name</key> + <description>the schema this table belongs to</description> + <standard>true</standard> + </column> + <column> + <name>table_name</name> + <type>VARCHAR</type> + <size>128</size> + <updatable>false</updatable> + <nullable>false</nullable> + <key>table_name</key> + <description>the fully qualified table name</description> + <standard>true</standard> + </column> + <column> + <name>table_type</name> + <size>8</size> + <type>VARCHAR</type> + <updatable>false</updatable> + <key>table_type</key> + <description>one of: table view</description> + <standard>true</standard> + </column> + <column> + <name>utype</name> + <type>VARCHAR</type> + <size>255</size> + <updatable>true</updatable> + <description>lists the utype of tables in the tableset</description> + <standard>true</standard> + </column> + <column> + <name>description</name> + <type>VARCHAR</type> + <size>255</size> + <updatable>true</updatable> + <description>describes tables in the tableset</description> + <standard>true</standard> + </column> </table> <table name="columns" description="description of columns in this tableset"> - <add> - <property> - <name>table_name</name> - <required>true</required> - <type>VARCHAR</type> - <size>128</size> - <updatable>false</updatable> - <nullable>false</nullable> - <key>table_name</key> - <description>the table this column belongs to</description> - <standard>true</standard> - </property> - <property> - <name>column_name</name> - <required>true</required> - <type>VARCHAR</type> - <size>64</size> - <updatable>false</updatable> - <nullable>false</nullable> - <key>column_name</key> - <description>the column name</description> - <standard>true</standard> - </property> - <property> - <name>datatype</name> - <type>VARCHAR</type> - <size>64</size> - <updatable>false</updatable> - <key>datatype</key> - <description>lists the ADQL datatype of columns in the tableset</description> - <standard>true</standard> - </property> - <property> - <name>size</name> - <type>INTEGER</type> - <updatable>false</updatable> - <key>size</key> - <description>lists the size of variable-length columns in the tableset</description> - <standard>true</standard> - </property> - <property> - <name>description</name> - <type>VARCHAR</type> - <size>255</size> - <updatable>true</updatable> - <description>describes the columns in the tableset</description> - <standard>true</standard> - </property> - <property> - <name>utype</name> - <type>VARCHAR</type> - <size>255</size> - <updatable>true</updatable> - <description>lists the utypes of columns in the tableset</description> - <standard>true</standard> - </property> - <property> - <name>unit</name> - <type>VARCHAR</type> - <size>64</size> - <updatable>true</updatable> - <description>lists the unit used for column values in the tableset</description> - <standard>true</standard> - </property> - <property> - <name>ucd</name> - <type>VARCHAR</type> - <size>64</size> - <updatable>true</updatable> - <description>lists the UCDs of columns in the tableset</description> - <standard>true</standard> - </property> - <property> - <name>indexed</name> - <type>INTEGER</type> - <updatable>false</updatable> - <nullable>false</nullable> - <key>indexed</key> - <default-value>0</default-value> - <description>an indexed column; 1 means true, 0 means false</description> - <standard>true</standard> - </property> - <property> - <name>principal</name> - <type>INTEGER</type> - <updatable>true</updatable> - <nullable>false</nullable> - <default-value>0</default-value> - <description>a principal column; 1 means true, 0 means false</description> - <standard>true</standard> - </property> - <property> - <name>std</name> - <type>INTEGER</type> - <updatable>true</updatable> - <nullable>false</nullable> - <default-value>0</default-value> - <description>a standard column; 1 means true, 0 means false</description> - <standard>true</standard> - </property> - </add> + <column> + <name>table_name</name> + <required>true</required> + <type>VARCHAR</type> + <size>128</size> + <updatable>false</updatable> + <nullable>false</nullable> + <key>table_name</key> + <description>the table this column belongs to</description> + <standard>true</standard> + </column> + <column> + <name>column_name</name> + <required>true</required> + <type>VARCHAR</type> + <size>64</size> + <updatable>false</updatable> + <nullable>false</nullable> + <key>column_name</key> + <description>the column name</description> + <standard>true</standard> + </column> + <column> + <name>datatype</name> + <type>VARCHAR</type> + <size>64</size> + <updatable>true</updatable> + <key>datatype</key> + <description>lists the ADQL datatype of columns in the tableset</description> + <standard>true</standard> + </column> + <column> + <name>size</name> + <type>INTEGER</type> + <updatable>false</updatable> + <key>size</key> + <description>lists the size of variable-length columns in the tableset</description> + <standard>true</standard> + </column> + <column> + <name>description</name> + <type>VARCHAR</type> + <size>255</size> + <updatable>true</updatable> + <description>describes the columns in the tableset</description> + <standard>true</standard> + </column> + <column> + <name>utype</name> + <type>VARCHAR</type> + <size>255</size> + <updatable>true</updatable> + <description>lists the utypes of columns in the tableset</description> + <standard>true</standard> + </column> + <column> + <name>unit</name> + <type>VARCHAR</type> + <size>64</size> + <updatable>true</updatable> + <description>lists the unit used for column values in the tableset</description> + <standard>true</standard> + </column> + <column> + <name>ucd</name> + <type>VARCHAR</type> + <size>64</size> + <updatable>true</updatable> + <description>lists the UCDs of columns in the tableset</description> + <standard>true</standard> + </column> + <column> + <name>indexed</name> + <type>INTEGER</type> + <updatable>false</updatable> + <nullable>false</nullable> + <key>indexed</key> + <default-value>0</default-value> + <description>an indexed column; 1 means true, 0 means false</description> + <standard>true</standard> + </column> + <column> + <name>principal</name> + <type>INTEGER</type> + <updatable>true</updatable> + <nullable>false</nullable> + <default-value>0</default-value> + <description>a principal column; 1 means true, 0 means false</description> + <standard>true</standard> + </column> + <column> + <name>std</name> + <type>INTEGER</type> + <updatable>true</updatable> + <nullable>false</nullable> + <default-value>0</default-value> + <description>a standard column; 1 means true, 0 means false</description> + <standard>true</standard> + </column> </table> <table name="keys" description="description of foreign keys in this tableset"> - <add> - <property> - <name>key_id</name> - <type>VARCHAR</type> - <size>64</size> - <updatable>true</updatable> - <description>unique key to join to TAP_SCHEMA.key_columns</description> - <standard>true</standard> - </property> - <property> - <name>from_table</name> - <type>VARCHAR</type> - <size>128</size> - <updatable>false</updatable> - <key>from_table</key> - <description>the table with the foreign key</description> - <standard>true</standard> - </property> - <property> - <name>target_table</name> - <type>VARCHAR</type> - <size>128</size> - <updatable>false</updatable> - <key>target_table</key> - <description>the table with the primary key</description> - <standard>true</standard> - </property> - <property> - <name>description</name> - <type>VARCHAR</type> - <size>255</size> - <updatable>true</updatable> - <description>describes keys in the tableset</description> - <standard>true</standard> - </property> - <property> - <name>utype</name> - <type>VARCHAR</type> - <size>255</size> - <updatable>true</updatable> - <description>lists the utype of keys in the tableset</description> - <standard>true</standard> - </property> - </add> + <column> + <name>key_id</name> + <type>VARCHAR</type> + <size>64</size> + <updatable>true</updatable> + <description>unique key to join to TAP_SCHEMA.key_columns</description> + <standard>true</standard> + </column> + <column> + <name>from_table</name> + <type>VARCHAR</type> + <size>128</size> + <updatable>false</updatable> + <key>from_table</key> + <description>the table with the foreign key</description> + <standard>true</standard> + </column> + <column> + <name>target_table</name> + <type>VARCHAR</type> + <size>128</size> + <updatable>false</updatable> + <key>target_table</key> + <description>the table with the primary key</description> + <standard>true</standard> + </column> + <column> + <name>description</name> + <type>VARCHAR</type> + <size>255</size> + <updatable>true</updatable> + <description>describes keys in the tableset</description> + <standard>true</standard> + </column> + <column> + <name>utype</name> + <type>VARCHAR</type> + <size>255</size> + <updatable>true</updatable> + <description>lists the utype of keys in the tableset</description> + <standard>true</standard> + </column> </table> <table name="key_columns" description="description of foreign key columns in this tableset"> - <add> - <property> - <name>key_id</name> - <type>VARCHAR</type> - <size>64</size> - <updatable>true</updatable> - <description>key to join to TAP_SCHEMA.keys</description> - <standard>true</standard> - </property> - <property> - <name>from_column</name> - <type>VARCHAR</type> - <size>64</size> - <updatable>false</updatable> - <key>from_column</key> - <description>column in the from_table</description> - <standard>true</standard> - </property> - <property> - <name>target_column</name> - <type>VARCHAR</type> - <size>64</size> - <updatable>false</updatable> - <key>target_column</key> - <description>column in the target_table</description> - <standard>true</standard> - </property> - </add> + <column> + <name>key_id</name> + <type>VARCHAR</type> + <size>64</size> + <updatable>true</updatable> + <description>key to join to TAP_SCHEMA.keys</description> + <standard>true</standard> + </column> + <column> + <name>from_column</name> + <type>VARCHAR</type> + <size>64</size> + <updatable>false</updatable> + <key>from_column</key> + <description>column in the from_table</description> + <standard>true</standard> + </column> + <column> + <name>target_column</name> + <type>VARCHAR</type> + <size>64</size> + <updatable>false</updatable> + <key>target_column</key> + <description>column in the target_table</description> + <standard>true</standard> + </column> </table> </schema> diff --git a/TASMAN-core/src/main/resources/schema_definition/tap_schema-1_1.xml b/TASMAN-core/src/main/resources/schema_definition/tap_schema-1_1.xml index ea62f6e8e42dd7a8f055463151c90c9c9583d005..6b36a0ff4769f5f3cfbeecbd9188bbc82f26eaf6 100644 --- a/TASMAN-core/src/main/resources/schema_definition/tap_schema-1_1.xml +++ b/TASMAN-core/src/main/resources/schema_definition/tap_schema-1_1.xml @@ -23,66 +23,62 @@ Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. --> <schema name="tap_schema" version="1.1" extends="1.0"> <table name="tables"> - <add> - <property> - <name>table_index</name> - <type>INTEGER</type> - <updatable>true</updatable> - <standard>true</standard> - </property> - </add> + <column> + <name>table_index</name> + <type>INTEGER</type> + <updatable>true</updatable> + <standard>true</standard> + </column> </table> <table name="columns"> - <add> - <property> - <name>arraysize</name> - <type>VARCHAR</type> - <updatable>false</updatable> - <key>arraysize</key> - <size>255</size> - <standard>true</standard> - </property> - <property> - <name>xtype</name> - <type>VARCHAR</type> - <updatable>true</updatable> - <size>255</size> - <standard>true</standard> - </property> - <property> - <name>column_index</name> - <type>INTEGER</type> - <updatable>true</updatable> - <standard>true</standard> - </property> - <property> - <name>indexed</name> - <type>BOOLEAN</type> - <updatable>false</updatable> - <nullable>false</nullable> - <default-value>false</default-value> - <key>indexed</key> - <description>an indexed column</description> - <standard>true</standard> - </property> - <property> - <name>principal</name> - <type>BOOLEAN</type> - <updatable>true</updatable> - <nullable>false</nullable> - <default-value>false</default-value> - <description>a principal column</description> - <standard>true</standard> - </property> - <property> - <name>std</name> - <type>BOOLEAN</type> - <updatable>true</updatable> - <nullable>false</nullable> - <default-value>false</default-value> - <description>a standard column</description> - <standard>true</standard> - </property> - </add> + <column> + <name>arraysize</name> + <type>VARCHAR</type> + <updatable>false</updatable> + <key>arraysize</key> + <size>255</size> + <standard>true</standard> + </column> + <column> + <name>xtype</name> + <type>VARCHAR</type> + <updatable>true</updatable> + <size>255</size> + <standard>true</standard> + </column> + <column> + <name>column_index</name> + <type>INTEGER</type> + <updatable>true</updatable> + <standard>true</standard> + </column> + <column> + <name>indexed</name> + <type>BOOLEAN</type> + <updatable>false</updatable> + <nullable>false</nullable> + <default-value>false</default-value> + <key>indexed</key> + <description>an indexed column</description> + <standard>true</standard> + </column> + <column> + <name>principal</name> + <type>BOOLEAN</type> + <updatable>true</updatable> + <nullable>false</nullable> + <default-value>false</default-value> + <description>a principal column</description> + <standard>true</standard> + </column> + <column> + <name>std</name> + <type>BOOLEAN</type> + <updatable>true</updatable> + <nullable>false</nullable> + <default-value>false</default-value> + <description>a standard column</description> + <standard>true</standard> + </column> </table> </schema> diff --git a/TASMAN-core/src/main/resources/sql_type_mapping.xml b/TASMAN-core/src/main/resources/sql_type_mapping.xml index 45161135688d27dfee88b712e47138f34251af69..51cf20d42bb836c696d18db1f769b9c84c951d14 100644 --- a/TASMAN-core/src/main/resources/sql_type_mapping.xml +++ b/TASMAN-core/src/main/resources/sql_type_mapping.xml @@ -77,11 +77,5 @@ Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. <pgsql>timestamp</pgsql> <java>java.lang.String</java> </type> - <type> - <adql>REGION</adql> - <mysql>VARCHAR</mysql> - <pgsql>character varying</pgsql> - <java>java.lang.String</java> - </type> </sql_type_mapping> diff --git a/TASMAN-core/src/test/java/it/inaf/ia2/tsm/TestXMLMerging.java b/TASMAN-core/src/test/java/it/inaf/ia2/tsm/TestXMLMerging.java new file mode 100644 index 0000000000000000000000000000000000000000..ae74b279b0cc87bd41a095636902bcc6dae925ea --- /dev/null +++ b/TASMAN-core/src/test/java/it/inaf/ia2/tsm/TestXMLMerging.java @@ -0,0 +1,142 @@ +/* + * _____________________________________________________________________________ + * + * INAF - OATS National Institute for Astrophysics - Astronomical Observatory of + * Trieste INAF - IA2 Italian Center for Astronomical Archives + * _____________________________________________________________________________ + * + * Copyright (C) 2017 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.model.XMLModelsLoader; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import org.junit.Test; +import static org.junit.Assert.*; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +/** + * + * @author Sonia Zorba {@literal <zorba at oats.inaf.it>} + */ +public class TestXMLMerging { + + public String getXMLString(Document doc) throws TransformerException { + TransformerFactory tFactory = TransformerFactory.newInstance(); + Transformer transformer = tFactory.newTransformer(); + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); + + DOMSource source = new DOMSource(doc); + StreamResult result = new StreamResult(new StringWriter()); + transformer.transform(source, result); + return result.getWriter().toString(); + } + + + @Test + public void test() throws Exception { + + String[] files = new String[]{"doc0.xml", "doc1.xml", "doc2.xml"}; + + XMLModelsLoader loader = new XMLModelsLoader(files); + + loader.load(TestXMLMerging.class.getClassLoader()); + + Map<String, Document> documents = loader.getDocuments(); + + Element schv0 = documents.get("0").getDocumentElement(); + Element schv1 = documents.get("1").getDocumentElement(); + Element schv2 = documents.get("2").getDocumentElement(); + + System.out.println("------------- 000 -------------"); + System.out.println(getXMLString(documents.get("0"))); + System.out.println("-------------------------------"); + System.out.println("------------- 111 -------------"); + System.out.println(getXMLString(documents.get("1"))); + System.out.println("-------------------------------"); + System.out.println("------------- 222 -------------"); + System.out.println(getXMLString(documents.get("2"))); + System.out.println("-------------------------------"); + + assertEquals("0", schv0.getAttribute("version")); + assertEquals("1", schv1.getAttribute("version")); + assertEquals("2", schv2.getAttribute("version")); + + // Checking final merge: + List<Element> tables = getElements(schv2.getElementsByTagName("table")); + Element tab0 = getElementByAttributeName(tables, "tab0"); + Element tab1 = getElementByAttributeName(tables, "tab1"); + Element tab2 = getElementByAttributeName(tables, "tab2"); + Element tab3 = getElementByAttributeName(tables, "tab3"); + Element tab4 = getElementByAttributeName(tables, "tab4"); + + // Checking first level table removal + assertNull(tab0); + // Checking second level table removal + assertNull(tab1); + + assertNotNull(tab2); + + // Checking first level table add + assertNotNull(tab3); + // Checking second level table add + assertNotNull(tab4); + + // Checking column override (first and second level) + List<Element> tab2Columns = getElements(tab2.getElementsByTagName("column")); + Element col2 = getElementByAttributeName(tab2Columns, "col2"); + assertEquals("CHAR", getTextElement(col2, "type")); + assertEquals("true", getTextElement(col2, "mandatory")); + assertEquals("100", getTextElement(col2, "size")); + assertEquals("false", getTextElement(col2, "updatable")); + } + + private String getTextElement(Element parent, String childName) { + return parent.getElementsByTagName(childName).item(0).getTextContent().trim(); + } + + private List<Element> getElements(NodeList nodes) { + List<Element> elements = new ArrayList<>(); + for (int i = 0; i < nodes.getLength(); i++) { + Node node = nodes.item(i); + if (node instanceof Element) { + elements.add((Element) node); + } + } + return elements; + } + + private Element getElementByAttributeName(List<Element> elements, String name) { + for (Element element : elements) { + if (name.equals(element.getAttribute("name"))) { + return element; + } + } + return null; + } +} diff --git a/TASMAN-core/src/test/resources/doc0.xml b/TASMAN-core/src/test/resources/doc0.xml new file mode 100644 index 0000000000000000000000000000000000000000..ce412fcce3298ae7f3155cc89475c8ac6ab86c71 --- /dev/null +++ b/TASMAN-core/src/test/resources/doc0.xml @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +_____________________________________________________________________________ + +INAF - OATS National Institute for Astrophysics - Astronomical Observatory of +Trieste INAF - IA2 Italian Center for Astronomical Archives +_____________________________________________________________________________ + +Copyright (C) 2017 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. +--> +<schema name="sch0" version="0"> + <table name="tab0"> + <column name="col0"> + <type>VARCHAR</type> + <size>255</size> + </column> + </table> + <table name="tab1"> + <column name="col0"> + <type>VARCHAR</type> + <size>255</size> + </column> + </table> + <table name="tab2"> + <column name="col0"> + <type>VARCHAR</type> + <size>255</size> + </column> + <column name="col1"> + <type>VARCHAR</type> + <size>255</size> + </column> + <column name="col2"> + <type>VARCHAR</type> + <size>255</size> + </column> + </table> +</schema> \ No newline at end of file diff --git a/TASMAN-core/src/test/resources/doc1.xml b/TASMAN-core/src/test/resources/doc1.xml new file mode 100644 index 0000000000000000000000000000000000000000..e5ca5c8bd9d7c44b65eb2ef9584efcb3da8034cf --- /dev/null +++ b/TASMAN-core/src/test/resources/doc1.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +_____________________________________________________________________________ + +INAF - OATS National Institute for Astrophysics - Astronomical Observatory of +Trieste INAF - IA2 Italian Center for Astronomical Archives +_____________________________________________________________________________ + +Copyright (C) 2017 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. +--> +<schema name="sch0" version="1" extends="0"> + <remove name="tab0" /> + <table name="tab2"> + <remove name="col0" /> + <column name="col2"> + <type>CHAR</type> + <mandatory>true</mandatory> + </column> + </table> + <table name="tab3"> + <column name="col0"> + <type>VARCHAR</type> + <size>255</size> + </column> + </table> +</schema> \ No newline at end of file diff --git a/TASMAN-core/src/test/resources/doc2.xml b/TASMAN-core/src/test/resources/doc2.xml new file mode 100644 index 0000000000000000000000000000000000000000..bbc5e14d5f0329ec061ef7ea8a6ae337ddd68c40 --- /dev/null +++ b/TASMAN-core/src/test/resources/doc2.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +_____________________________________________________________________________ + +INAF - OATS National Institute for Astrophysics - Astronomical Observatory of +Trieste INAF - IA2 Italian Center for Astronomical Archives +_____________________________________________________________________________ + +Copyright (C) 2017 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. +--> +<schema name="sch0" version="2" extends="1"> + <remove name="tab1" /> + <table name="tab2"> + <remove name="col1" /> + <column name="col2"> + <size>100</size> + <updatable>false</updatable> + </column> + </table> + <table name="tab4"> + <column name="col0"> + <type>VARCHAR</type> + <size>255</size> + </column> + </table> +</schema> \ No newline at end of file diff --git a/TASMAN-webapp/pom.xml b/TASMAN-webapp/pom.xml index a0dbb0fcb5076d35e46e0a43bc16b08f66e910e0..cd826caf7bc80fc50c94cd2bfce4360ab1fac410 100644 --- a/TASMAN-webapp/pom.xml +++ b/TASMAN-webapp/pom.xml @@ -103,6 +103,20 @@ <enable.jetty.config.start><!-- </enable.jetty.config.start> <enable.jetty.config.end> --></enable.jetty.config.end> </properties> + <dependencies> + <dependency> + <groupId>it.inaf.ia2.tap</groupId> + <artifactId>tasman-core</artifactId> + <version>1.2.0</version> + <exclusions> + <!-- exclusion due to tomcat-jdbc dependency conflicting with Jetty --> + <exclusion> + <groupId>org.apache.tomcat</groupId> + <artifactId>tomcat-juli</artifactId> + </exclusion> + </exclusions> + </dependency> + </dependencies> </profile> </profiles> @@ -111,13 +125,6 @@ <groupId>it.inaf.ia2.tap</groupId> <artifactId>tasman-core</artifactId> <version>1.2.0</version> - <exclusions> - <!-- exclusion due to tomcat-jdbc dependency conflicting with Jetty --> - <exclusion> - <groupId>org.apache.tomcat</groupId> - <artifactId>tomcat-juli</artifactId> - </exclusion> - </exclusions> </dependency> <dependency> <groupId>ari.ucidy</groupId> diff --git a/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/TapSchemaEditingBean.java b/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/TapSchemaEditingBean.java index 0bbac7f52aaf8d16bf140343223d1f5cdbcfa4e8..f3db6d4ed6239c85eb1f1db22880301fb123bfd2 100644 --- a/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/TapSchemaEditingBean.java +++ b/TASMAN-webapp/src/main/java/it/inaf/ia2/tsm/webapp/TapSchemaEditingBean.java @@ -404,41 +404,52 @@ public class TapSchemaEditingBean implements Serializable { } /** - * In TAP_SCHEMA 1.0 std column has an integer data type and use 1 for true - * and 0 for false, but we want to edit it using a JSF booleanCheckbox, so - * we need this workaround pairs of getter and setter. + * In TAP_SCHEMA 1.0 some columns have an integer data type and use 1 for + * true and 0 for false, but we want to edit them using a JSF + * booleanCheckbox, so we need this workaround for obtaining compatible + * getters and setters. */ - public Boolean getStd() { + public Boolean getCompatibleBoolValue(String key) { Column column = getSelectedColumn(); - if (column != null && column.getProperty("std") != null) { - return column.getValue("std", Integer.class) == 1; + if (column != null && column.getProperty(key) != null) { + Object objValue = column.getValue(key); + if (objValue == null) { + return null; + } + if (objValue instanceof Integer) { + return ((Integer) objValue) == 1; + } + return (Boolean) objValue; } return null; } - public void setStd(Boolean value) { + public void setCompatibleBoolValue(String key, Boolean value) { Column column = getSelectedColumn(); if (column != null) { - column.setValue("std", value ? 1 : 0); + Class type = column.getPropertyType(key); + if (type == Integer.class) { + column.setValue(key, value ? 1 : 0); + } else { + column.setValue(key, value); + } } } - /** - * Same of getStd(). - */ + public Boolean getStd() { + return getCompatibleBoolValue("std"); + } + + public void setStd(Boolean value) { + setCompatibleBoolValue("std", value); + } + public Boolean getPrincipal() { - Column column = getSelectedColumn(); - if (column != null && column.getProperty("principal") != null) { - return column.getValue("principal", Integer.class) == 1; - } - return null; + return getCompatibleBoolValue("principal"); } public void setPrincipal(Boolean value) { - Column column = getSelectedColumn(); - if (column != null) { - column.setValue("principal", value ? 1 : 0); - } + setCompatibleBoolValue("principal", value); } public List<Key> getVisibleKeys() {