/* * _____________________________________________________________________________ * * INAF - OATS National Institute for Astrophysics - Astronomical Observatory of * Trieste INAF - IA2 Italian Center for Astronomical Archives * _____________________________________________________________________________ * * Copyright (C) 2016 Istituto Nazionale di Astrofisica * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License Version 3 as published by the * Free Software Foundation. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 51 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ package it.inaf.ia2.tsm; import it.inaf.ia2.tsm.datalayer.DatabaseType; import it.inaf.ia2.tsm.datalayer.DBWrapper; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import javax.sql.DataSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Utility class that contains some static methods to manage various operations * with the TAP_SCHEMA entities. * * @author Sonia Zorba {@literal } */ public class TSMUtil { private static final Logger LOG = LoggerFactory.getLogger(TSMUtil.class); protected static List sortStringsList(List list) { Collections.sort(list, String.CASE_INSENSITIVE_ORDER); return list; } protected static List getChildrenByStatus(Iterable entities, Status... statuses) { List ret = new ArrayList<>(); for (T child : entities) { if (statuses == null || statuses.length == 0) { if (child != null) { 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 getChild(Map 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 List getAddableChildrenNames(Map children) { List list = new ArrayList<>(); for (Map.Entry 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: *
    *
  • In some cases the {@code getObject()} method (e.g. with * {@code Integer.class}) returns 0 instead of null. *
  • *
  • * Method * {@code org.postgresql.jdbc4.Jdbc4ResultSet.getObject(int, Class)} is * not yet implemented. *
  • *
*/ public static T getObject(ResultSet rs, String key, Class 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)}. */ public static T getObject(ResultSet rs, int i, Class type) throws SQLException { T ret; if (type == String.class) { ret = (T) rs.getString(i); } else if (type == Integer.class) { ret = (T) (Integer) rs.getInt(i); } else if (type == Long.class) { ret = (T) (Long) rs.getLong(i); } else if (type == Boolean.class) { ret = (T) (Boolean) rs.getBoolean(i); } else { throw new UnsupportedOperationException("Type " + type.getCanonicalName() + " not supported by " + TSMUtil.class.getCanonicalName() + " getObject() method"); } if (rs.wasNull()) { return null; } return ret; } protected static DataSource getSchemaDataSource(DBWrapper dbWrapper, TapSchema tapSchema, String schemaName) { return schemaName.equals(tapSchema.getName()) ? dbWrapper.getTapSchemaDataSource() : dbWrapper.getSourceDataSource(); } protected static DatabaseType getSchemaDatabaseType(DBWrapper dbWrapper, TapSchema tapSchema, String schemaName) { return schemaName.equals(tapSchema.getName()) ? dbWrapper.getTapSchemaDatabaseType() : dbWrapper.getSourceDatabaseType(); } protected static boolean isTapSchema(TapSchema tapSchema, String schemaName) { return schemaName.equals(tapSchema.getName()); } protected static UnsupportedOperationException getUnsupportedOperationException(String version, String unsupportedFeature) { return new UnsupportedOperationException("Version \"" + version + "\" doesn't support " + unsupportedFeature); } protected static String escapeName(String name, DatabaseType dbType) { char escapeChar; switch (dbType) { case MYSQL: escapeChar = '`'; break; case POSTGRES: escapeChar = '"'; break; default: throw new UnsupportedOperationException("Database type " + dbType + " not supported"); } return String.format("%s%s%s", escapeChar, name, escapeChar); } protected static String getTapSchemaTableNameFromEntity(TapSchemaEntity entity) { if (entity instanceof Schema) { return TapSchema.SCHEMAS_TABLE; } else if (entity instanceof Table) { return TapSchema.TABLES_TABLE; } else if (entity instanceof Column) { return TapSchema.COLUMNS_TABLE; } else if (entity instanceof Key) { return TapSchema.KEYS_TABLE; } else if (entity instanceof KeyColumn) { return TapSchema.KEY_COLUMNS_TABLE; } LOG.warn("getTapSchemaTableNameFromEntity returns null for {}" + entity.getClass().getCanonicalName()); return null; } public static String 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(); } /** * Utility class for joining a collection of object properties. */ public static class StringJoiner { private final Iterable values; private final String separator; public StringJoiner(Iterable values, String separator) { this.values = values; this.separator = separator; } public final String getString() { StringBuilder sb = new StringBuilder(); boolean first = true; for (T value : values) { if (!first) { sb.append(separator); } sb.append(getStringValue(value)); first = false; } return sb.toString(); } public String getStringValue(T value) { if (value instanceof String) { return (String) value; } return null; } } }