Newer
Older
/*
* _____________________________________________________________________________
*
* INAF - OATS National Institute for Astrophysics - Astronomical Observatory of
* Trieste INAF - IA2 Italian Center for Astronomical Archives
* _____________________________________________________________________________
*
* Copyright (C) 2016 Istituto Nazionale di Astrofisica
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License Version 3 as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
Sonia Zorba
committed
package it.inaf.ia2.tsm.api;
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
Sonia Zorba
committed
import it.inaf.ia2.tsm.api.contract.DatabaseType;
import it.inaf.ia2.tsm.api.contract.ChildEntity;
import it.inaf.ia2.tsm.api.contract.Column;
import it.inaf.ia2.tsm.api.contract.Key;
import it.inaf.ia2.tsm.api.contract.KeyColumn;
import it.inaf.ia2.tsm.api.contract.Schema;
import it.inaf.ia2.tsm.api.contract.Status;
import it.inaf.ia2.tsm.api.contract.Table;
import it.inaf.ia2.tsm.api.contract.TapSchema;
import it.inaf.ia2.tsm.api.contract.TapSchemaEntity;
import it.inaf.ia2.tsm.api.contract.TapSchemaVersion;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Map;
import javax.sql.DataSource;
import org.postgresql.ds.PGPoolingDataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
* Utility class that contains some static methods to manage various operations
* with the TAP_SCHEMA entities.
* @author Sonia Zorba {@literal <zorba at oats.inaf.it>}
public class TSMUtil {
private static final Logger log = LoggerFactory.getLogger(TSMUtil.class);
public static DataSource createDataSource(Credentials credentials) {
switch (credentials.getDatabaseType()) {
case MYSQL:
MysqlDataSource myds = new MysqlDataSource();
myds.setServerName(credentials.getHostname());
myds.setPortNumber(credentials.getPort());
myds.setUser(credentials.getUsername());
myds.setPassword(credentials.getPassword());
return myds;
case POSTGRES:
PGPoolingDataSource pgds = new PGPoolingDataSource();
pgds.setServerName(credentials.getHostname());
pgds.setPortNumber(credentials.getPort());
pgds.setUser(credentials.getUsername());
pgds.setPassword(credentials.getPassword());
pgds.setDatabaseName(credentials.getDatabase());
return pgds;
default:
throw new UnsupportedOperationException(credentials.getDatabaseType() + " not supported yet.");
}
}
protected static List<String> sortStringsList(List<String> list) {
Collections.sort(list, String.CASE_INSENSITIVE_ORDER);
return list;
}
protected static <T extends ChildEntity> List<T> getChildrenByStatus(Iterable<T> entities, Status... statuses) {
List<T> ret = new ArrayList<>();
for (T child : entities) {
if (statuses == null || statuses.length == 0) {
ret.add(child);
}
} else {
for (Status status : statuses) {
if (child != null && child.getStatus().equals(status)) {
ret.add(child);
break;
}
}
}
}
return Collections.unmodifiableList(ret);
}
protected static <T extends ChildEntity> T getChild(Map<String, T> children, String childName, Status... statuses) {
T child = children.get(childName);
if (child == null) {
return null;
}
if (statuses == null || statuses.length == 0) {
return child;
}
for (Status status : statuses) {
if (child.getStatus().equals(status)) {
return child;
}
}
return null;
}
protected static <T extends ChildEntity> List<String> getAddableChildrenNames(Map<String, T> children) {
List<String> list = new ArrayList<>();
for (Map.Entry<String, T> entry : children.entrySet()) {
T entity = entry.getValue();
if (entity == null || entity.getStatus() == Status.LOADED) {
list.add(entry.getKey());
}
}
return Collections.unmodifiableList(list);
}
* This method is thought for avoiding various problem encountered using the
* standard {@code ResultSet} {@code getObject()} method.
* In particular:
* <ul>
* <li>In some cases the {@code getObject()} method (e.g. with
* {@code Integer.class}) returns 0 instead of null.
* </li>
* <li>
* Method
* {@code org.postgresql.jdbc4.Jdbc4ResultSet.getObject(int, Class<T>)} is
* not yet implemented.
* </li>
* </ul>
protected static <T> T getObject(ResultSet rs, String key, Class<T> type) throws SQLException {
T ret;
if (type == String.class) {
ret = (T) rs.getString(key);
} else if (type == Integer.class) {
ret = (T) (Integer) rs.getInt(key);
} else if (type == Long.class) {
ret = (T) (Long) rs.getLong(key);
} else if (type == Boolean.class) {
ret = (T) (Boolean) rs.getBoolean(key);
} else {
throw new UnsupportedOperationException("Type " + type.getCanonicalName() + " not supported by " + TSMUtil.class.getCanonicalName() + " getObject() method");
if (rs.wasNull()) {
return null;
}
return ret;
* Same as {@link DLUtil.getObject(ResultSet, String, Class<T>)}.
protected static <T> T getObject(ResultSet rs, int i, Class<T> type) throws SQLException {
T ret;
if (type == String.class) {
ret = (T) rs.getString(i);
} else if (type == Integer.class) {
ret = (T) (Integer) rs.getInt(i);
} else if (type == Long.class) {
ret = (T) (Long) rs.getLong(i);
} else if (type == Boolean.class) {
ret = (T) (Boolean) rs.getBoolean(i);
} else {
throw new UnsupportedOperationException("Type " + type.getCanonicalName() + " not supported by " + TSMUtil.class.getCanonicalName() + " getObject() method");
if (rs.wasNull()) {
return null;
}
return ret;
}
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
protected static DataSource getSchemaDataSource(DBWrapper dbWrapper, TapSchema tapSchema, String schemaName) {
return schemaName.equals(tapSchema.getName()) ? dbWrapper.getTapSchemaDataSource() : dbWrapper.getSourceDataSource();
}
protected static DatabaseType getSchemaDatabaseType(DBWrapper dbWrapper, TapSchema tapSchema, String schemaName) {
return schemaName.equals(tapSchema.getName()) ? dbWrapper.getTapSchemaDatabaseType() : dbWrapper.getSourceDatabaseType();
}
protected static boolean isTapSchema(TapSchema tapSchema, String schemaName) {
return schemaName.equals(tapSchema.getName());
}
protected static UnsupportedOperationException getUnsupportedOperationException(TapSchemaVersion version, String unsupportedFeature) {
return new UnsupportedOperationException("Version \"" + version.name() + "\" doesn't support " + unsupportedFeature);
}
protected static boolean is1_1(TapSchemaVersion version) {
return version == TapSchemaVersion.TAP_SCHEMA_1_1 || version == TapSchemaVersion.TAP_SCHEMA_1_1_IA2;
}
protected static boolean isIA2(TapSchemaVersion version) {
return version == TapSchemaVersion.TAP_SCHEMA_1_IA2 || version == TapSchemaVersion.TAP_SCHEMA_1_1_IA2;
}
protected static String escapeName(String name, DatabaseType dbType) {
char escapeChar;
switch (dbType) {
case MYSQL:
escapeChar = '`';
break;
case POSTGRES:
escapeChar = '"';
break;
default:
throw new UnsupportedOperationException("Database type " + dbType + " not supported");
}
return String.format("%s%s%s", escapeChar, name, escapeChar);
}
protected static String getTapSchemaTableNameFromEntity(TapSchemaEntity entity) {
if (entity instanceof Schema) {
return TapSchema.SCHEMAS_TABLE;
} else if (entity instanceof Table) {
return TapSchema.TABLES_TABLE;
} else if (entity instanceof Column) {
return TapSchema.COLUMNS_TABLE;
} else if (entity instanceof Key) {
return TapSchema.KEYS_TABLE;
} else if (entity instanceof KeyColumn) {
return TapSchema.KEY_COLUMNS_TABLE;
}
log.warn("getTapSchemaTableNameFromEntity returns null for {}" + entity.getClass().getCanonicalName());
return null;
private static void setTSColumnDescription(Table table, String columnName, String description) {
Column column = table.getChild(columnName);
column.setDescription(description);
column.setStd(true);
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
public static String getNaturalLangueName(TapSchemaEntity entity) {
if (entity instanceof Schema) {
return "schema";
} else if (entity instanceof Table) {
return "table";
} else if (entity instanceof Column) {
return "column";
} else if (entity instanceof Key) {
return "key";
} else if (entity instanceof KeyColumn) {
return "key_column";
} else {
throw new UnsupportedOperationException("entity class " + entity.getClass().getCanonicalName() + " not supported yet");
}
}
public static String getName(TapSchemaEntity entity) {
if (entity instanceof Schema) {
return ((Schema) entity).getName();
} else if (entity instanceof Table) {
return ((Table) entity).getCompleteName();
} else if (entity instanceof Column) {
Column column = (Column) entity;
return column.getParent().getCompleteName() + "." + column.getName();
} else if (entity instanceof Key) {
return printKeyInfo((Key) entity);
} else if (entity instanceof KeyColumn) {
KeyColumn keyColumn = (KeyColumn) entity;
return String.format("%s -> %s [key: %s]",
keyColumn.getFromColumn(), keyColumn.getTargetColumn(),
printKeyInfo(keyColumn.getParent()));
} else {
throw new UnsupportedOperationException("entity class " + entity.getClass().getCanonicalName() + " not supported yet");
}
}
public static String printKeyInfo(Key key) {
StringBuilder sb = new StringBuilder();
sb.append(String.format("[%s] %s(", key.getId(), key.getFromTableCompleteName()));
boolean first = true;
for (KeyColumn keyColumn : key.getKeyColumns()) {
if (!first) {
sb.append(",");
}
first = false;
sb.append(keyColumn.getFromColumn());
}
sb.append(String.format(") -> %s(", key.getTargetTableCompleteName()));
first = true;
for (KeyColumn keyColumn : key.getKeyColumns()) {
if (!first) {
sb.append(",");
}
first = false;
sb.append(keyColumn.getTargetColumn());
}
sb.append(")");
return sb.toString();
}
/**
* Fill descriptions of the TAP_SCHEMA schema entities.
*
* @param schema the TAP_SCHEMA schema <code>SchemaEntity</code>.
*/
protected static void putInfoIntoTapSchemaSchema(Schema schema) {
schema.setDescription("a special schema to describe a TAP tableset");
// SCHEMAS
Table schemasTable = schema.getChild("schemas");
schemasTable.setDescription("description of schemas in this tableset");
setTSColumnDescription(schemasTable, "schema_name", "schema name for reference to TAP_SCHEMA.schemas");
setTSColumnDescription(schemasTable, "utype", "lists the utypes of schemas in the tableset");
setTSColumnDescription(schemasTable, "description", "describes schemas in the tableset");
Table tablesTable = schema.getChild("tables");
tablesTable.setDescription("description of tables in this tableset");
setTSColumnDescription(tablesTable, "schema_name", "the schema this table belongs to");
setTSColumnDescription(tablesTable, "table_name", "the fully qualified table name");
setTSColumnDescription(tablesTable, "table_type", "one of: table view");
setTSColumnDescription(tablesTable, "utype", "lists the utype of tables in the tableset");
setTSColumnDescription(tablesTable, "description", "describes tables in the tableset");
Table columnsTable = schema.getChild("columns");
columnsTable.setDescription("description of columns in this tableset");
setTSColumnDescription(columnsTable, "table_name", "the table this column belongs to");
setTSColumnDescription(columnsTable, "column_name", "the column name");
setTSColumnDescription(columnsTable, "utype", "lists the utypes of columns in the tableset");
setTSColumnDescription(columnsTable, "ucd", "lists the UCDs of columns in the tableset");
setTSColumnDescription(columnsTable, "unit", "lists the unit used for column values in the tableset");
setTSColumnDescription(columnsTable, "description", "describes the columns in the tableset");
setTSColumnDescription(columnsTable, "datatype", "lists the ADQL datatype of columns in the tableset");
setTSColumnDescription(columnsTable, "size", "lists the size of variable-length columns in the tableset");
setTSColumnDescription(columnsTable, "principal", "a principal column; 1 means 1, 0 means 0");
setTSColumnDescription(columnsTable, "indexed", "an indexed column; 1 means 1, 0 means 0");
setTSColumnDescription(columnsTable, "std", "a standard column; 1 means 1, 0 means 0");
Table keysTable = schema.getChild("keys");
keysTable.setDescription("description of foreign keys in this tableset");
setTSColumnDescription(keysTable, "key_id", "unique key to join to TAP_SCHEMA.key_columns");
setTSColumnDescription(keysTable, "from_table", "the table with the foreign key");
setTSColumnDescription(keysTable, "target_table", "the table with the primary key");
setTSColumnDescription(keysTable, "utype", "lists the utype of keys in the tableset");
setTSColumnDescription(keysTable, "description", "describes keys in the tableset");
Table keyColumnsTable = schema.getChild("key_columns");
keyColumnsTable.setDescription("description of foreign key columns in this tableset");
setTSColumnDescription(keyColumnsTable, "key_id", "key to join to TAP_SCHEMA.keys");
setTSColumnDescription(keyColumnsTable, "from_column", "column in the from_table");
setTSColumnDescription(keyColumnsTable, "target_column", "column in the target_table");