Skip to content
Snippets Groups Projects
Commit e963dd44 authored by gmantele's avatar gmantele
Browse files

Official TAP v1.0 Release (including ADQL v1.1 and UWS v4.0)

parents
Branches
No related tags found
No related merge requests found
Showing
with 1912 additions and 0 deletions
File added
File added
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE project>
<project name="TAPUploaderTest" basedir="." default="jarBuild">
<target name="init">
<property name="srcRep" value="src" />
<property name="buildRep" value="build"/>
<property name="jarFile" value="uploadUtils.jar" />
<property name="jarDest" value=".." />
</target>
<target name="jarBuild" depends="init" >
<echo>Création du jar (${jarDest}/${jarFile})...</echo>
<jar destfile="${jarDest}/${jarFile}">
<zipfileset src="binarySavot.jar" excludes="META-INF/*" />
<zipfileset src="cds.savot.common.jar" excludes="META-INF/*" />
<zipfileset src="cds.savot.model.jar" excludes="META-INF/*" />
<zipfileset src="cds.savot.pull.jar" excludes="META-INF/*" />
<zipfileset src="cds.savot.writer.jar" excludes="META-INF/*" />
<zipfileset src="kxml2-min.jar" excludes="META-INF/*" />
<zipfileset src="cos.jar" excludes="META-INF/*" />
</jar>
</target>
</project>
\ No newline at end of file
File added
File added
File added
File added
File added
File added
This diff is collapsed.
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.
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 2011 - UDS/Centre de Données astronomiques de Strasbourg (CDS)
*/
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import adql.db.exception.UnresolvedColumnException;
import adql.db.exception.UnresolvedIdentifiersException;
import adql.db.exception.UnresolvedTableException;
import adql.parser.ParseException;
import adql.parser.QueryChecker;
import adql.query.ADQLObject;
import adql.query.ADQLQuery;
import adql.query.ClauseSelect;
import adql.query.ColumnReference;
import adql.query.IdentifierField;
import adql.query.SelectAllColumns;
import adql.query.SelectItem;
import adql.query.from.ADQLTable;
import adql.query.operand.ADQLColumn;
import adql.search.ISearchHandler;
import adql.search.SearchColumnHandler;
import adql.search.SimpleSearchHandler;
/**
* <p>
* Checks the existence of tables and columns, but also adds database metadata
* on {@link ADQLTable} and {@link ADQLColumn} instances when they are resolved.
* </p>
*
* <p>These information are:</p>
* <ul>
* <li>the corresponding {@link DBTable} or {@link DBColumn} (see getter and setter for DBLink in {@link ADQLTable} and {@link ADQLColumn})</li>
* <li>the link between an {@link ADQLColumn} and its {@link ADQLTable}</li>
* </ul>
*
* <p><i><u>Note:</u>
* Knowing DB metadata of {@link ADQLTable} and {@link ADQLColumn} is particularly useful for the translation of the ADQL query to SQL, because the ADQL name of columns and tables
* can be replaced in SQL by their DB name, if different. This mapping is done automatically by {@link adql.translator.PostgreSQLTranslator}.
* </i></p>
*
* @author Gr&eacute;gory Mantelet (CDS)
* @version 08/2011
*/
public class DBChecker implements QueryChecker {
/** List of all available tables ({@link DBTable}). */
protected SearchTableList lstTables;
/* ************ */
/* CONSTRUCTORS */
/* ************ */
/**
* Builds a {@link DBChecker} with an empty list of tables.
*/
public DBChecker(){
lstTables = new SearchTableList();
}
/**
* Builds a {@link DBChecker} with the given list of tables.
*
* @param tables List of all available tables.
*/
public DBChecker(final Collection<DBTable> tables){
setTables(tables);
}
/* ****** */
/* SETTER */
/* ****** */
/**
* <p>Sets the list of all available tables.</p>
*
* <p><i><u>Note:</u>
* Only if the given collection is NOT an instance of {@link SearchTableList},
* the collection will be copied inside a new {@link SearchTableList}.
* </i></p>
*
* @param tables List of {@link DBTable}s.
*/
public final void setTables(final Collection<DBTable> tables){
if (tables == null)
lstTables = new SearchTableList();
else if (tables instanceof SearchTableList)
lstTables = (SearchTableList)tables;
else
lstTables = new SearchTableList(tables);
}
/* ************* */
/* CHECK METHODS */
/* ************* */
/**
* Followed algorithm:
* <pre>
* Map&lt;DBTable,ADQLTable&gt; mapTables;
*
* For each ADQLTable t
* if (t.isSubQuery())
* dbTable = generateDBTable(t.getSubQuery, t.getAlias());
* else
* dbTable = resolveTable(t);
* t.setDBLink(dbTable);
* dbTables.put(t, dbTable);
* End
*
* For each SelectAllColumns c
* table = c.getAdqlTable();
* if (table != null){
* dbTable = resolveTable(table);
* if (dbTable == null)
* dbTable = query.getFrom().getTablesByAlias(table.getTableName(), table.isCaseSensitive(IdentifierField.TABLE));
* if (dbTable == null)
* throw new UnresolvedTableException(table);
* table.setDBLink(dbTable);
* }
* End
*
* SearchColumnList list = query.getFrom().getDBColumns();
*
* For each ADQLColumn c
* dbColumn = resolveColumn(c, list);
* c.setDBLink(dbColumn);
* c.setAdqlTable(mapTables.get(dbColumn.getTable()));
* End
*
* For each ColumnReference colRef
* checkColumnReference(colRef, query.getSelect(), list);
* End
* </pre>
*
* @param query The query to check.
*
* @throws ParseException An {@link UnresolvedIdentifiersException} if some tables or columns can not be resolved.
*
* @see #resolveTable(ADQLTable)
* @see #generateDBTable(ADQLQuery, String)
* @see #resolveColumn(ADQLColumn, SearchColumnList)
* @see #checkColumnReference(ColumnReference, ClauseSelect, SearchColumnList)
*/
public void check(final ADQLQuery query) throws ParseException {
UnresolvedIdentifiersException errors = new UnresolvedIdentifiersException();
HashMap<DBTable, ADQLTable> mapTables = new HashMap<DBTable, ADQLTable>();
ISearchHandler sHandler;
// Check the existence of all tables:
sHandler = new SearchTableHandler();
sHandler.search(query.getFrom());
for(ADQLObject result : sHandler){
try{
ADQLTable table = (ADQLTable)result;
// resolve the table:
DBTable dbTable = null;
if (table.isSubQuery()){
dbTable = generateDBTable(table.getSubQuery(), table.getAlias());
}else{
dbTable = resolveTable(table);
if (table.hasAlias())
dbTable = dbTable.copy(dbTable.getDBName(), table.getAlias());
}
// link with the matched DBTable:
table.setDBLink(dbTable);
mapTables.put(dbTable, table);
}catch(ParseException pe){
errors.addException(pe);
}
}
// Attach table information on wildcards with the syntax "{tableName}.*" of the SELECT clause:
sHandler = new SearchWildCardHandler();
sHandler.search(query.getSelect());
for(ADQLObject result : sHandler){
try{
SelectAllColumns wildcard = (SelectAllColumns)result;
ADQLTable table = wildcard.getAdqlTable();
DBTable dbTable = null;
// First, try to resolve the table by table alias:
if (table.getTableName() != null && table.getSchemaName() == null){
ArrayList<ADQLTable> tables = query.getFrom().getTablesByAlias(table.getTableName(), table.isCaseSensitive(IdentifierField.TABLE));
if (tables.size() == 1)
dbTable = tables.get(0).getDBLink();
}
// Then try to resolve the table reference by table name:
if (dbTable == null)
dbTable = resolveTable(table);
// table.setDBLink(dbTable);
wildcard.setAdqlTable(mapTables.get(dbTable));
}catch(ParseException pe){
errors.addException(pe);
}
}
SearchColumnList list = query.getFrom().getDBColumns();
// // DEBUG
// System.out.println("\n*** FROM COLUMNS ***");
// for(DBColumn dbCol : list){
// System.out.println("\t- "+dbCol.getADQLName()+" in "+((dbCol.getTable()==null)?"<NULL>":dbCol.getTable().getADQLName())+" (= "+dbCol.getDBName()+" in "+((dbCol.getTable()==null)?"<NULL>":dbCol.getTable().getDBName())+")");
// }
// System.out.println();
// Check the existence of all columns:
sHandler = new SearchColumnHandler();
sHandler.search(query);
for(ADQLObject result : sHandler){
try{
ADQLColumn adqlColumn = (ADQLColumn)result;
// resolve the column:
DBColumn dbColumn = resolveColumn(adqlColumn, list);
// link with the matched DBColumn:
adqlColumn.setDBLink(dbColumn);
adqlColumn.setAdqlTable(mapTables.get(dbColumn.getTable()));
}catch(ParseException pe){
errors.addException(pe);
}
}
// Check the correctness of all column references:
sHandler = new SearchColReferenceHandler();
sHandler.search(query);
ClauseSelect select = query.getSelect();
for(ADQLObject result : sHandler){
try{
ColumnReference colRef = (ColumnReference)result;
// resolve the column reference:
DBColumn dbColumn = checkColumnReference(colRef, select, list);
// link with the matched DBColumn:
colRef.setDBLink(dbColumn);
if (dbColumn != null)
colRef.setAdqlTable(mapTables.get(dbColumn.getTable()));
}catch(ParseException pe){
errors.addException(pe);
}
}
// Throw all errors if any:
if (errors.getNbErrors() > 0)
throw errors;
}
/**
* Resolves the given table, that's to say searches for the corresponding {@link DBTable}.
*
* @param table The table to resolve.
*
* @return The corresponding {@link DBTable} if found, <i>null</i> otherwise.
*
* @throws ParseException An {@link UnresolvedTableException} if the given table can't be resolved.
*/
protected DBTable resolveTable(final ADQLTable table) throws ParseException {
ArrayList<DBTable> tables = lstTables.search(table);
// good if only one table has been found:
if (tables.size() == 1)
return tables.get(0);
// but if more than one: ambiguous table name !
else if (tables.size() > 1)
throw new UnresolvedTableException(table, tables.get(0).getADQLSchemaName()+"."+tables.get(0).getADQLName(), tables.get(1).getADQLSchemaName()+"."+tables.get(1).getADQLName());
// otherwise (no match): unknown table !
else
throw new UnresolvedTableException(table);
}
/**
* Resolves the given column, that's to say searches for the corresponding {@link DBColumn}.
*
* @param column The column to resolve.
* @param dbColumns List of all available {@link DBColumn}s.
*
* @return The corresponding {@link DBColumn} if found, <i>null</i> otherwise.
*
* @throws ParseException An {@link UnresolvedColumnException} if the given column can't be resolved
* or an {@link UnresolvedTableException} if its table reference can't be resolved.
*/
protected DBColumn resolveColumn(final ADQLColumn column, final SearchColumnList dbColumns) throws ParseException {
ArrayList<DBColumn> foundColumns = dbColumns.search(column);
// good if only one column has been found:
if (foundColumns.size() == 1)
return foundColumns.get(0);
// but if more than one: ambiguous table reference !
else if (foundColumns.size() > 1){
if (column.getTableName() == null)
throw new UnresolvedColumnException(column, (foundColumns.get(0).getTable()==null)?"<NULL>":(foundColumns.get(0).getTable().getADQLName()+"."+foundColumns.get(0).getADQLName()), (foundColumns.get(1).getTable()==null)?"<NULL>":(foundColumns.get(1).getTable().getADQLName()+"."+foundColumns.get(1).getADQLName()));
else
throw new UnresolvedTableException(column, (foundColumns.get(0).getTable()==null)?"<NULL>":foundColumns.get(0).getTable().getADQLName(), (foundColumns.get(1).getTable()==null)?"<NULL>":foundColumns.get(1).getTable().getADQLName());
}// otherwise (no match): unknown column !
else
throw new UnresolvedColumnException(column);
}
/**
* Checks whether the given column reference corresponds to a selected item (column or an expression with an alias)
* or to an existing column.
*
* @param colRef The column reference which must be checked.
* @param select The SELECT clause of the ADQL query.
* @param dbColumns The list of all available {@link DBColumn}s.
*
* @return The corresponding {@link DBColumn} if this reference is actually the name of a column, <i>null</i> otherwise.
*
* @throws ParseException An {@link UnresolvedColumnException} if the given column can't be resolved
* or an {@link UnresolvedTableException} if its table reference can't be resolved.
*
* @see ClauseSelect#searchByAlias(String)
* @see #resolveColumn(ADQLColumn, SearchColumnList)
*/
protected DBColumn checkColumnReference(final ColumnReference colRef, final ClauseSelect select, final SearchColumnList dbColumns) throws ParseException {
if (colRef.isIndex()){
int index = colRef.getColumnIndex();
if (index > 0 && index <= select.size()){
SelectItem item = select.get(index-1);
if (item.getOperand() instanceof ADQLColumn)
return ((ADQLColumn)item.getOperand()).getDBLink();
else
return null;
}else
throw new ParseException("Column index out of bounds: "+index+" (must be between 1 and "+select.size()+") !");
}else{
ADQLColumn col = new ADQLColumn(colRef.getColumnName());
col.setCaseSensitive(colRef.isCaseSensitive());
// search among the select_item aliases:
if (col.getTableName() == null){
ArrayList<SelectItem> founds = select.searchByAlias(colRef.getColumnName(), colRef.isCaseSensitive());
if (founds.size() == 1)
return null;
else if (founds.size() > 1)
throw new UnresolvedColumnException(col, founds.get(0).getAlias(), founds.get(1).getAlias());
}
// check the corresponding column:
return resolveColumn(col, dbColumns);
}
}
/* ************************************* */
/* DBTABLE & DBCOLUMN GENERATION METHODS */
/* ************************************* */
/**
* Generates a {@link DBTable} corresponding to the given sub-query with the given table name.
* This {@link DBTable} which contains all {@link DBColumn} returned by {@link ADQLQuery#getResultingColumns()}.
*
* @param subQuery Sub-query in which the specified table must be searched.
* @param tableName Name of the table to search.
*
* @return The corresponding {@link DBTable} if the table has been found in the given sub-query, <i>null</i> otherwise.
*
* @throws ParseException Can be used to explain why the table has not been found.
*/
public static DBTable generateDBTable(final ADQLQuery subQuery, final String tableName) throws ParseException {
DefaultDBTable dbTable = new DefaultDBTable(tableName);
DBColumn[] columns = subQuery.getResultingColumns();
for(DBColumn dbCol : columns)
dbTable.addColumn(dbCol.copy(dbCol.getADQLName(), dbCol.getADQLName(), dbTable));
return dbTable;
}
/* *************** */
/* SEARCH HANDLERS */
/* *************** */
/**
* Lets searching all tables.
*
* @author Gr&eacute;gory Mantelet (CDS)
* @version 07/2011
*/
private static class SearchTableHandler extends SimpleSearchHandler {
@Override
public boolean match(final ADQLObject obj) {
return obj instanceof ADQLTable;
}
}
/**
* Lets searching all wildcards.
*
* @author Gr&eacute;gory Mantelet (CDS)
* @version 09/2011
*/
private static class SearchWildCardHandler extends SimpleSearchHandler {
@Override
public boolean match(final ADQLObject obj){
return (obj instanceof SelectAllColumns) && (((SelectAllColumns)obj).getAdqlTable() != null);
}
}
/**
* Lets searching column references.
*
* @author Gr&eacute;gory Mantelet (CDS)
* @version 11/2011
*/
private static class SearchColReferenceHandler extends SimpleSearchHandler {
@Override
public boolean match(final ADQLObject obj) {
return (obj instanceof ColumnReference);
}
}
}
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 2011 - UDS/Centre de Données astronomiques de Strasbourg (CDS)
*/
/**
* <p>Definition of a valid target column.</p>
*
* <p>
* This column can be used in an ADQL query with its ADQL name ({@link #getADQLName()})
* and corresponds to a real column in the "database" with its DB name ({@link #getDBName()}).
* </p>
*
* @author Gr&eacute;gory Mantelet (CDS)
* @version 08/2011
*/
public interface DBColumn {
/**
* Gets the name of this column which must be used in an ADQL query.
*
* @return Its ADQL name.
*/
public String getADQLName();
/**
* Gets the name of this column in the "database".
*
* @return Its DB name.
*/
public String getDBName();
/**
* Gets the table which contains this {@link DBColumn}.
*
* @return Its table or <i>null</i> if no table is specified.
*/
public DBTable getTable();
/**
* Makes a copy of this instance of {@link DBColumn}.
*
* @param dbName Its new DB name.
* @param adqlName Its new ADQL name.
* @param dbTable Its new table.
*
* @return A modified copy of this {@link DBColumn}.
*/
public DBColumn copy(final String dbName, final String adqlName, final DBTable dbTable);
}
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 - UDS/Centre de Données astronomiques de Strasbourg (CDS)
*/
/**
* <p>Definition of a valid target table.</p>
*
* <p>
* This table can be used in an ADQL query with its ADQL name ({@link #getADQLName()})
* and corresponds to a real table in the "database" with its DB name ({@link #getDBName()}).
* </p>
*
* @author Gr&eacute;gory Mantelet (CDS)
* @version 07/2011
*/
public interface DBTable extends Iterable<DBColumn> {
/**
* Gets the name of this table which must be used in an ADQL query.
*
* @return Its ADQL name.
*/
public String getADQLName();
/**
* Gets the name of this table in the "database".
*
* @return Its DB name.
*/
public String getDBName();
/**
* Gets the ADQL name of the schema which contains this table.
*
* @return ADQL name of its schema.
*/
public String getADQLSchemaName();
/**
* Gets the DB name of the schema which contains this table.
*
* @return DB name of its schema.
*/
public String getDBSchemaName();
/**
* Gets the ADQL name of the catalog which contains this table.
*
* @return ADQL name of its catalog.
*/
public String getADQLCatalogName();
/**
* Gets the DB name of the catalog which contains this table.
*
* @return DB name of its catalog.
*/
public String getDBCatalogName();
/**
* Gets the definition of the specified column if it exists in this table.
*
* @param colName Name of the column <i>(may be the ADQL or DB name depending of the second parameter)</i>.
* @param adqlName <i>true</i> means the given name is the ADQL name of the column and that the research must be done on the ADQL name of columns,
* <i>false</i> means the same thing but with the DB name.
*
* @return The corresponding column, or <i>null</i> if the specified column had not been found.
*/
public DBColumn getColumn(String colName, boolean adqlName);
/**
* Makes a copy of this instance of {@link DBTable}, with the possibility to change the DB and ADQL names.
*
* @param dbName Its new DB name.
* @param adqlName Its new ADQL name.
*
* @return A modified copy of this {@link DBTable}.
*/
public DBTable copy(final String dbName, final String adqlName);
}
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 - UDS/Centre de Données astronomiques de Strasbourg (CDS)
*/
/**
* Default implementation of {@link DBColumn}.
*
* @author Gr&eacute;gory Mantelet (CDS)
* @version 08/2011
*/
public class DefaultDBColumn implements DBColumn {
protected String dbName;
protected DBTable table;
protected String adqlName = null;
/**
* Builds a default {@link DBColumn} with the given DB name and DB table.
*
* @param dbName Database column name (it will be also used for the ADQL name).
* <b>Only the column name is expected. Contrary to {@link DefaultDBTable},
* if a whole column reference is given, no split will be done.</b>
* @param table DB table which contains this column.
*
* @see #DefaultDBColumn(String, String, DBTable)
*/
public DefaultDBColumn(final String dbName, final DBTable table){
this(dbName, dbName, table);
}
/**
* Builds a default {@link DBColumn} with the given DB name, DB table and ADQL name.
*
* @param dbName Database column name.
* <b>Only the column name is expected. Contrary to {@link DefaultDBTable},
* if a whole column reference is given, no split will be done.</b>
* @param adqlName Column name used in ADQL queries.
* <b>Only the column name is expected. Contrary to {@link DefaultDBTable},
* if a whole column reference is given, no split will be done.</b>
* @param table DB table which contains this column.
*/
public DefaultDBColumn(final String dbName, final String adqlName, final DBTable table){
this.dbName = dbName;
this.adqlName = adqlName;
this.table = table;
}
public final String getADQLName() {
return adqlName;
}
public final void setADQLName(final String adqlName){
if (adqlName != null)
this.adqlName = adqlName;
}
public final String getDBName() {
return dbName;
}
public final DBTable getTable() {
return table;
}
public final void setTable(final DBTable table){
this.table = table;
}
public DBColumn copy(final String dbName, final String adqlName, final DBTable dbTable){
return new DefaultDBColumn(dbName, adqlName, dbTable);
}
}
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 - UDS/Centre de Données astronomiques de Strasbourg (CDS)
*/
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
/**
* Default implementation of {@link DBTable}.
*
* @author Gr&eacute;gory Mantelet (CDS)
* @version 08/2011
*/
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 HashMap<String, DBColumn> columns = new HashMap<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.
* @param dbSchemName Database schema name.
* @param adqlSchemName Schema name used in ADQL queries.
* @param dbName Database table name.
* @param adqlName Table name used in ADQL queries.
*/
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;
dbSchemaName = dbSchemName;
adqlSchemaName = adqlSchemName;
dbCatalogName = dbCatName;
adqlCatalogName = adqlCatName;
}
public final String getDBName() {
return dbName;
}
public final String getDBSchemaName() {
return dbSchemaName;
}
public final String getDBCatalogName() {
return dbCatalogName;
}
public final String getADQLName() {
return adqlName;
}
public void setADQLName(final String name){
adqlName = (name != null)?name:dbName;
}
public final String getADQLSchemaName() {
return adqlSchemaName;
}
public void setADQLSchemaName(final String name){
adqlSchemaName = (name != null)?name:dbSchemaName;
}
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)
*/
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);
}
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;
}
public DBTable copy(final String dbName, final String adqlName) {
DefaultDBTable copy = new DefaultDBTable(dbName, adqlName);
for(DBColumn col : this)
copy.addColumn(col.copy(col.getDBName(), col.getADQLName(), copy));
return copy;
}
}
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 - UDS/Centre de Données astronomiques de Strasbourg (CDS)
*/
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import adql.query.IdentifierField;
import adql.query.operand.ADQLColumn;
import cds.utils.TextualSearchList;
/**
* <p>A list of {@link DBColumn} elements ordered by their ADQL name in an ascending manner.</p>
*
* <p>
* In addition to an ADQL name, {@link DBColumn} elements can be searched by specifying their table, schema and catalog.
* These last information will be used only if the ADQL column name is ambiguous, otherwise all matching elements are returned.
* </p>
*
* <p><i>
* <u>Note:</u>
* Table aliases can be listed here with their corresponding table name. Consequently, a table alias can be given as table name in the search parameters.
* </i></p>
*
* @author Gr&eacute;gory Mantelet (CDS)
* @version 09/2011
*/
public class SearchColumnList extends TextualSearchList<DBColumn> {
private static final long serialVersionUID = 1L;
/** Indicates whether multiple occurrences are allowed. */
private boolean distinct = false;
/** Case-sensitive dictionary of table aliases. (tableAlias <-> TableName) */
private final HashMap<String, String> tableAliases = new HashMap<String, String>();
/** Case-insensitive dictionary of table aliases. (tablealias <-> List&lt;TableName&gt;) */
private final HashMap<String, ArrayList<String>> mapAliases = new HashMap<String, ArrayList<String>>();
/* ************ */
/* CONSTRUCTORS */
/* ************ */
/**
* Void constructor.
*/
public SearchColumnList() {
super(new DBColumnKeyExtractor());
}
/**
* Constructor by copy: all the elements of the given collection of {@link DBColumn} are copied ordered into this list.
*
* @param collection Collection of {@link DBColumn} to copy.
*/
public SearchColumnList(final Collection<DBColumn> collection) {
super(collection, new DBColumnKeyExtractor());
}
/**
* Constructor with the initial capacity.
*
* @param initialCapacity Initial capacity of this list.
*/
public SearchColumnList(final int initialCapacity) {
super(initialCapacity, new DBColumnKeyExtractor());
}
/* ******* */
/* GETTERS */
/* ******* */
/**
* Tells whether multiple occurrences are allowed.
*
* @return <i>true</i> means that multiple occurrences are allowed, <i>false</i> otherwise.
*/
public final boolean isDistinct() {
return distinct;
}
/**
* Lets indicating that multiple occurrences are allowed.
*
* @param distinct <i>true</i> means that multiple occurrences are allowed, <i>false</i> otherwise.
*/
public final void setDistinct(final boolean distinct) {
this.distinct = distinct;
}
/* ********************** */
/* TABLE ALIAS MANAGEMENT */
/* ********************** */
/**
* Adds the given association between a table name and its alias in a query.
*
* @param tableAlias Table alias.
* @param tableName Table name.
*/
public final void putTableAlias(final String tableAlias, final String tableName){
if (tableAlias != null && tableName != null){
tableAliases.put(tableAlias, tableName);
ArrayList<String> aliases = mapAliases.get(tableAlias.toLowerCase());
if (aliases == null){
aliases = new ArrayList<String>();
mapAliases.put(tableAlias.toLowerCase(), aliases);
}
aliases.add(tableAlias);
}
}
/**
* Removes the given alias from this list.
*
* @param tableAlias The table alias which must be removed.
*/
public final void removeTableAlias(final String tableAlias){
tableAliases.remove(tableAlias);
ArrayList<String> aliases = mapAliases.get(tableAlias.toLowerCase());
if (aliases != null){
aliases.remove(tableAlias);
if (aliases.isEmpty())
mapAliases.remove(tableAlias.toLowerCase());
}
}
/**
* Removes all table name/alias associations.
*/
public final void removeAllTableAliases(){
tableAliases.clear();
mapAliases.clear();
}
public final int getNbTableAliases(){
return tableAliases.size();
}
/* ************** */
/* SEARCH METHODS */
/* ************** */
/**
* Searches all {@link DBColumn} elements which has the given name (case insensitive).
*
* @param columnName ADQL name of {@link DBColumn} to search for.
*
* @return The corresponding {@link DBColumn} elements.
*
* @see TextualSearchList#get(String)
*/
public ArrayList<DBColumn> search(final String columnName){
return get(columnName);
}
/**
* Searches all {@link DBColumn} elements which have the given catalog, schema, table and column name (case insensitive).
*
* @param catalog Catalog name.
* @param schema Schema name.
* @param table Table name.
* @param column Column name.
*
* @return The list of all matching {@link DBColumn} elements.
*
* @see #search(String, String, String, String, byte)
*/
public final ArrayList<DBColumn> search(final String catalog, final String schema, final String table, final String column){
return search(catalog, schema, table, column, (byte)0);
}
/**
* Searches all {@link DBColumn} elements corresponding to the given {@link ADQLColumn} (case insensitive).
*
* @param column An {@link ADQLColumn}.
*
* @return The list of all corresponding {@link DBColumn} elements.
*
* @see #search(String, String, String, String, byte)
*/
public ArrayList<DBColumn> search(final ADQLColumn column){
return search(column.getCatalogName(), column.getSchemaName(), column.getTableName(), column.getColumnName(), column.getCaseSensitive());
}
/**
* Searches all {@link DBColumn} elements which have the given catalog, schema, table and column name, with the specified case sensitivity.
*
* @param catalog Catalog name.
* @param schema Schema name.
* @param table Table name.
* @param column Column name.
* @param caseSensitivity Case sensitivity for each column parts (one bit by part ; 0=sensitive,1=insensitive ; see {@link IdentifierField} for more details).
*
* @return The list of all matching {@link DBColumn} elements.
*
* @see IdentifierField
*/
public ArrayList<DBColumn> search(final String catalog, final String schema, final String table, final String column, final byte caseSensitivity){
ArrayList<DBColumn> tmpResult = get(column, IdentifierField.COLUMN.isCaseSensitive(caseSensitivity));
if (table != null){
ArrayList<DBColumn> result = new ArrayList<DBColumn>();
for(DBColumn match : tmpResult){
DBTable dbTable = match.getTable();
if (IdentifierField.TABLE.isCaseSensitive(caseSensitivity)){
String tableName = tableAliases.get(table);
if (tableName == null) tableName = table;
if (!dbTable.getADQLName().equals(tableName))
continue;
}else{
ArrayList<String> aliases = mapAliases.get(table.toLowerCase());
if (aliases == null){
if (!dbTable.getADQLName().equalsIgnoreCase(table))
continue;
}else{
boolean foundAlias = false;
String temp;
for(int a=0; !foundAlias && a<aliases.size(); a++){
temp = tableAliases.get(aliases.get(a));
if (temp != null)
foundAlias = dbTable.getADQLName().equalsIgnoreCase(temp);
}
if (!foundAlias)
continue;
}
}
if (schema != null){
if (IdentifierField.SCHEMA.isCaseSensitive(caseSensitivity)){
if (!dbTable.getADQLSchemaName().equals(schema))
continue;
}else{
if (!dbTable.getADQLSchemaName().equalsIgnoreCase(schema))
continue;
}
if (catalog != null){
if (IdentifierField.CATALOG.isCaseSensitive(caseSensitivity)){
if (!dbTable.getADQLCatalogName().equals(catalog))
continue;
}else{
if (!dbTable.getADQLCatalogName().equalsIgnoreCase(catalog))
continue;
}
}
}
result.add(match);
}
return result;
}else{
// Special case: the columns merged by a NATURAL JOIN or a USING may have no table reference:
if (tmpResult.size() > 1){
ArrayList<DBColumn> result = new ArrayList<DBColumn>(tmpResult.size());
for(int i=0; i<tmpResult.size(); i++){
if (tmpResult.get(i).getTable() == null)
result.add(tmpResult.remove(i));
}
if (result.size() == 1)
return result;
}
return tmpResult;
}
}
/* ***************** */
/* INHERITED METHODS */
/* ***************** */
@Override
public boolean add(final DBColumn item) {
if (distinct && contains(item))
return false;
else
return super.add(item);
}
@Override
public boolean addAll(final Collection<? extends DBColumn> c) {
boolean changed = super.addAll(c);
if (changed){
if (c instanceof SearchColumnList){
SearchColumnList list = (SearchColumnList)c;
for(Map.Entry<String, String> entry : list.tableAliases.entrySet())
putTableAlias(entry.getKey(), entry.getValue());
}
}
return changed;
}
@Override
public boolean removeAll(final Collection<?> c) {
boolean changed = super.removeAll(c);
if (changed){
if (c instanceof SearchColumnList){
SearchColumnList list = (SearchColumnList)c;
for(String key : list.tableAliases.keySet())
removeTableAlias(key);
}
}
return changed;
}
/**
* Lets extracting the key to associate with a given {@link DBColumn} instance.
*
* @author Gr&eacute;gory Mantelet (CDS)
* @version 09/2011
*/
private static class DBColumnKeyExtractor implements KeyExtractor<DBColumn> {
public String getKey(DBColumn obj) {
return obj.getADQLName();
}
}
}
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 - UDS/Centre de Données astronomiques de Strasbourg (CDS)
*/
import java.util.ArrayList;
import java.util.Collection;
import adql.query.IdentifierField;
import adql.query.from.ADQLTable;
import cds.utils.TextualSearchList;
/**
* <p>A list of {@link DBTable} elements ordered by their ADQL name in an ascending manner.</p>
*
* <p>
* In addition to an ADQL name, {@link DBTable} elements can be searched by specifying their schema and catalog.
* These last information will be used only if the ADQL table name is ambiguous, otherwise all matching elements are returned.
* </p>
*
* @author Gr&eacute;gory Mantelet (CDS)
* @version 09/2011
*/
public class SearchTableList extends TextualSearchList<DBTable> {
private static final long serialVersionUID = 1L;
/** Indicates whether multiple occurrences are allowed. */
private boolean distinct = false;
/* ************ */
/* CONSTRUCTORS */
/* ************ */
/**
* Void constructor.
*/
public SearchTableList() {
super(new DBTableKeyExtractor());
}
/**
* Constructor by copy: all the elements of the given collection of {@link DBTable} are copied ordered into this list.
*
* @param collection Collection of {@link DBTable} to copy.
*/
public SearchTableList(final Collection<DBTable> collection) {
super(collection, new DBTableKeyExtractor());
}
/**
* Constructor with the initial capacity.
*
* @param initialCapacity Initial capacity of this list.
*/
public SearchTableList(final int initialCapacity) {
super(initialCapacity, new DBTableKeyExtractor());
}
/* ******* */
/* GETTERS */
/* ******* */
/**
* Tells whether multiple occurrences are allowed.
*
* @return <i>true</i> means that multiple occurrences are allowed, <i>false</i> otherwise.
*/
public final boolean isDistinct() {
return distinct;
}
/**
* Lets indicating that multiple occurrences are allowed.
*
* @param distinct <i>true</i> means that multiple occurrences are allowed, <i>false</i> otherwise.
*/
public final void setDistinct(final boolean distinct) {
this.distinct = distinct;
}
/* ************** */
/* SEARCH METHODS */
/* ************** */
/**
* Searches all {@link DBTable} elements which has the given name (case insensitive).
*
* @param tableName ADQL name of {@link DBTable} to search for.
*
* @return The corresponding {@link DBTable} elements.
*
* @see TextualSearchList#get(String)
*/
public ArrayList<DBTable> search(final String tableName){
return get(tableName);
}
/**
* Searches all {@link DBTable} elements which have the given catalog, schema, and table name (case insensitive).
*
* @param catalog Catalog name.
* @param schema Schema name.
* @param table Table name.
*
* @return The list of all matching {@link DBTable} elements.
*
* @see #search(String, String, String, byte)
*/
public final ArrayList<DBTable> search(final String catalog, final String schema, final String table){
return search(catalog, schema, table, (byte)0);
}
/**
* Searches all {@link DBTable} elements corresponding to the given {@link ADQLTable} (case insensitive).
*
* @param table An {@link ADQLTable}.
*
* @return The list of all corresponding {@link DBTable} elements.
*
* @see #search(String, String, String, byte)
*/
public ArrayList<DBTable> search(final ADQLTable table){
return search(table.getCatalogName(), table.getSchemaName(), table.getTableName(), table.getCaseSensitive());
}
/**
* Searches all {@link DBTable} elements which have the given catalog, schema, and table name, with the specified case sensitivity.
*
* @param catalog Catalog name.
* @param schema Schema name.
* @param table Table name.
* @param caseSensitivity Case sensitivity for each table parts (one bit by part ; 0=sensitive,1=insensitive ; see {@link IdentifierField} for more details).
*
* @return The list of all matching {@link DBTable} elements.
*
* @see IdentifierField
*/
public ArrayList<DBTable> search(final String catalog, final String schema, final String table, final byte caseSensitivity){
ArrayList<DBTable> tmpResult = get(table, IdentifierField.TABLE.isCaseSensitive(caseSensitivity));
if (schema != null){
ArrayList<DBTable> result = new ArrayList<DBTable>();
for(DBTable match : tmpResult){
if (IdentifierField.SCHEMA.isCaseSensitive(caseSensitivity)){
if (!match.getADQLSchemaName().equals(schema))
continue;
}else{
if (!match.getADQLSchemaName().equalsIgnoreCase(schema))
continue;
}
if (catalog != null){
if (IdentifierField.CATALOG.isCaseSensitive(caseSensitivity)){
if (!match.getADQLCatalogName().equals(catalog))
continue;
}else{
if (!match.getADQLCatalogName().equalsIgnoreCase(catalog))
continue;
}
}
result.add(match);
}
return result;
}else
return tmpResult;
}
/* ***************** */
/* INHERITED METHODS */
/* ***************** */
@Override
public boolean add(final DBTable item) {
if (distinct && contains(item))
return false;
else
return super.add(item);
}
/**
* Lets extracting a key to associate with a given {@link DBTable} instance.
*
* @author Gr&eacute;gory Mantelet (CDS)
* @version 09/2011
*/
private static class DBTableKeyExtractor implements KeyExtractor<DBTable> {
public String getKey(DBTable obj) {
return obj.getADQLName();
}
}
}
package adql.db.exception;
/*
* 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 - UDS/Centre de Données astronomiques de Strasbourg (CDS)
*/
import adql.db.DBChecker;
import adql.parser.ParseException;
import adql.query.operand.ADQLColumn;
/**
* This exception is thrown by {@link DBChecker} when a column does not exist
* or whose the table reference is ambiguous.
*
* @author Gr&eacute;gory Mantelet (CDS)
* @version 08/2011
*
* @see DBChecker
*/
public class UnresolvedColumnException extends ParseException {
private static final long serialVersionUID = 1L;
private final String columnName;
/* ************ */
/* CONSTRUCTORS */
/* ************ */
/**
* <p><b>UNKNOWN COLUMN</b></p>
*
* <p>Builds the exception with an {@link ADQLColumn} which does not exist.</p>
*
* @param c The unresolved {@link ADQLColumn}.
*/
public UnresolvedColumnException(ADQLColumn c){
super(buildMessage("Unknown column", c));
initPosition(c);
columnName = (c!=null)?c.getColumnName():null;
}
/**
* <p><b>AMBIGUOUS COLUMN NAME</b></p>
*
* <p>
* Builds the exception with an {@link ADQLColumn} which does not have a table reference AND which may come from more than one table
* OR with an {@link ADQLColumn} which may reference more than one column in the table.
* </p>
*
* @param c The ambiguous {@link ADQLColumn}.
* @param col1 First possibility.
* @param col2 A second possibility.
*/
public UnresolvedColumnException(ADQLColumn c, String col1, String col2){
super(buildMessage("Ambiguous column name", c, col1, col2));
initPosition(c);
columnName = (c!=null)?c.getColumnName():null;
}
protected final void initPosition(final ADQLColumn c){
position = c.getPosition();
}
public final String getColumnName(){
return columnName;
}
private static final String buildMessage(String msgStart, ADQLColumn c){
StringBuffer msg = new StringBuffer();
msg.append(msgStart).append(" \"").append(c.getFullColumnName()).append("\" !");
return msg.toString();
}
private static final String buildMessage(String msgStart, ADQLColumn c, String col1, String col2){
if (col1 != null && col2 != null){
StringBuffer msg = new StringBuffer(buildMessage(msgStart, c));
msg.append(" It may be (at least) \"").append(col1).append("\" or \"").append(col2).append("\".");
return msg.toString();
}else
return buildMessage(msgStart, c);
}
}
package adql.db.exception;
/*
* 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 - UDS/Centre de Données astronomiques de Strasbourg (CDS)
*/
import java.util.ArrayList;
import java.util.Iterator;
import adql.db.DBChecker;
import adql.parser.ParseException;
/**
* <p>
* This exception is thrown by {@link DBChecker} when several columns or tables do not exist.
* It lists several {@link ParseException} (either {@link UnresolvedColumnException} or {@link UnresolvedTableException}).
* </p>
* <p>
* Its message only tells the number of unresolved identifiers.
* If you want to have more details about the position and the exact message of each exception, you just have to iterate
* on this {@link UnresolvedIdentifiersException} (method {@link #iterator()}).
* </p>
*
* @author Gr&eacute;gory Mantelet (CDS)
* @version 06/2012
*
* @see DBChecker
*/
public class UnresolvedIdentifiersException extends ParseException implements Iterable<ParseException> {
private static final long serialVersionUID = 1L;
/** List of exceptions (one per unresolved identifier). */
protected ArrayList<ParseException> exceptions;
private String unresolvedIdentifiers = null;
/**
* Build an empty {@link UnresolvedIdentifiersException} (that's to say: there is no unresolved identifier).
*/
public UnresolvedIdentifiersException() {
exceptions = new ArrayList<ParseException>();
}
/**
* Adds a {@link ParseException} (supposed to be either an {@link UnresolvedColumnException} or an {@link UnresolvedTableException}).
*
* @param pe An exception.
*/
public final void addException(final ParseException pe){
if (pe != null){
exceptions.add(pe);
if (pe instanceof UnresolvedColumnException){
String colName = ((UnresolvedColumnException)pe).getColumnName();
if (colName != null && !colName.trim().isEmpty())
addIdentifierName(colName+" "+pe.getPosition());
}else if (pe instanceof UnresolvedTableException){
String tableName = ((UnresolvedTableException)pe).getTableName();
if (tableName != null && !tableName.trim().isEmpty())
addIdentifierName(tableName+" "+pe.getPosition());
}else if (pe instanceof UnresolvedIdentifiersException)
addIdentifierName(((UnresolvedIdentifiersException)pe).unresolvedIdentifiers);
}
}
/**
* Adds the name (or the description) into the string list of all the unresolved identifiers.
*
* @param name Name (or description) of the identifier to add.
*/
private final void addIdentifierName(final String name){
if (name != null && !name.trim().isEmpty()){
if (unresolvedIdentifiers == null)
unresolvedIdentifiers = "";
else
unresolvedIdentifiers += ", ";
unresolvedIdentifiers += name;
}
}
/**
* Gets the number of unresolved identifiers.
*
* @return The number of unresolved identifiers.
*/
public final int getNbErrors(){
return exceptions.size();
}
/**
* Gets the list of all errors.
*
* @return Errors list.
*/
public final Iterator<ParseException> getErrors(){
return exceptions.iterator();
}
public final Iterator<ParseException> iterator(){
return getErrors();
}
/**
* Only tells how many identifiers have not been resolved.
*
* @see java.lang.Throwable#getMessage()
*/
@Override
public String getMessage() {
return exceptions.size()+" unresolved identifiers"+((unresolvedIdentifiers!=null)?(": "+unresolvedIdentifiers):"")+" !";
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment