package adql.db; /* * This file is part of ADQLLibrary. * * ADQLLibrary is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * ADQLLibrary 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with ADQLLibrary. If not, see <http://www.gnu.org/licenses/>. * * Copyright 2012-2015 - UDS/Centre de DonnĂ©es astronomiques de Strasbourg (CDS), * Astronomisches Rechen Institut (ARI) */ import java.util.Collection; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; /** * Default implementation of {@link DBTable}. * * @author Grégory Mantelet (CDS;ARI) * @version 1.4 (08/2015) */ public class DefaultDBTable implements DBTable { protected String dbCatalogName; protected String dbSchemaName; protected String dbName; protected String adqlCatalogName = null; protected String adqlSchemaName = null; protected String adqlName = null; protected Map<String,DBColumn> columns = new LinkedHashMap<String,DBColumn>(); /** * <p>Builds a default {@link DBTable} with the given DB name.</p> * * <p>With this constructor: ADQL name = DB name.</p> * * <p><i><u>Note:</u> The table name can be prefixed by a schema and a catalog: t1 or schema1.t1 or cat1.schema1.t2</i></p> * * @param dbName Database name (it will be also used as ADQL table name). * * @see #DefaultDBTable(String, String) */ public DefaultDBTable(final String dbName){ this(dbName, null); } /** * <p>Builds a default {@link DBTable} with the given DB and ADQL names.</p> * * <p><i><u>Note:</u> The table names can be prefixed by a schema and a catalog: t1 or schema1.t1 or cat1.schema1.t2</i></p> * * @param dbName Database name. * @param adqlName Name used in ADQL queries. */ public DefaultDBTable(final String dbName, final String adqlName){ // DB names: String[] names = splitTableName(dbName); if (names[2] == null || names[2].length() == 0) throw new NullPointerException("Missing DB name !"); else this.dbName = names[2]; this.dbSchemaName = names[1]; this.dbCatalogName = names[0]; // ADQL names: names = splitTableName(adqlName); if (names[2] == null || names[2].length() == 0){ this.adqlName = this.dbName; this.adqlSchemaName = this.dbSchemaName; this.adqlCatalogName = this.dbCatalogName; }else{ this.adqlName = names[2]; this.adqlSchemaName = names[1]; this.adqlCatalogName = names[0]; } } /** * Builds default {@link DBTable} with a DB catalog, schema and table names. * * @param dbCatName Database catalog name (it will be also used as ADQL catalog name). * @param dbSchemName Database schema name (it will be also used as ADQL schema name). * @param dbName Database table name (it will be also used as ADQL table name). * * @see #DefaultDBTable(String, String, String, String, String, String) */ public DefaultDBTable(final String dbCatName, final String dbSchemName, final String dbName){ this(dbCatName, null, dbSchemName, null, dbName, null); } /** * Builds default {@link DBTable} with the DB and ADQL names for the catalog, schema and table. * * @param dbCatName Database catalog name. * @param adqlCatName Catalog name used in ADQL queries. * <em>If NULL, it will be set to dbCatName.</em> * @param dbSchemName Database schema name. * @param adqlSchemName Schema name used in ADQL queries. * <em>If NULL, it will be set to dbSchemName.</em> * @param dbName Database table name. * @param adqlName Table name used in ADQL queries. * <em>If NULL, it will be set to dbName.</em> */ public DefaultDBTable(final String dbCatName, final String adqlCatName, final String dbSchemName, final String adqlSchemName, final String dbName, final String adqlName){ if (dbName == null || dbName.length() == 0) throw new NullPointerException("Missing DB name !"); this.dbName = dbName; this.adqlName = (adqlName == null) ? dbName : adqlName; dbSchemaName = dbSchemName; adqlSchemaName = (adqlSchemName == null) ? dbSchemName : adqlSchemName; dbCatalogName = dbCatName; adqlCatalogName = (adqlCatName == null) ? dbCatName : adqlCatName; } @Override public final String getDBName(){ return dbName; } @Override public final String getDBSchemaName(){ return dbSchemaName; } @Override public final String getDBCatalogName(){ return dbCatalogName; } @Override public final String getADQLName(){ return adqlName; } public void setADQLName(final String name){ adqlName = (name != null) ? name : dbName; } @Override public final String getADQLSchemaName(){ return adqlSchemaName; } public void setADQLSchemaName(final String name){ adqlSchemaName = (name != null) ? name : dbSchemaName; } @Override public final String getADQLCatalogName(){ return adqlCatalogName; } public void setADQLCatalogName(final String name){ adqlName = (name != null) ? null : dbName; } /** * <p>Case sensitive !</p> * <p>Research optimized for researches by ADQL name.</p> * * @see adql.db.DBTable#getColumn(java.lang.String, boolean) */ @Override public DBColumn getColumn(String colName, boolean byAdqlName){ if (byAdqlName) return columns.get(colName); else{ for(DBColumn col : columns.values()){ if (col.getDBName().equals(colName)) return col; } return null; } } public boolean hasColumn(String colName, boolean byAdqlName){ return (getColumn(colName, byAdqlName) != null); } @Override public Iterator<DBColumn> iterator(){ return columns.values().iterator(); } public void addColumn(DBColumn column){ if (column != null) columns.put(column.getADQLName(), column); } public void addAllColumns(Collection<DBColumn> colList){ if (colList != null){ for(DBColumn column : colList) addColumn(column); } } /** * Splits the given table name in 3 parts: catalog, schema, table. * * @param table The table name to split. * * @return A String array of 3 items: [0]=catalog, [1]=schema, [0]=table. */ public static final String[] splitTableName(final String table){ String[] splitRes = new String[]{null,null,null}; if (table == null || table.trim().length() == 0) return splitRes; String[] names = table.trim().split("\\."); switch(names.length){ case 1: splitRes[2] = table.trim(); break; case 2: splitRes[2] = names[1].trim(); splitRes[1] = names[0].trim(); break; case 3: splitRes[2] = names[2].trim(); splitRes[1] = names[1].trim(); splitRes[0] = names[0].trim(); break; default: splitRes[2] = names[names.length - 1].trim(); splitRes[1] = names[names.length - 2].trim(); StringBuffer buff = new StringBuffer(names[0].trim()); for(int i = 1; i < names.length - 2; i++) buff.append('.').append(names[i].trim()); splitRes[0] = buff.toString(); } return splitRes; } /** * <p>Join the last 3 items of the given string array with a dot ('.'). * These three parts should be: [0]=catalog name, [1]=schema name, [2]=table name.</p> * * <p> * If the array contains less than 3 items, all the given items will be though joined. * However, if it contains more than 3 items, only the three last items will be. * </p> * * <p>A null item will be written as an empty string (string of length 0 ; "").</p> * * <p> * In the case the first and the third items are not null, but the second is null, the final string will contain in the middle two dots. * Example: if the array is {"cat", NULL, "table"}, then the joined string will be: "cat..table". * </p> * * @param nameParts String items to join. * * @return A string joining the 3 last string items of the given array, * or an empty string if the given array is NULL. * * @since 1.3 */ public static final String joinTableName(final String[] nameParts){ if (nameParts == null) return ""; StringBuffer str = new StringBuffer(); boolean empty = true; for(int i = (nameParts.length <= 3) ? 0 : (nameParts.length - 3); i < nameParts.length; i++){ if (!empty) str.append('.'); String part = (nameParts[i] == null) ? null : nameParts[i].trim(); if (part != null && part.length() > 0){ str.append(part); empty = false; } } return str.toString(); } @Override public DBTable copy(String dbName, String adqlName){ dbName = (dbName == null) ? joinTableName(new String[]{dbCatalogName,dbSchemaName,this.dbName}) : dbName; adqlName = (adqlName == null) ? joinTableName(new String[]{adqlCatalogName,adqlSchemaName,this.adqlName}) : adqlName; DefaultDBTable copy = new DefaultDBTable(dbName, adqlName); for(DBColumn col : this){ if (col instanceof DBCommonColumn) copy.addColumn(new DBCommonColumn((DBCommonColumn)col, col.getDBName(), col.getADQLName())); else copy.addColumn(col.copy(col.getDBName(), col.getADQLName(), copy)); } return copy; } }