diff --git a/src/adql/db/DBChecker.java b/src/adql/db/DBChecker.java index 7dcbc62b104f70b3aa75c4d8a0eeb7d38b57004d..834d45abc5cf55a0005ad4b178941ac28469b586 100644 --- a/src/adql/db/DBChecker.java +++ b/src/adql/db/DBChecker.java @@ -17,16 +17,22 @@ package adql.db; * along with ADQLLibrary. If not, see <http://www.gnu.org/licenses/>. * * Copyright 2011,2013-2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS), - * Astronomishes Rechen Institut (ARI) + * Astronomisches Rechen Institut (ARI) */ import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; +import java.util.Map; import java.util.Stack; +import adql.db.STCS.CoordSys; +import adql.db.STCS.Region; +import adql.db.STCS.RegionType; import adql.db.exception.UnresolvedColumnException; +import adql.db.exception.UnresolvedFunction; import adql.db.exception.UnresolvedIdentifiersException; import adql.db.exception.UnresolvedTableException; import adql.parser.ParseException; @@ -42,14 +48,37 @@ import adql.query.SelectItem; import adql.query.from.ADQLTable; import adql.query.from.FromContent; import adql.query.operand.ADQLColumn; +import adql.query.operand.ADQLOperand; +import adql.query.operand.StringConstant; +import adql.query.operand.UnknownType; +import adql.query.operand.function.ADQLFunction; +import adql.query.operand.function.DefaultUDF; +import adql.query.operand.function.UserDefinedFunction; +import adql.query.operand.function.geometry.BoxFunction; +import adql.query.operand.function.geometry.CircleFunction; +import adql.query.operand.function.geometry.GeometryFunction; +import adql.query.operand.function.geometry.PointFunction; +import adql.query.operand.function.geometry.PolygonFunction; +import adql.query.operand.function.geometry.RegionFunction; import adql.search.ISearchHandler; import adql.search.SearchColumnHandler; import adql.search.SimpleSearchHandler; /** + * This {@link QueryChecker} implementation is able to do the following verifications on an ADQL query: + * <ol> + * <li>Check the existence of all table and column references found in a query</li> + * <li>Resolve all unknown functions as supported User Defined Functions (UDFs)</li> + * <li>Check whether all used geometrical functions are supported</li> + * <li>Check whether all used coordinate systems are supported</li> + * <li>Check that types of columns and UDFs match with their context</li> + * </ol> + * + * <h3>Check tables and columns</h3> * <p> - * Checks the existence of tables and columns, but also adds database metadata - * on {@link ADQLTable} and {@link ADQLColumn} instances when they are resolved. + * In addition to check the existence of tables and columns referenced in the query, + * this checked will also attach database metadata on these references ({@link ADQLTable} + * and {@link ADQLColumn} instances when they are resolved. * </p> * * <p>These information are:</p> @@ -59,35 +88,239 @@ import adql.search.SimpleSearchHandler; * </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}. + * 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.JDBCTranslator}. * </i></p> * * @author Grégory Mantelet (CDS;ARI) - * @version 1.3 (08/2014) + * @version 1.3 (10/2014) */ public class DBChecker implements QueryChecker { /** List of all available tables ({@link DBTable}). */ protected SearchTableList lstTables; + /** <p>List of all allowed geometrical functions (i.e. CONTAINS, REGION, POINT, COORD2, ...).</p> + * <p> + * If this list is NULL, all geometrical functions are allowed. + * However, if not, all items of this list must be the only allowed geometrical functions. + * So, if the list is empty, no such function is allowed. + * </p> + * @since 1.3 */ + protected String[] allowedGeo = null; + + /** <p>List of all allowed coordinate systems.</p> + * <p> + * Each item of this list must be of the form: "{frame} {refpos} {flavor}". + * Each of these 3 items can be either of value, a list of values expressed with the syntax "({value1}|{value2}|...)" + * or a '*' to mean all possible values. + * </p> + * <p><i>Note: since a default value (corresponding to the empty string - '') should always be possible for each part of a coordinate system, + * the checker will always add the default value (UNKNOWNFRAME, UNKNOWNREFPOS or SPHERICAL2) into the given list of possible values for each coord. sys. part.</i></p> + * <p> + * If this list is NULL, all coordinates systems are allowed. + * However, if not, all items of this list must be the only allowed coordinate systems. + * So, if the list is empty, none is allowed. + * </p> + * @since 1.3 */ + protected String[] allowedCoordSys = null; + + /** <p>A regular expression built using the list of allowed coordinate systems. + * With this regex, it is possible to known whether a coordinate system expression is allowed or not.</p> + * <p>If NULL, all coordinate systems are allowed.</p> + * @since 1.3 */ + protected String coordSysRegExp = null; + + /** <p>List of all allowed User Defined Functions (UDFs).</p> + * <p> + * If this list is NULL, any encountered UDF will be allowed. + * However, if not, all items of this list must be the only allowed UDFs. + * So, if the list is empty, no UDF is allowed. + * </p> + * @since 1.3 */ + protected FunctionDef[] allowedUdfs = null; + /* ************ */ /* CONSTRUCTORS */ /* ************ */ /** - * Builds a {@link DBChecker} with an empty list of tables. + * <p>Builds a {@link DBChecker} with an empty list of tables.</p> + * + * <p>Verifications done by this object after creation:</p> + * <ul> + * <li>Existence of tables and columns: <b>NO <i>(even unknown or fake tables and columns are allowed)</i></b></li> + * <li>Existence of User Defined Functions (UDFs): <b>NO <i>(any "unknown" function is allowed)</i></b></li> + * <li>Support of geometrical functions: <b>NO <i>(all valid geometrical functions are allowed)</i></b></li> + * <li>Support of coordinate systems: <b>NO <i>(all valid coordinate systems are allowed)</i></b></li> + * </ul> */ public DBChecker(){ - lstTables = new SearchTableList(); + this(null, null); } /** - * Builds a {@link DBChecker} with the given list of tables. + * <p>Builds a {@link DBChecker} with the given list of known tables.</p> + * + * <p>Verifications done by this object after creation:</p> + * <ul> + * <li>Existence of tables and columns: <b>OK</b></li> + * <li>Existence of User Defined Functions (UDFs): <b>NO <i>(any "unknown" function is allowed)</i></b></li> + * <li>Support of geometrical functions: <b>NO <i>(all valid geometrical functions are allowed)</i></b></li> + * <li>Support of coordinate systems: <b>NO <i>(all valid coordinate systems are allowed)</i></b></li> + * </ul> * * @param tables List of all available tables. */ public DBChecker(final Collection<? extends DBTable> tables){ + this(tables, null); + } + + /** + * <p>Builds a {@link DBChecker} with the given list of known tables and with a restricted list of user defined functions.</p> + * + * <p>Verifications done by this object after creation:</p> + * <ul> + * <li>Existence of tables and columns: <b>OK</b></li> + * <li>Existence of User Defined Functions (UDFs): <b>OK</b></li> + * <li>Support of geometrical functions: <b>NO <i>(all valid geometrical functions are allowed)</i></b></li> + * <li>Support of coordinate systems: <b>NO <i>(all valid coordinate systems are allowed)</i></b></li> + * </ul> + * + * @param tables List of all available tables. + * @param allowedUdfs List of all allowed user defined functions. + * If NULL, no verification will be done (and so, all UDFs are allowed). + * If empty list, no "unknown" (or UDF) is allowed. + * <i>Note: match with items of this list are done case insensitively.</i> + * + * @since 1.3 + */ + public DBChecker(final Collection<? extends DBTable> tables, final Collection<? extends FunctionDef> allowedUdfs){ + // Sort and store the given tables: setTables(tables); + + Object[] tmp; + int cnt; + + // Store all allowed UDFs in a sorted array: + if (allowedUdfs != null){ + // Remove all NULL and empty strings: + tmp = new FunctionDef[allowedUdfs.size()]; + cnt = 0; + for(FunctionDef udf : allowedUdfs){ + if (udf != null && udf.name.trim().length() > 0) + tmp[cnt++] = udf; + } + // make a copy of the array: + this.allowedUdfs = Arrays.copyOf(tmp, cnt, FunctionDef[].class); + tmp = null; + // sort the values: + Arrays.sort(this.allowedUdfs); + } + } + + /** + * <p>Builds a {@link DBChecker} with the given list of known tables and with a restricted list of user defined functions.</p> + * + * <p>Verifications done by this object after creation:</p> + * <ul> + * <li>Existence of tables and columns: <b>OK</b></li> + * <li>Existence of User Defined Functions (UDFs): <b>NO <i>(any "unknown" function is allowed)</i></b></li> + * <li>Support of geometrical functions: <b>OK</b></li> + * <li>Support of coordinate systems: <b>OK</b></li> + * </ul> + * + * @param tables List of all available tables. + * @param allowedGeoFcts List of all allowed geometrical functions (i.e. CONTAINS, POINT, UNION, CIRCLE, COORD1). + * If NULL, no verification will be done (and so, all geometries are allowed). + * If empty list, no geometry function is allowed. + * <i>Note: match with items of this list are done case insensitively.</i> + * @param allowedCoordSys List of all allowed coordinate system patterns. The syntax of a such pattern is the following: + * "{frame} {refpos} {flavor}" ; on the contrary to a coordinate system expression, here no part is optional. + * Each part of this pattern can be one the possible values (case insensitive), a list of possible values + * expressed with the syntax "({value1}|{value2}|...)", or a '*' for any valid value. + * For instance: "ICRS (GEOCENTER|heliocenter) *". + * If the given list is NULL, no verification will be done (and so, all coordinate systems are allowed). + * If it is empty, no coordinate system is allowed (except the default values - generally expressed by an empty string: ''). + * + * @since 1.3 + */ + public DBChecker(final Collection<? extends DBTable> tables, final Collection<String> allowedGeoFcts, final Collection<String> allowedCoordSys) throws ParseException{ + this(tables, null, allowedGeoFcts, allowedCoordSys); + } + + /** + * <p>Builds a {@link DBChecker}.</p> + * + * <p>Verifications done by this object after creation:</p> + * <ul> + * <li>Existence of tables and columns: <b>OK</b></li> + * <li>Existence of User Defined Functions (UDFs): <b>OK</b></li> + * <li>Support of geometrical functions: <b>OK</b></li> + * <li>Support of coordinate systems: <b>OK</b></li> + * </ul> + * + * @param tables List of all available tables. + * @param allowedUdfs List of all allowed user defined functions. + * If NULL, no verification will be done (and so, all UDFs are allowed). + * If empty list, no "unknown" (or UDF) is allowed. + * <i>Note: match with items of this list are done case insensitively.</i> + * @param allowedGeoFcts List of all allowed geometrical functions (i.e. CONTAINS, POINT, UNION, CIRCLE, COORD1). + * If NULL, no verification will be done (and so, all geometries are allowed). + * If empty list, no geometry function is allowed. + * <i>Note: match with items of this list are done case insensitively.</i> + * @param allowedCoordSys List of all allowed coordinate system patterns. The syntax of a such pattern is the following: + * "{frame} {refpos} {flavor}" ; on the contrary to a coordinate system expression, here no part is optional. + * Each part of this pattern can be one the possible values (case insensitive), a list of possible values + * expressed with the syntax "({value1}|{value2}|...)", or a '*' for any valid value. + * For instance: "ICRS (GEOCENTER|heliocenter) *". + * If the given list is NULL, no verification will be done (and so, all coordinate systems are allowed). + * If it is empty, no coordinate system is allowed (except the default values - generally expressed by an empty string: ''). + * + * @since 1.3 + */ + public DBChecker(final Collection<? extends DBTable> tables, final Collection<? extends FunctionDef> allowedUdfs, final Collection<String> allowedGeoFcts, final Collection<String> allowedCoordSys) throws ParseException{ + // Set the list of available tables + Set the list of all known UDFs: + this(tables, allowedUdfs); + + // Set the list of allowed geometrical functions: + allowedGeo = specialSort(allowedGeoFcts); + + // Set the list of allowed coordinate systems: + this.allowedCoordSys = specialSort(allowedCoordSys); + coordSysRegExp = STCS.buildCoordSysRegExp(this.allowedCoordSys); + } + + /** + * Transform the given collection of string elements in a sorted array. + * Only non-NULL and non-empty strings are kept. + * + * @param items Items to copy and sort. + * + * @return A sorted array containing all - except NULL and empty strings - items of the given collection. + * + * @since 1.3 + */ + protected final static String[] specialSort(final Collection<String> items){ + // Nothing to do if the array is NULL: + if (items == null) + return null; + + // Keep only valid items (not NULL and not empty string): + String[] tmp = new String[items.size()]; + int cnt = 0; + for(String item : items){ + if (item != null && item.trim().length() > 0) + tmp[cnt++] = item; + } + + // Make an adjusted array copy: + String[] copy = Arrays.copyOf(tmp, cnt); + + // Sort the values: + Arrays.sort(copy); + + return copy; } /* ****** */ @@ -98,7 +331,7 @@ public class DBChecker implements QueryChecker { * * <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}. + * the collection will be copied inside a new {@link SearchTableList}, otherwise it is used as provided. * </i></p> * * @param tables List of {@link DBTable}s. @@ -130,63 +363,136 @@ public class DBChecker implements QueryChecker { * @see #check(ADQLQuery, Stack) */ @Override - public void check(final ADQLQuery query) throws ParseException{ + public final void check(final ADQLQuery query) throws ParseException{ check(query, null); } /** - * Followed algorithm: - * <pre> - * Map<DBTable,ADQLTable> 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> + * <p>Process several (semantic) verifications in the given ADQL query.</p> + * + * <p>Main verifications done in this function:</p> + * <ol> + * <li>Existence of DB items (tables and columns)</li> + * <li>Semantic verification of sub-queries</li> + * <li>Support of every encountered User Defined Functions (UDFs - functions unknown by the syntactic parser)</li> + * <li>Support of every encountered geometries (functions, coordinate systems and STC-S expressions)</li> + * <li>Consistency of types still unknown (because the syntactic parser could not yet resolve them)</li> + * </ol> * * @param query The query to check. - * @param fathersList List of all columns available in the father query. + * @param fathersList List of all columns available in the father queries and that should be accessed in sub-queries. + * Each item of this stack is a list of columns available in each father-level query. + * <i>Note: this parameter is NULL if this function is called with the root/father query as parameter.</i> * - * @throws UnresolvedIdentifiersException An {@link UnresolvedIdentifiersException} if some tables or columns can not be resolved. + * @throws UnresolvedIdentifiersException An {@link UnresolvedIdentifiersException} if one or several of the above listed tests have detected + * some semantic errors (i.e. unresolved table, columns, function). * * @since 1.2 * - * @see #resolveTable(ADQLTable) - * @see #generateDBTable(ADQLQuery, String) - * @see #resolveColumn(ADQLColumn, SearchColumnList, Stack) - * @see #checkColumnReference(ColumnReference, ClauseSelect, SearchColumnList) + * @see #checkDBItems(ADQLQuery, Stack, UnresolvedIdentifiersException) + * @see #checkSubQueries(ADQLQuery, Stack, SearchColumnList, UnresolvedIdentifiersException) + * @see #checkUDFs(ADQLQuery, UnresolvedIdentifiersException) + * @see #checkGeometries(ADQLQuery, UnresolvedIdentifiersException) + * @see #checkTypes(ADQLQuery, UnresolvedIdentifiersException) */ - protected void check(final ADQLQuery query, Stack<SearchColumnList> fathersList) throws UnresolvedIdentifiersException{ + protected void check(final ADQLQuery query, final Stack<SearchColumnList> fathersList) throws UnresolvedIdentifiersException{ UnresolvedIdentifiersException errors = new UnresolvedIdentifiersException(); + + // A. Check DB items (tables and columns): + SearchColumnList availableColumns = checkDBItems(query, fathersList, errors); + + // B. Check UDFs: + if (allowedUdfs != null) + checkUDFs(query, errors); + + // C. Check geometries: + checkGeometries(query, errors); + + // D. Check types: + checkTypes(query, errors); + + // E. Check sub-queries: + checkSubQueries(query, fathersList, availableColumns, errors); + + // Throw all errors, if any: + if (errors.getNbErrors() > 0) + throw errors; + } + + /* ************************************************ */ + /* CHECKING METHODS FOR DB ITEMS (TABLES & COLUMNS) */ + /* ************************************************ */ + + /** + * <p>Check DB items (tables and columns) used in the given ADQL query.</p> + * + * <p>Operations done in this function:</p> + * <ol> + * <li>Resolve all found tables</li> + * <li>Get the whole list of all available columns <i>Note: this list is returned by this function.</i></li> + * <li>Resolve all found columns</li> + * </ol> + * + * @param query Query in which the existence of DB items must be checked. + * @param fathersList List of all columns available in the father queries and that should be accessed in sub-queries. + * Each item of this stack is a list of columns available in each father-level query. + * <i>Note: this parameter is NULL if this function is called with the root/father query as parameter.</i> + * @param errors List of errors to complete in this function each time an unknown table or column is encountered. + * + * @return List of all columns available in the given query. + * + * @see #resolveTables(ADQLQuery, Stack, UnresolvedIdentifiersException) + * @see FromContent#getDBColumns() + * @see #resolveColumns(ADQLQuery, Stack, Map, SearchColumnList, UnresolvedIdentifiersException) + * + * @since 1.3 + */ + protected SearchColumnList checkDBItems(final ADQLQuery query, final Stack<SearchColumnList> fathersList, final UnresolvedIdentifiersException errors){ + // a. Resolve all tables: + Map<DBTable,ADQLTable> mapTables = resolveTables(query, fathersList, errors); + + // b. Get the list of all columns made available in the clause FROM: + SearchColumnList availableColumns; + try{ + availableColumns = query.getFrom().getDBColumns(); + }catch(ParseException pe){ + errors.addException(pe); + availableColumns = new SearchColumnList(); + } + + // c. Resolve all columns: + resolveColumns(query, fathersList, mapTables, availableColumns, errors); + + return availableColumns; + } + + /** + * <p>Search all table references inside the given query, resolve them against the available tables, and if there is only one match, + * attach the matching metadata to them.</p> + * + * <b>Management of sub-query tables</b> + * <p> + * If a table is not a DB table reference but a sub-query, this latter is first checked (using {@link #check(ADQLQuery, Stack)} ; + * but the father list must not contain tables of the given query, because on the same level) and then corresponding table metadata + * are generated (using {@link #generateDBTable(ADQLQuery, String)}) and attached to it. + * </p> + * + * <b>Management of "{table}.*" in the SELECT clause</b> + * <p> + * For each of this SELECT item, this function tries to resolve the table name. If only one match is found, the corresponding ADQL table object + * is got from the list of resolved tables and attached to this SELECT item (thus, the joker item will also have the good metadata, + * particularly if the referenced table is a sub-query). + * </p> + * + * @param query Query in which the existence of tables must be checked. + * @param fathersList List of all columns available in the father queries and that should be accessed in sub-queries. + * Each item of this stack is a list of columns available in each father-level query. + * <i>Note: this parameter is NULL if this function is called with the root/father query as parameter.</i> + * @param errors List of errors to complete in this function each time an unknown table or column is encountered. + * + * @return An associative map of all the resolved tables. + */ + protected Map<DBTable,ADQLTable> resolveTables(final ADQLQuery query, final Stack<SearchColumnList> fathersList, final UnresolvedIdentifiersException errors){ HashMap<DBTable,ADQLTable> mapTables = new HashMap<DBTable,ADQLTable>(); ISearchHandler sHandler; @@ -200,7 +506,7 @@ public class DBChecker implements QueryChecker { // resolve the table: DBTable dbTable = null; if (table.isSubQuery()){ - // check the subquery tables: + // check the sub-query tables: check(table.getSubQuery(), fathersList); // generate its DBTable: dbTable = generateDBTable(table.getSubQuery(), table.getAlias()); @@ -220,9 +526,9 @@ public class DBChecker implements QueryChecker { // Attach table information on wildcards with the syntax "{tableName}.*" of the SELECT clause: /* Note: no need to check the table name among the father tables, because there is - * no interest to select a father column in a subquery - * (which can return only one column ; besides, no aggregate is not allowed - * in subqueries).*/ + * no interest to select a father column in a sub-query + * (which can return only one column ; besides, no aggregate is allowed + * in sub-queries).*/ sHandler = new SearchWildCardHandler(); sHandler.search(query.getSelect()); for(ADQLObject result : sHandler){ @@ -230,31 +536,77 @@ public class DBChecker implements QueryChecker { SelectAllColumns wildcard = (SelectAllColumns)result; ADQLTable table = wildcard.getAdqlTable(); DBTable dbTable = null; - // First, try to resolve the table by table alias: + + // 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: + + // then try to resolve the table reference by table name: if (dbTable == null) dbTable = resolveTable(table); - // table.setDBLink(dbTable); + // set the corresponding tables among the list of resolved tables: wildcard.setAdqlTable(mapTables.get(dbTable)); }catch(ParseException pe){ errors.addException(pe); } } - // Get the list of all columns made available in the clause FROM: - SearchColumnList list; - try{ - list = query.getFrom().getDBColumns(); - }catch(ParseException pe){ - errors.addException(pe); - list = new SearchColumnList(); - } + return mapTables; + } + + /** + * Resolve the given table, that's to say search 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); + } + + /** + * <p>Search all column references inside the given query, resolve them thanks to the given tables' metadata, + * and if there is only one match, attach the matching metadata to them.</p> + * + * <b>Management of selected columns' references</b> + * <p> + * A column reference is not only a direct reference to a table column using a column name. + * It can also be a reference to an item of the SELECT clause (which will then call a "selected column"). + * That kind of reference can be either an index (an unsigned integer starting from 1 to N, where N is the + * number selected columns), or the name/alias of the column. + * </p> + * <p> + * These references are also checked, in a second step, in this function. Thus, column metadata are + * also attached to them, as common columns. + * </p> + * + * @param query Query in which the existence of tables must be checked. + * @param fathersList List of all columns available in the father queries and that should be accessed in sub-queries. + * Each item of this stack is a list of columns available in each father-level query. + * <i>Note: this parameter is NULL if this function is called with the root/father query as parameter.</i> + * @param mapTables List of all resolved tables. + * @param list List of column metadata to complete in this function each time a column reference is resolved. + * @param errors List of errors to complete in this function each time an unknown table or column is encountered. + */ + protected void resolveColumns(final ADQLQuery query, final Stack<SearchColumnList> fathersList, final Map<DBTable,ADQLTable> mapTables, final SearchColumnList list, final UnresolvedIdentifiersException errors){ + ISearchHandler sHandler; // Check the existence of all columns: sHandler = new SearchColumnHandler(); @@ -272,7 +624,7 @@ public class DBChecker implements QueryChecker { } } - // Check the correctness of all column references: + // Check the correctness of all column references (= references to selected columns): /* Note: no need to provide the father tables when resolving column references, * because no father column can be used in ORDER BY and/or GROUP BY. */ sHandler = new SearchColReferenceHandler(); @@ -291,70 +643,22 @@ public class DBChecker implements QueryChecker { errors.addException(pe); } } - - // Check subqueries outside the clause FROM: - sHandler = new SearchSubQueryHandler(); - sHandler.search(query); - if (sHandler.getNbMatch() > 0){ - - // Push the list of columns in the father columns stack: - if (fathersList == null) - fathersList = new Stack<SearchColumnList>(); - fathersList.push(list); - - // Check each found subquery (except the first one because it is the current query): - for(ADQLObject result : sHandler){ - try{ - check((ADQLQuery)result, fathersList); - }catch(UnresolvedIdentifiersException uie){ - Iterator<ParseException> itPe = uie.getErrors(); - while(itPe.hasNext()) - errors.addException(itPe.next()); - } - } - - // Pop the list of columns from the father columns stack: - fathersList.pop(); - - } - - // 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. + * <p>Resolve the given column, that's to say search for the corresponding {@link DBColumn}.</p> * - * @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); - } - - /** - * <p>Resolves the given column, that's to say searches for the corresponding {@link DBColumn}.</p> - * <p>The third parameter is used only if this function is called inside a subquery. In this case, - * column is tried to be resolved with the first list (dbColumns). If no match is found, - * the resolution is tried with the father columns list (fatherColumns).</p> + * <p> + * The third parameter is used only if this function is called inside a sub-query. In this case, + * the column is tried to be resolved with the first list (dbColumns). If no match is found, + * the resolution is tried with the father columns list (fathersList). + * </p> * * @param column The column to resolve. * @param dbColumns List of all available {@link DBColumn}s. - * @param fathersList List of all columns available in the father query ; a list for each father-level. + * @param fathersList List of all columns available in the father queries and that should be accessed in sub-queries. + * Each item of this stack is a list of columns available in each father-level query. + * <i>Note: this parameter is NULL if this function is called with the root/father query as parameter.</i> * * @return The corresponding {@link DBColumn} if found. Otherwise an exception is thrown. * @@ -386,14 +690,14 @@ public class DBChecker implements QueryChecker { } /** - * Checks whether the given column reference corresponds to a selected item (column or an expression with an alias) + * Check 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. + * @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 columns. * - * @return The corresponding {@link DBColumn} if this reference is actually the name of a column, <i>null</i> otherwise. + * @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. @@ -431,19 +735,16 @@ public class DBChecker implements QueryChecker { } } - /* ************************************* */ - /* 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()}. + * Generate a {@link DBTable} corresponding to the given sub-query with the given table name. + * This {@link DBTable} will contain 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. + * @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. + * @throws ParseException Can be used to explain why the table has not been found. <i>Note: not used by default.</i> */ public static DBTable generateDBTable(final ADQLQuery subQuery, final String tableName) throws ParseException{ DefaultDBTable dbTable = new DefaultDBTable(tableName); @@ -455,6 +756,469 @@ public class DBChecker implements QueryChecker { return dbTable; } + /* ************************* */ + /* CHECKING METHODS FOR UDFs */ + /* ************************* */ + + /** + * <p>Search all UDFs (User Defined Functions) inside the given query, and then + * check their signature against the list of allowed UDFs.</p> + * + * <p><i>Note: + * When more than one allowed function match, the function is considered as correct + * and no error is added. + * However, in case of multiple matches, the return type of matching functions could + * be different and in this case, there would be an error while checking later + * the types. In such case, throwing an error could make sense, but the user would + * then need to cast some parameters to help the parser identifying the right function. + * But the type-casting ability is not yet possible in ADQL. + * </i></p> + * + * @param query Query in which UDFs must be checked. + * @param errors List of errors to complete in this function each time a UDF does not match to any of the allowed UDFs. + * + * @since 1.3 + */ + protected void checkUDFs(final ADQLQuery query, final UnresolvedIdentifiersException errors){ + // Search all UDFs: + ISearchHandler sHandler = new SearchUDFHandler(); + sHandler.search(query); + + // If no UDF are allowed, throw immediately an error: + if (allowedUdfs.length == 0){ + for(ADQLObject result : sHandler) + errors.addException(new UnresolvedFunction((UserDefinedFunction)result)); + } + // Otherwise, try to resolve all of them: + else{ + ArrayList<UserDefinedFunction> toResolveLater = new ArrayList<UserDefinedFunction>(); + UserDefinedFunction udf; + int match; + BinarySearch<FunctionDef,UserDefinedFunction> binSearch = new BinarySearch<FunctionDef,UserDefinedFunction>(){ + @Override + protected int compare(UserDefinedFunction searchItem, FunctionDef arrayItem){ + return arrayItem.compareTo(searchItem) * -1; + } + }; + + // Try to resolve all the found UDFs: + /* Note: at this stage, it can happen that UDFs can not be yet resolved because the building of + * their signature depends of other UDFs. That's why, these special cases should be kept + * for a later resolution try. */ + for(ADQLObject result : sHandler){ + udf = (UserDefinedFunction)result; + // search for a match: + match = binSearch.search(udf, allowedUdfs); + // if no match... + if (match < 0){ + // ...if the type of all parameters is resolved, add an error (no match is possible): + if (isAllParamTypesResolved(udf)) + errors.addException(new UnresolvedFunction(udf)); // TODO Add the ADQLOperand position! + // ...otherwise, try to resolved it later (when other UDFs will be mostly resolved): + else + toResolveLater.add(udf); + } + // if there is a match, metadata may be attached (particularly if the function is built automatically by the syntactic parser): + else if (udf instanceof DefaultUDF) + ((DefaultUDF)udf).setDefinition(allowedUdfs[match]); + } + + // Try to resolve UDFs whose some parameter types are depending of other UDFs: + for(int i = 0; i < toResolveLater.size(); i++){ + udf = toResolveLater.get(i); + // search for a match: + match = binSearch.search(udf, allowedUdfs); + // if no match, add an error: + if (match < 0) + errors.addException(new UnresolvedFunction(udf)); // TODO Add the ADQLOperand position! + // otherwise, metadata may be attached (particularly if the function is built automatically by the syntactic parser): + else if (udf instanceof DefaultUDF) + ((DefaultUDF)udf).setDefinition(allowedUdfs[match]); + } + } + } + + /** + * <p>Tell whether the type of all parameters of the given ADQL function + * is resolved.</p> + * + * <p>A parameter type may not be resolved for 2 main reasons:</p> + * <ul> + * <li>the parameter is a <b>column</b>, but this column has not been successfully resolved. Thus its type is still unknown.</li> + * <li>the parameter is a <b>UDF</b>, but this UDF has not been already resolved. Thus, as for the column, its return type is still unknown. + * But it could be known later if the UDF is resolved later ; a second try should be done afterwards.</li> + * </ul> + * + * @param fct ADQL function whose the parameters' type should be checked. + * + * @return <i>true</i> if the type of all parameters is known, <i>false</i> otherwise. + * + * @since 1.3 + */ + protected final boolean isAllParamTypesResolved(final ADQLFunction fct){ + for(ADQLOperand op : fct.getParameters()){ + if (op.isNumeric() == op.isString()) + return false; + } + return true; + } + + /* ************************************************************************************************* */ + /* METHODS CHECKING THE GEOMETRIES (geometrical functions, coordinate systems and STC-S expressions) */ + /* ************************************************************************************************* */ + + /** + * <p>Check all geometries.</p> + * + * <p>Operations done in this function:</p> + * <ol> + * <li>Check that all geometrical functions are supported</li> + * <li>Check that all explicit (string constant) coordinate system definitions are supported</i></li> + * <li>Check all STC-S expressions (only in {@link RegionFunction} for the moment) and + * Apply the 2 previous checks on them</li> + * </ol> + * + * @param query Query in which geometries must be checked. + * @param errors List of errors to complete in this function each time a geometry item is not supported. + * + * @see #resolveGeometryFunctions(ADQLQuery, BinarySearch, UnresolvedIdentifiersException) + * @see #resolveCoordinateSystems(ADQLQuery, UnresolvedIdentifiersException) + * @see #resolveSTCSExpressions(ADQLQuery, BinarySearch, UnresolvedIdentifiersException) + * + * @since 1.3 + */ + protected void checkGeometries(final ADQLQuery query, final UnresolvedIdentifiersException errors){ + BinarySearch<String,String> binSearch = new BinarySearch<String,String>(){ + @Override + protected int compare(String searchItem, String arrayItem){ + return searchItem.compareToIgnoreCase(arrayItem); + } + }; + + // a. Ensure that all used geometry functions are allowed: + if (allowedGeo != null) + resolveGeometryFunctions(query, binSearch, errors); + + // b. Check whether the coordinate systems are allowed: + if (allowedCoordSys != null) + resolveCoordinateSystems(query, errors); + + // c. Check all STC-S expressions (in RegionFunctions only) + the used coordinate systems (if StringConstant only): + if (allowedGeo == null || (allowedGeo.length > 0 && binSearch.search("REGION", allowedGeo) >= 0)) + resolveSTCSExpressions(query, binSearch, errors); + } + + /** + * Search for all geometrical functions and check whether they are allowed. + * + * @param query Query in which geometrical functions must be checked. + * @param errors List of errors to complete in this function each time a geometrical function is not supported. + * + * @see #checkGeometryFunction(String, ADQLFunction, BinarySearch, UnresolvedIdentifiersException) + * + * @since 1.3 + */ + protected void resolveGeometryFunctions(final ADQLQuery query, final BinarySearch<String,String> binSearch, final UnresolvedIdentifiersException errors){ + ISearchHandler sHandler = new SearchGeometryHandler(); + sHandler.search(query); + + String fctName; + for(ADQLObject result : sHandler){ + fctName = result.getName(); + checkGeometryFunction(fctName, (ADQLFunction)result, binSearch, errors); + } + } + + /** + * <p>Check whether the specified geometrical function is allowed by this implementation.</p> + * + * <p><i>Note: + * If the list of allowed geometrical functions is empty, this function will always add an errors to the given list. + * Indeed, it means that no geometrical function is allowed and so that the specified function is automatically not supported. + * </i></p> + * + * @param fctName Name of the geometrical function to test. + * @param fct The function instance being or containing the geometrical function to check. <i>Note: this function can be the function to test or a function embedding the function under test (i.e. RegionFunction). + * @param binSearch The object to use in order to search a function name inside the list of allowed functions. + * It is able to perform a binary search inside a sorted array of String objects. The interest of + * this object is its compare function which must be overridden and tells how to compare the item + * to search and the items of the array (basically, a non-case-sensitive comparison between 2 strings). + * @param errors List of errors to complete in this function each time a geometrical function is not supported. + * + * @since 1.3 + */ + protected void checkGeometryFunction(final String fctName, final ADQLFunction fct, final BinarySearch<String,String> binSearch, final UnresolvedIdentifiersException errors){ + int match = -1; + if (allowedGeo.length != 0) + match = binSearch.search(fctName, allowedGeo); + if (match < 0) + errors.addException(new UnresolvedFunction("The geometrical function \"" + fctName + "\" is not available in this implementation!", fct)); + } + + /** + * <p>Search all explicit coordinate system declarations, check their syntax and whether they are allowed by this implementation.</p> + * + * <p><i>Note: + * "explicit" means here that all {@link StringConstant} instances. Only coordinate systems expressed as string can + * be parsed and so checked. So if a coordinate system is specified by a column, no check can be done at this stage... + * it will be possible to perform such test only at the execution. + * </i></p> + * + * @param query Query in which coordinate systems must be checked. + * @param errors List of errors to complete in this function each time a coordinate system has a wrong syntax or is not supported. + * + * @see #checkCoordinateSystem(StringConstant, UnresolvedIdentifiersException) + * + * @since 1.3 + */ + protected void resolveCoordinateSystems(final ADQLQuery query, final UnresolvedIdentifiersException errors){ + ISearchHandler sHandler = new SearchCoordSysHandler(); + sHandler.search(query); + for(ADQLObject result : sHandler) + checkCoordinateSystem((StringConstant)result, errors); + } + + /** + * Parse and then check the coordinate system contained in the given {@link StringConstant} instance. + * + * @param adqlCoordSys The {@link StringConstant} object containing the coordinate system to check. + * @param errors List of errors to complete in this function each time a coordinate system has a wrong syntax or is not supported. + * + * @see STCS#parseCoordSys(String) + * @see #checkCoordinateSystem(CoordSys, ADQLOperand, UnresolvedIdentifiersException) + * + * @since 1.3 + */ + protected void checkCoordinateSystem(final StringConstant adqlCoordSys, final UnresolvedIdentifiersException errors){ + String coordSysStr = adqlCoordSys.getValue(); + try{ + checkCoordinateSystem(STCS.parseCoordSys(coordSysStr), adqlCoordSys, errors); + }catch(ParseException pe){ + errors.addException(new ParseException(pe.getMessage())); // TODO Missing object position! + } + } + + /** + * Check whether the given coordinate system is allowed by this implementation. + * + * @param coordSys Coordinate system to test. + * @param operand The operand representing or containing the coordinate system under test. + * @param errors List of errors to complete in this function each time a coordinate system is not supported. + * + * @since 1.3 + */ + protected void checkCoordinateSystem(final CoordSys coordSys, final ADQLOperand operand, final UnresolvedIdentifiersException errors){ + if (coordSysRegExp != null && coordSys != null && !coordSys.toFullSTCS().matches(coordSysRegExp)) + errors.addException(new ParseException("Coordinate system \"" + ((operand instanceof StringConstant) ? ((StringConstant)operand).getValue() : coordSys.toString()) + "\" (= \"" + coordSys.toFullSTCS() + "\") not allowed in this implementation.")); // TODO Missing object position! + List of accepted coordinate systems + } + + /** + * <p>Search all STC-S expressions inside the given query, parse them (and so check their syntax) and then determine + * whether the declared coordinate system and the expressed region are allowed in this implementation.</p> + * + * <p><i>Note: + * In the current ADQL language definition, STC-S expressions can be found only as only parameter of the REGION function. + * </i></p> + * + * @param query Query in which STC-S expressions must be checked. + * @param binSearch The object to use in order to search a region name inside the list of allowed functions/regions. + * It is able to perform a binary search inside a sorted array of String objects. The interest of + * this object is its compare function which must be overridden and tells how to compare the item + * to search and the items of the array (basically, a non-case-sensitive comparison between 2 strings). + * @param errors List of errors to complete in this function each time the STC-S syntax is wrong or each time the declared coordinate system or region is not supported. + * + * @see STCS#parseRegion(String) + * @see #checkRegion(Region, RegionFunction, BinarySearch, UnresolvedIdentifiersException) + * + * @since 1.3 + */ + protected void resolveSTCSExpressions(final ADQLQuery query, final BinarySearch<String,String> binSearch, final UnresolvedIdentifiersException errors){ + // Search REGION functions: + ISearchHandler sHandler = new SearchRegionHandler(); + sHandler.search(query); + + // Parse and check their STC-S expression: + String stcs; + Region region; + for(ADQLObject result : sHandler){ + try{ + // get the STC-S expression: + stcs = ((StringConstant)((RegionFunction)result).getParameter(0)).getValue(); + + // parse the STC-S expression (and so check the syntax): + region = STCS.parseRegion(stcs); + + // check whether the regions (this one + the possible inner ones) and the coordinate systems are allowed: + checkRegion(region, (RegionFunction)result, binSearch, errors); + }catch(ParseException pe){ + errors.addException(new ParseException(pe.getMessage())); // TODO Missing object position! + } + } + } + + /** + * <p>Check the given region.</p> + * + * <p>The following points are checked in this function:</p> + * <ul> + * <li>whether the coordinate system is allowed</li> + * <li>whether the type of region is allowed</li> + * <li>whether the inner regions are correct (here this function is called recursively on each inner region).</li> + * </ul> + * + * @param r The region to check. + * @param fct The REGION function containing the region to check. + * @param errors List of errors to complete in this function if the given region or its inner regions are not supported. + * + * @see #checkCoordinateSystem(CoordSys, ADQLOperand, UnresolvedIdentifiersException) + * @see #checkGeometryFunction(String, ADQLFunction, BinarySearch, UnresolvedIdentifiersException) + * + * @since 1.3 + */ + protected void checkRegion(final Region r, final RegionFunction fct, final BinarySearch<String,String> binSearch, final UnresolvedIdentifiersException errors){ + if (r == null) + return; + + // Check the coordinate system (if any): + if (r.coordSys != null) + checkCoordinateSystem(r.coordSys, fct, errors); + + // Check that the region type is allowed: + if (allowedGeo != null){ + if (allowedGeo.length == 0) + errors.addException(new UnresolvedFunction("The region type \"" + r.type + "\" is not available in this implementation!", fct)); + else + checkGeometryFunction((r.type == RegionType.POSITION) ? "POINT" : r.type.toString(), fct, binSearch, errors); + } + + // Check all the inner regions: + if (r.regions != null){ + for(Region innerR : r.regions) + checkRegion(innerR, fct, binSearch, errors); + } + } + + /* **************************************************** */ + /* METHODS CHECKING TYPES UNKNOWN WHILE CHECKING SYNTAX */ + /* **************************************************** */ + + /** + * <p>Search all operands whose the type is not yet known and try to resolve it now + * and to check whether it matches the type expected by the syntactic parser.</p> + * + * <p> + * Only two operands may have an unresolved type: columns and user defined functions. + * Indeed, their type can be resolved only if the list of available columns and UDFs is known, + * and if columns and UDFs used in the query are resolved successfully. + * </p> + * + * <p> + * When an operand type is still unknown, they will own the three kinds of type and + * so this function won't raise an error: it is thus automatically on the expected type. + * This behavior is perfectly correct because if the type is not resolved + * that means the item/operand has not been resolved in the previous steps and so that + * an error about this item has already been raised. + * </p> + * + * <p><i><b>Important note:</b> + * This function does not check the types exactly, but just roughly by considering only three categories: + * string, numeric and geometry. + * </i></p> + * + * @param query Query in which unknown types must be resolved and checked. + * @param errors List of errors to complete in this function each time a types does not match to the expected one. + * + * @see UnknownType + * + * @since 1.3 + */ + protected void checkTypes(final ADQLQuery query, final UnresolvedIdentifiersException errors){ + // Search all unknown types: + ISearchHandler sHandler = new SearchUnknownTypeHandler(); + sHandler.search(query); + + // Check whether their type matches the expected one: + UnknownType unknown; + for(ADQLObject result : sHandler){ + unknown = (UnknownType)result; + switch(unknown.getExpectedType()){ + case 'G': + case 'g': + if (!unknown.isGeometry()) + errors.addException(new ParseException("Type mismatch! A geometry was expected instead of \"" + unknown.toADQL() + "\".")); // TODO Add the ADQLOperand position! + break; + case 'N': + case 'n': + if (!unknown.isNumeric()) + errors.addException(new ParseException("Type mismatch! A numeric value was expected instead of \"" + unknown.toADQL() + "\".")); // TODO Add the ADQLOperand position! + break; + case 'S': + case 's': + if (!unknown.isString()) + errors.addException(new ParseException("Type mismatch! A string value was expected instead of \"" + unknown.toADQL() + "\".")); // TODO Add the ADQLOperand position! + break; + } + } + } + + /* ******************************** */ + /* METHODS CHECKING THE SUB-QUERIES */ + /* ******************************** */ + + /** + * <p>Search all sub-queries found in the given query but not in the clause FROM. + * These sub-queries are then checked using {@link #check(ADQLQuery, Stack)}.</p> + * + * <b>Fathers stack</b> + * <p> + * Each time a sub-query must be checked with {@link #check(ADQLQuery, Stack)}, + * the list of all columns available in each of its father queries must be provided. + * This function is composing itself this stack by adding the given list of available + * columns (= all columns resolved in the given query) at the end of the given stack. + * If this stack is given empty, then a new stack is created. + * </p> + * <p> + * This modification of the given stack is just the execution time of this function. + * Before returning, this function removes the last item of the stack. + * </p> + * + * + * @param query Query in which sub-queries must be checked. + * @param fathersList List of all columns available in the father queries and that should be accessed in sub-queries. + * Each item of this stack is a list of columns available in each father-level query. + * <i>Note: this parameter is NULL if this function is called with the root/father query as parameter.</i> + * @param availableColumns List of all columns resolved in the given query. + * @param errors List of errors to complete in this function each time a semantic error is encountered. + * + * @since 1.3 + */ + protected void checkSubQueries(final ADQLQuery query, Stack<SearchColumnList> fathersList, final SearchColumnList availableColumns, final UnresolvedIdentifiersException errors){ + // Check sub-queries outside the clause FROM: + ISearchHandler sHandler = new SearchSubQueryHandler(); + sHandler.search(query); + if (sHandler.getNbMatch() > 0){ + + // Push the list of columns into the father columns stack: + if (fathersList == null) + fathersList = new Stack<SearchColumnList>(); + fathersList.push(availableColumns); + + // Check each found sub-query: + for(ADQLObject result : sHandler){ + try{ + check((ADQLQuery)result, fathersList); + }catch(UnresolvedIdentifiersException uie){ + Iterator<ParseException> itPe = uie.getErrors(); + while(itPe.hasNext()) + errors.addException(itPe.next()); + } + } + + // Pop the list of columns from the father columns stack: + fathersList.pop(); + } + } + /* *************** */ /* SEARCH HANDLERS */ /* *************** */ @@ -462,7 +1226,7 @@ public class DBChecker implements QueryChecker { * Lets searching all tables. * * @author Grégory Mantelet (CDS) - * @version 07/2011 + * @version 1.0 (07/2011) */ private static class SearchTableHandler extends SimpleSearchHandler { @Override @@ -475,7 +1239,7 @@ public class DBChecker implements QueryChecker { * Lets searching all wildcards. * * @author Grégory Mantelet (CDS) - * @version 09/2011 + * @version 1.0 (09/2011) */ private static class SearchWildCardHandler extends SimpleSearchHandler { @Override @@ -488,7 +1252,7 @@ public class DBChecker implements QueryChecker { * Lets searching column references. * * @author Grégory Mantelet (CDS) - * @version 11/2011 + * @version 1.0 (11/2011) */ private static class SearchColReferenceHandler extends SimpleSearchHandler { @Override @@ -527,4 +1291,168 @@ public class DBChecker implements QueryChecker { } } + /** + * Let searching user defined functions. + * + * @author Grégory Mantelet (ARI) + * @version 1.3 (10/2014) + * @since 1.3 + */ + private static class SearchUDFHandler extends SimpleSearchHandler { + @Override + protected boolean match(ADQLObject obj){ + return (obj instanceof UserDefinedFunction); + } + } + + /** + * Let searching geometrical functions. + * + * @author Grégory Mantelet (ARI) + * @version 1.3 (10/2014) + * @since 1.3 + */ + private static class SearchGeometryHandler extends SimpleSearchHandler { + @Override + protected boolean match(ADQLObject obj){ + return (obj instanceof GeometryFunction); + } + } + + /** + * <p>Let searching all ADQL objects whose the type was not known while checking the syntax of the ADQL query. + * These objects are {@link ADQLColumn}s and {@link UserDefinedFunction}s.</p> + * + * <p><i><b>Important note:</b> + * Only {@link UnknownType} instances having an expected type equals to 'S' (or 's' ; for string) or 'N' (or 'n' ; for numeric) + * are kept by this handler. Others are ignored. + * </i></p> + * + * @author Grégory Mantelet (ARI) + * @version 1.3 (10/2014) + * @since 1.3 + */ + private static class SearchUnknownTypeHandler extends SimpleSearchHandler { + @Override + protected boolean match(ADQLObject obj){ + if (obj instanceof UnknownType){ + char expected = ((UnknownType)obj).getExpectedType(); + return (expected == 'G' || expected == 'g' || expected == 'S' || expected == 's' || expected == 'N' || expected == 'n'); + }else + return false; + } + } + + /** + * Let searching all explicit declaration of coordinate systems. + * So, only {@link StringConstant} objects will be returned. + * + * @author Grégory Mantelet (ARI) + * @version 1.3 (10/2014) + * @since 1.3 + */ + private static class SearchCoordSysHandler extends SimpleSearchHandler { + @Override + protected boolean match(ADQLObject obj){ + if (obj instanceof PointFunction || obj instanceof BoxFunction || obj instanceof CircleFunction || obj instanceof PolygonFunction) + return (((GeometryFunction)obj).getCoordinateSystem() instanceof StringConstant); + else + return false; + } + + @Override + protected void addMatch(ADQLObject matchObj, ADQLIterator it){ + results.add(((GeometryFunction)matchObj).getCoordinateSystem()); + } + + } + + /** + * Let searching all {@link RegionFunction}s. + * + * @author Grégory Mantelet (ARI) + * @version 1.3 (10/2014) + * @since 1.3 + */ + private static class SearchRegionHandler extends SimpleSearchHandler { + @Override + protected boolean match(ADQLObject obj){ + if (obj instanceof RegionFunction) + return (((RegionFunction)obj).getParameter(0) instanceof StringConstant); + else + return false; + } + + } + + /** + * <p>Implement the binary search algorithm over a sorted array.</p> + * + * <p> + * The only difference with the standard implementation of Java is + * that this object lets perform research with a different type + * of object than the types of array items. + * </p> + * + * <p> + * For that reason, the "compare" function must always be implemented. + * </p> + * + * @author Grégory Mantelet (ARI) + * @version 1.3 (10/2014) + * + * @param <T> Type of items stored in the array. + * @param <S> Type of the item to search. + * + * @since 1.3 + */ + protected static abstract class BinarySearch< T, S > { + private int s, e, m, comp; + + /** + * <p>Search the given item in the given array.</p> + * + * <p> + * In case the given object matches to several items of the array, + * this function will return the smallest index, pointing thus to the first + * of all matches. + * </p> + * + * @param searchItem Object for which a corresponding array item must be searched. + * @param array Array in which the given object must be searched. + * + * @return The array index of the first item of all matches. + */ + public int search(final S searchItem, final T[] array){ + s = 0; + e = array.length - 1; + while(s < e){ + // middle of the sorted array: + m = s + ((e - s) / 2); + // compare the fct with the middle item of the array: + comp = compare(searchItem, array[m]); + // if the fct is after, trigger the inspection of the right part of the array: + if (comp > 0) + s = m + 1; + // otherwise, the left part: + else + e = m; + } + if (s != e || compare(searchItem, array[s]) != 0) + return -1; + else + return s; + } + + /** + * Compare the search item and the array item. + * + * @param searchItem Item whose a corresponding value must be found in the array. + * @param arrayItem An item of the array. + * + * @return Negative value if searchItem is less than arrayItem, 0 if they are equals, or a positive value if searchItem is greater. + */ + protected abstract int compare(final S searchItem, final T arrayItem); + } + } diff --git a/src/adql/db/DBColumn.java b/src/adql/db/DBColumn.java index a803717e449bb7d1bf8594a3aee51a1b632eb2f9..c987e062cc161f5b20488c8e4652accc00455463 100644 --- a/src/adql/db/DBColumn.java +++ b/src/adql/db/DBColumn.java @@ -16,7 +16,8 @@ package adql.db; * 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) + * Copyright 2011,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS), + * Astronomisches Rechen Institut (ARI) */ /** @@ -27,8 +28,8 @@ package adql.db; * and corresponds to a real column in the "database" with its DB name ({@link #getDBName()}). * </p> * - * @author Grégory Mantelet (CDS) - * @version 08/2011 + * @author Grégory Mantelet (CDS;ARI) + * @version 1.3 (10/2014) */ public interface DBColumn { @@ -46,6 +47,19 @@ public interface DBColumn { */ public String getDBName(); + /** + * <p>Get the type of this column (as closed as possible from the "database" type).</p> + * + * <p><i>Note: + * The returned type should be as closed as possible from a type listed by the IVOA in the TAP protocol description into the section UPLOAD. + * </i></p> + * + * @return Its type. + * + * @since 1.3 + */ + public DBType getDatatype(); + /** * Gets the table which contains this {@link DBColumn}. * diff --git a/src/adql/db/DBCommonColumn.java b/src/adql/db/DBCommonColumn.java index cab30f6f86cf8be463679d0fbf78fdb1c8c22257..8c5d3ba8e3c9ce5a8f4569c3c575060933adbfdf 100644 --- a/src/adql/db/DBCommonColumn.java +++ b/src/adql/db/DBCommonColumn.java @@ -16,12 +16,13 @@ package adql.db; * 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 2014 - Astronomishes Rechen Institut (ARI) + * Copyright 2014 - Astronomisches Rechen Institut (ARI) */ import java.util.ArrayList; import java.util.Iterator; +import adql.db.exception.UnresolvedJoin; import adql.query.ADQLQuery; /** @@ -33,7 +34,7 @@ import adql.query.ADQLQuery; * in case of several JOINs. * * @author Grégory Mantelet (ARI) - gmantele@ari.uni-heidelberg.de - * @version 1.2 (11/2013) + * @version 1.3 (10/2014) * @since 1.2 */ public class DBCommonColumn implements DBColumn { @@ -54,8 +55,13 @@ public class DBCommonColumn implements DBColumn { * * @param leftCol Column of the left join table. May be a {@link DBCommonColumn}. * @param rightCol Column of the right join table. May be a {@link DBCommonColumn}. + * + * @throws UnresolvedJoin If the type of the two given columns are not roughly (just testing numeric, string or geometry) compatible. */ - public DBCommonColumn(final DBColumn leftCol, final DBColumn rightCol){ + public DBCommonColumn(final DBColumn leftCol, final DBColumn rightCol) throws UnresolvedJoin{ + // Test whether type of both columns are compatible: + if (leftCol.getDatatype() != null && rightCol.getDatatype() != null && !leftCol.getDatatype().isCompatible(rightCol.getDatatype())) + throw new UnresolvedJoin("JOIN impossible: incompatible column types when trying to join the columns " + leftCol.getADQLName() + " (" + leftCol.getDatatype() + ") and " + rightCol.getADQLName() + " (" + rightCol.getDatatype() + ")!"); // LEFT COLUMN: if (leftCol instanceof DBCommonColumn){ @@ -83,7 +89,6 @@ public class DBCommonColumn implements DBColumn { // add the table to cover: addCoveredTable(rightCol.getTable()); } - } /** @@ -112,6 +117,11 @@ public class DBCommonColumn implements DBColumn { return generalColumnDesc.getDBName(); } + @Override + public final DBType getDatatype(){ + return generalColumnDesc.getDatatype(); + } + @Override public final DBTable getTable(){ return null; diff --git a/src/tap/metadata/TAPType.java b/src/adql/db/DBType.java similarity index 51% rename from src/tap/metadata/TAPType.java rename to src/adql/db/DBType.java index 1990d56b98206001bac4ee2c79076b368ed89aec..87f6c05c81674a98bed60cc17ec67a7c2947eb0a 100644 --- a/src/tap/metadata/TAPType.java +++ b/src/adql/db/DBType.java @@ -1,14 +1,14 @@ -package tap.metadata; +package adql.db; /* - * This file is part of TAPLibrary. + * This file is part of ADQLLibrary. * - * TAPLibrary is free software: you can redistribute it and/or modify + * 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. * - * TAPLibrary is distributed in the hope that it will be useful, + * 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. @@ -16,35 +16,35 @@ package tap.metadata; * You should have received a copy of the GNU Lesser General Public License * along with TAPLibrary. If not, see <http://www.gnu.org/licenses/>. * - * Copyright 2014 - Astronomishes Rechen Institut (ARI) + * Copyright 2014 - Astronomisches Rechen Institut (ARI) */ /** * * <p> - * Describe a full TAP column type as it is described in the IVOA document. + * Describe a full column type as it is described in the IVOA document of TAP. * Thus, this object contains 2 attributes: <code>type</code> (or datatype) and <code>length</code> (or size). * </p> * * <p>The length/size may be not defined ; in this case, its value is set to {@link #NO_LENGTH} or is negative or null.</p> * - * <p>All datatypes declared in the IVOA recommendation document of TAP are listed in an enumeration type: {@link TAPDatatype}. + * <p>All datatypes declared in the IVOA recommendation document of TAP are listed in an enumeration type: {@link DBDatatype}. * It is used to set the attribute type/datatype of this class.</p> * - * @author Grégory Mantelet (ARI) - gmantele@ari.uni-heidelberg.de - * @version 2.0 (06/2014) - * @since 2.0 + * @author Grégory Mantelet (ARI) + * @version 1.3 (10/2014) + * @since 1.3 */ -public class TAPType { +public class DBType { /** * List of all datatypes declared in the IVOA recommendation of TAP (in the section UPLOAD). * - * @author Grégory Mantelet (ARI) - gmantele@ari.uni-heidelberg.de - * @version 2.0 (06/2014) - * @since 2.0 + * @author Grégory Mantelet (ARI) + * @version 1.3 (10/2014) + * @since 1.3 */ - public static enum TAPDatatype{ + public static enum DBDatatype{ SMALLINT, INTEGER, BIGINT, REAL, DOUBLE, BINARY, VARBINARY, CHAR, VARCHAR, BLOB, CLOB, TIMESTAMP, POINT, REGION; } @@ -52,7 +52,7 @@ public class TAPType { public static final int NO_LENGTH = -1; /** Datatype of a column. */ - public final TAPDatatype type; + public final DBDatatype type; /** The length parameter (only few datatypes need this parameter: char, varchar, binary and varbinary). */ public final int length; @@ -62,7 +62,7 @@ public class TAPType { * * @param datatype Column datatype. */ - public TAPType(final TAPDatatype datatype){ + public DBType(final DBDatatype datatype){ this(datatype, NO_LENGTH); } @@ -72,22 +72,71 @@ public class TAPType { * @param datatype Column datatype. * @param length Length of the column value (needed only for datatypes like char, varchar, binary and varbinary). */ - public TAPType(final TAPDatatype datatype, final int length){ + public DBType(final DBDatatype datatype, final int length){ if (datatype == null) throw new NullPointerException("Missing TAP column datatype !"); this.type = datatype; this.length = length; } - /** - * Convert this TAP column type into a VOTable field type. - * - * @return The corresponding VOTable field type. - * - * @see VotType#VotType(TAPType) - */ - public VotType toVotType(){ - return new VotType(this); + public boolean isNumeric(){ + switch(type){ + case SMALLINT: + case INTEGER: + case BIGINT: + case REAL: + case DOUBLE: + /* Note: binaries are also included here because they can also be considered as Numeric, + * but not for JOINs. */ + case BINARY: + case VARBINARY: + case BLOB: + return true; + default: + return false; + } + } + + public boolean isBinary(){ + switch(type){ + case BINARY: + case VARBINARY: + case BLOB: + return true; + default: + return false; + } + } + + public boolean isString(){ + switch(type){ + case CHAR: + case VARCHAR: + case CLOB: + case TIMESTAMP: + return true; + default: + return false; + } + } + + public boolean isGeometry(){ + return (type == DBDatatype.POINT || type == DBDatatype.REGION); + } + + public boolean isCompatible(final DBType t){ + if (t == null) + return false; + else if (isBinary() == t.isBinary()) + return (type == DBDatatype.BLOB && t.type == DBDatatype.BLOB) || (type != DBDatatype.BLOB && t.type != DBDatatype.BLOB); + else if (isNumeric() == t.isNumeric()) + return true; + else if (isGeometry() == t.isGeometry()) + return (type == t.type); + else if (isString()) + return (type == DBDatatype.CLOB && t.type == DBDatatype.CLOB) || (type != DBDatatype.CLOB && t.type != DBDatatype.CLOB); + else + return (type == t.type); } @Override diff --git a/src/adql/db/DefaultDBColumn.java b/src/adql/db/DefaultDBColumn.java index 8496501aa3ee7ecc3fb15619c8bddecafb98e3ef..a4ed9e3bc557bc8cba391bc68c35e269dbf27ea9 100644 --- a/src/adql/db/DefaultDBColumn.java +++ b/src/adql/db/DefaultDBColumn.java @@ -16,20 +16,27 @@ package adql.db; * 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) + * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS), + * Astronomisches Rechen Institut (ARI) */ /** * Default implementation of {@link DBColumn}. * - * @author Grégory Mantelet (CDS) - * @version 08/2011 + * @author Grégory Mantelet (CDS;ARI) + * @version 1.3 (10/2014) */ public class DefaultDBColumn implements DBColumn { + /** Name of the column in the "database". */ protected String dbName; + /** Type of the column in the "database". + * <i>Note: This should be one of the types listed by the IVOA in the TAP description.</i> + * @since 1.3 */ + protected DBType type; + /** Table in which this column exists. */ protected DBTable table; - + /** Name that this column must have in ADQL queries. */ protected String adqlName = null; /** @@ -40,10 +47,30 @@ public class DefaultDBColumn implements DBColumn { * 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) + * @see #DefaultDBColumn(String, String, DBType, DBTable) */ public DefaultDBColumn(final String dbName, final DBTable table){ - this(dbName, dbName, table); + this(dbName, dbName, null, table); + } + + /** + * 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 type Type of the column. + * <i>Note: there is no default value. Consequently if this parameter is NULL, + * the type should be considered as unknown. It means that any comparison with + * any type will always return 'true'.</i> + * @param table DB table which contains this column. + * + * @see #DefaultDBColumn(String, String, DBType, DBTable) + * + * @since 1.3 + */ + public DefaultDBColumn(final String dbName, final DBType type, final DBTable table){ + this(dbName, dbName, type, table); } /** @@ -56,13 +83,38 @@ public class DefaultDBColumn implements DBColumn { * <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, DBType, DBTable) */ public DefaultDBColumn(final String dbName, final String adqlName, final DBTable table){ + this(dbName, adqlName, null, 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 type Type of the column. + * <i>Note: there is no default value. Consequently if this parameter is NULL, + * the type should be considered as unknown. It means that any comparison with + * any type will always return 'true'.</i> + * @param table DB table which contains this column. + * + * @since 1.3 + */ + public DefaultDBColumn(final String dbName, final String adqlName, final DBType type, final DBTable table){ this.dbName = dbName; this.adqlName = adqlName; + this.type = type; this.table = table; } + @Override public final String getADQLName(){ return adqlName; } @@ -72,10 +124,38 @@ public class DefaultDBColumn implements DBColumn { this.adqlName = adqlName; } + @Override + public final DBType getDatatype(){ + return type; + } + + /** + * <p>Set the type of this column.</p> + * + * <p><i>Note 1: + * The given type should be as closed as possible from a type listed by the IVOA in the TAP protocol description into the section UPLOAD. + * </i></p> + * + * <p><i>Note 2: + * there is no default value. Consequently if this parameter is NULL, + * the type should be considered as unknown. It means that any comparison with + * any type will always return 'true'. + * </i></p> + * + * @param type New type of this column. + * + * @since 1.3 + */ + public final void setDatatype(final DBType type){ + this.type = type; + } + + @Override public final String getDBName(){ return dbName; } + @Override public final DBTable getTable(){ return table; } @@ -84,8 +164,9 @@ public class DefaultDBColumn implements DBColumn { this.table = table; } + @Override public DBColumn copy(final String dbName, final String adqlName, final DBTable dbTable){ - return new DefaultDBColumn(dbName, adqlName, dbTable); + return new DefaultDBColumn(dbName, adqlName, type, dbTable); } } diff --git a/src/adql/db/FunctionDef.java b/src/adql/db/FunctionDef.java new file mode 100644 index 0000000000000000000000000000000000000000..a8071eecb96545e846316d58c83a65de0e13eb43 --- /dev/null +++ b/src/adql/db/FunctionDef.java @@ -0,0 +1,476 @@ +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 2014 - Astronomisches Rechen Institut (ARI) + */ + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import adql.db.DBType.DBDatatype; +import adql.parser.ParseException; +import adql.query.operand.function.ADQLFunction; + +/** + * <p>Definition of any function that could be used in ADQL queries.</p> + * + * <p> + * A such definition can be built manually thanks to the different constructors of this class, + * or by parsing a string function definition form using the static function {@link #parse(String)}. + * </p> + * + * <p> + * The syntax of the expression expected by {@link #parse(String)} is the same as the one used to build + * the string returned by {@link #toString()}. Here is this syntax: + * </p> + * <pre>{fctName}([{param1Name} {param1Type}, ...])[ -> {returnType}]</pre> + * + * <p> + * A description of this function may be set thanks to the public class attribute {@link #description}. + * </p> + * + * @author Grégory Mantelet (ARI) + * @version 1.3 (10/2014) + * + * @since 1.3 + */ +public class FunctionDef implements Comparable<FunctionDef> { + /** Regular expression for what should be a function or parameter name - a regular identifier. */ + protected final static String regularIdentifierRegExp = "[a-zA-Z]+[0-9a-zA-Z_]*"; + /** Rough regular expression for a function return type or a parameter type. + * The exact type is not checked here ; just the type name syntax is tested, not its value. + * This regular expression allows a type to have exactly one parameter (which is generally the length of a character or binary string. */ + protected final static String typeRegExp = "([a-zA-Z]+[0-9a-zA-Z]*)(\\(\\s*([0-9]+)\\s*\\))?"; + /** Rough regular expression for a function parameters' list. */ + protected final static String fctParamsRegExp = "\\s*[^,]+\\s*(,\\s*[^,]+\\s*)*"; + /** Rough regular expression for a function parameter: a name (see {@link #regularIdentifierRegExp}) and a type (see {@link #typeRegExp}). */ + protected final static String fctParamRegExp = "\\s*(" + regularIdentifierRegExp + ")\\s+" + typeRegExp + "\\s*"; + /** Rough regular expression for a whole function definition. */ + protected final static String fctDefRegExp = "\\s*(" + regularIdentifierRegExp + ")\\s*\\(([a-zA-Z0-9,() \r\n\t]*)\\)(\\s*->\\s*(" + typeRegExp + "))?\\s*"; + + /** Pattern of a function definition. This object has been compiled with {@link #fctDefRegExp}. */ + protected final static Pattern fctPattern = Pattern.compile(fctDefRegExp); + /** Pattern of a single parameter definition. This object has been compiled with {@link #fctParamRegExp}. */ + protected final static Pattern paramPattern = Pattern.compile(fctParamRegExp); + + /** Name of the function. */ + public final String name; + + /** Description of this function. */ + public String description = null; + + /** Type of the result returned by this function. */ + public final DBType returnType; + /** Indicate whether the return type is a string. */ + protected final boolean isString; + /** Indicate whether the return type is a numeric. */ + protected final boolean isNumeric; + /** Indicate whether the return type is a geometry. */ + protected final boolean isGeometry; + + /** Total number of parameters. */ + public final int nbParams; + /** List of all the parameters of this function. */ + protected final FunctionParam[] params; + + /** <p>String representation of this function.</p> + * <p>The syntax of this representation is the following <i>(items between brackets are optional)</i>:</p> + * <pre>{fctName}([{param1Name} {param1Type}, ...])[ -> {returnType}]</pre> */ + private final String serializedForm; + + /** <p>String representation of this function dedicated to comparison with any function signature.</p> + * <p>This form is different from the serialized form on the following points:</p> + * <ul> + * <li>the function name is always in lower case.</li> + * <li>each parameter is represented by a string of 3 characters, one for each kind of type (in the order): numeric, string, geometry. + * Each character is either a 0 or 1, so that indicating whether the parameter is of that kind of type.</li> + * <li>no return type.</li> + * </ul> + * <p>So the syntax of this form is the following <i>(items between brackets are optional ; xxx is a string of 3 characters, each being either 0 or 1)</i>:</p> + * <pre>{fctName}([xxx, ...])</pre> */ + private final String compareForm; + + /** + * <p>Definition of a function parameter.</p> + * + * <p>This definition is composed of two items: the name and the type of the parameter.</p> + * + * @author Grégory Mantelet (ARI) + * @version 1.3 (10/2014) + * @since 1.3 + */ + public static final class FunctionParam { + /** Parameter name. <i>Ensured not null</i> */ + public final String name; + /** Parameter type. <i>Ensured not null</i> */ + public final DBType type; + + /** + * Create a function parameter. + * + * @param paramName Name of the parameter to create. <i>MUST NOT be NULL</i> + * @param paramType Type of the parameter to create. <i>MUST NOT be NULL</i> + */ + public FunctionParam(final String paramName, final DBType paramType){ + if (paramName == null) + throw new NullPointerException("Missing name! The function parameter can not be created."); + if (paramType == null) + throw new NullPointerException("Missing type! The function parameter can not be created."); + this.name = paramName; + this.type = paramType; + } + } + + /** + * <p>Create a function definition.</p> + * + * <p>The created function will have <b>no return type</b> and <b>no parameter</b>.</p> + * + * @param fctName Name of the function. + */ + public FunctionDef(final String fctName){ + this(fctName, null, null); + } + + /** + * <p>Create a function definition.</p> + * + * <p>The created function will have a return type (if the provided one is not null) and <b>no parameter</b>.</p> + * + * @param fctName Name of the function. + * @param returnType Return type of the function. <i>If NULL, this function will have no return type</i> + */ + public FunctionDef(final String fctName, final DBType returnType){ + this(fctName, returnType, null); + } + + /** + * <p>Create a function definition.</p> + * + * <p>The created function will have <b>no return type</b> and some parameters (except if the given array is NULL or empty).</p> + * + * @param fctName Name of the function. + * @param params Parameters of this function. <i>If NULL or empty, this function will have no parameter.</i> + */ + public FunctionDef(final String fctName, final FunctionParam[] params){ + this(fctName, null, params); + } + + public FunctionDef(final String fctName, final DBType returnType, final FunctionParam[] params){ + // Set the name: + if (fctName == null) + throw new NullPointerException("Missing name! Can not create this function definition."); + this.name = fctName; + + // Set the parameters: + this.params = (params == null || params.length == 0) ? null : params; + this.nbParams = (params == null) ? 0 : params.length; + + // Set the return type; + this.returnType = returnType; + if (returnType != null){ + isNumeric = returnType.isNumeric(); + isString = returnType.isString(); + isGeometry = returnType.isGeometry(); + }else + isNumeric = isString = isGeometry = false; + + // Serialize in Strings (serializedForm and compareForm) this function definition: + StringBuffer bufSer = new StringBuffer(name), bufCmp = new StringBuffer(name.toLowerCase()); + bufSer.append('('); + for(int i = 0; i < nbParams; i++){ + bufSer.append(params[i].name).append(' ').append(params[i].type); + bufCmp.append(params[i].type.isNumeric() ? '1' : '0').append(params[i].type.isString() ? '1' : '0').append(params[i].type.isGeometry() ? '1' : '0'); + if (i + 1 < nbParams) + bufSer.append(", "); + } + bufSer.append(')'); + if (returnType != null) + bufSer.append(" -> ").append(returnType); + serializedForm = bufSer.toString(); + compareForm = bufCmp.toString(); + } + + /** + * Tell whether this function returns a numeric. + * + * @return <i>true</i> if this function returns a numeric, <i>false</i> otherwise. + */ + public final boolean isNumeric(){ + return isNumeric; + } + + /** + * Tell whether this function returns a string. + * + * @return <i>true</i> if this function returns a string, <i>false</i> otherwise. + */ + public final boolean isString(){ + return isString; + } + + /** + * Tell whether this function returns a geometry. + * + * @return <i>true</i> if this function returns a geometry, <i>false</i> otherwise. + */ + public final boolean isGeometry(){ + return isGeometry; + } + + /** + * Get the number of parameters required by this function. + * + * @return Number of required parameters. + */ + public final int getNbParams(){ + return nbParams; + } + + /** + * Get the definition of the indParam-th parameter of this function. + * + * @param indParam Index of the parameter whose the definition must be returned. + * + * @return Definition of the specified parameter. + * + * @throws ArrayIndexOutOfBoundsException If the given index is negative or bigger than the number of parameters. + */ + public final FunctionParam getParam(final int indParam) throws ArrayIndexOutOfBoundsException{ + if (indParam < 0 || indParam >= nbParams) + throw new ArrayIndexOutOfBoundsException(indParam); + else + return params[indParam]; + } + + /** + * <p>Let parsing the serialized form of a function definition.</p> + * + * <p>The expected syntax is <i>(items between brackets are optional)</i>:</p> + * <pre>{fctName}([{param1Name} {param1Type}, ...])[ -> {returnType}]</pre> + * + * <p> + * Allowed parameter types and return types should be one the types listed by the UPLOAD section of the TAP recommendation document. + * These types are listed in the enumeration object {@link DBType}. + * However, other types should be accepted like the common database types...but it should be better to not rely on that + * since the conversion of those types to TAP types should not be exactly what is expected. + * </p> + * + * @param strDefinition Serialized function definition to parse. + * + * @return The object representation of the given string definition. + * + * @throws ParseException If the given string has a wrong syntax or uses unknown types. + */ + public static FunctionDef parse(final String strDefinition) throws ParseException{ + if (strDefinition == null) + throw new NullPointerException("Missing string definition to build a FunctionDef!"); + + // Check the global syntax of the function definition: + Matcher m = fctPattern.matcher(strDefinition); + if (m.matches()){ + + // Get the function name: + String fctName = m.group(1); + + // Parse and get the return type: + DBType returnType = null; + if (m.group(3) != null){ + returnType = parseType(m.group(5), (m.group(7) == null) ? DBType.NO_LENGTH : Integer.parseInt(m.group(7))); + if (returnType == null) + throw new ParseException("Unknown return type: \"" + m.group(4).trim() + "\"!"); + } + + // Get the parameters, if any: + String paramsList = m.group(2); + FunctionParam[] params = null; + if (paramsList != null && paramsList.trim().length() > 0){ + + // Check the syntax of the parameters' list: + if (!paramsList.matches(fctParamsRegExp)) + throw new ParseException("Wrong parameters syntax! Expected syntax: \"(<regular_identifier> <type_name> (, <regular_identifier> <type_name>)*)\", where <regular_identifier>=\"[a-zA-Z]+[a-zA-Z0-9_]*\", <type_name> should be one of the types described in the UPLOAD section of the TAP documentation. Examples of good syntax: \"()\", \"(param INTEGER)\", \"(param1 INTEGER, param2 DOUBLE)\""); + + // Split all the parameter definitions: + String[] paramsSplit = paramsList.split(","); + params = new FunctionParam[paramsSplit.length]; + DBType paramType; + + // For each parameter definition... + for(int i = 0; i < params.length; i++){ + m = paramPattern.matcher(paramsSplit[i]); + if (m.matches()){ + + // ...parse and get the parameter type: + paramType = parseType(m.group(2), (m.group(4) == null) ? DBType.NO_LENGTH : Integer.parseInt(m.group(4))); + + // ...build the parameter definition object: + if (paramType == null) + throw new ParseException("Unknown type for the parameter \"" + m.group(1) + "\": \"" + m.group(2) + ((m.group(3) == null) ? "" : m.group(3)) + "\"!"); + else + params[i] = new FunctionParam(m.group(1), paramType); + }else + // note: should never happen because we have already check the syntax of the whole parameters list before parsing each individual parameter. + throw new ParseException("Wrong syntax for the " + (i + 1) + "-th parameter: \"" + paramsSplit[i].trim() + "\"! Expected syntax: \"(<regular_identifier> <type_name> (, <regular_identifier> <type_name>)*)\", where <regular_identifier>=\"[a-zA-Z]+[a-zA-Z0-9_]*\", <type_name> should be one of the types described in the UPLOAD section of the TAP documentation. Examples of good syntax: \"()\", \"(param INTEGER)\", \"(param1 INTEGER, param2 DOUBLE)\""); + } + } + + // Build the function definition object: + return new FunctionDef(fctName, returnType, params); + }else + throw new ParseException("Wrong function definition syntax! Expected syntax: \"<regular_identifier>(<parameters>?) <return_type>?\", where <regular_identifier>=\"[a-zA-Z]+[a-zA-Z0-9_]*\", <return_type>=\" -> <type_name>\", <parameters>=\"(<regular_identifier> <type_name> (, <regular_identifier> <type_name>)*)\", <type_name> should be one of the types described in the UPLOAD section of the TAP documentation. Examples of good syntax: \"foo()\", \"foo() -> VARCHAR\", \"foo(param INTEGER)\", \"foo(param1 INTEGER, param2 DOUBLE) -> DOUBLE\""); + } + + /** + * Parse the given string representation of a datatype. + * + * @param datatype String representation of a datatype. + * <i>Note: This string must not contain the length parameter or any other parameter. + * These latter should have been separated from the datatype before calling this function.</i> + * @param length Length of this datatype. + * <i>Note: This length will be used only for binary (BINARY and VARBINARY) + * and character (CHAR and VARCHAR) types.</i> + * + * @return The object representation of the specified datatype. + */ + private static DBType parseType(String datatype, int length){ + if (datatype == null) + return null; + + try{ + // Try to find a corresponding DBType item: + DBDatatype dbDatatype = DBDatatype.valueOf(datatype.toUpperCase()); + + // If there's a match, build the type object representation: + length = (length <= 0) ? DBType.NO_LENGTH : length; + switch(dbDatatype){ + case CHAR: + case VARCHAR: + case BINARY: + case VARBINARY: + return new DBType(dbDatatype, length); + default: + return new DBType(dbDatatype); + } + }catch(IllegalArgumentException iae){ + // If there's no corresponding DBType item, try to find a match among the most used DB types: + datatype = datatype.toLowerCase(); + if (datatype.equals("bool") || datatype.equals("boolean") || datatype.equals("short")) + return new DBType(DBDatatype.SMALLINT); + else if (datatype.equals("int2")) + return new DBType(DBDatatype.SMALLINT); + else if (datatype.equals("int") || datatype.equals("int4")) + return new DBType(DBDatatype.INTEGER); + else if (datatype.equals("long") || datatype.equals("number") || datatype.equals("bigint") || datatype.equals("int8")) + return new DBType(DBDatatype.BIGINT); + else if (datatype.equals("float") || datatype.equals("float4")) + return new DBType(DBDatatype.REAL); + else if (datatype.equals("numeric") || datatype.equals("float8")) + return new DBType(DBDatatype.DOUBLE); + else if (datatype.equals("byte") || datatype.equals("raw")) + return new DBType(DBDatatype.BINARY, length); + else if (datatype.equals("unsignedByte")) + return new DBType(DBDatatype.VARBINARY, length); + else if (datatype.equals("character")) + return new DBType(DBDatatype.CHAR, length); + else if (datatype.equals("string") || datatype.equals("varchar2")) + return new DBType(DBDatatype.VARCHAR, length); + else if (datatype.equals("bytea")) + return new DBType(DBDatatype.BLOB); + else if (datatype.equals("text")) + return new DBType(DBDatatype.CLOB); + else if (datatype.equals("date") || datatype.equals("time")) + return new DBType(DBDatatype.TIMESTAMP); + else if (datatype.equals("position")) + return new DBType(DBDatatype.POINT); + else if (datatype.equals("polygon") || datatype.equals("box") || datatype.equals("circle")) + return new DBType(DBDatatype.REGION); + else + return null; + } + } + + @Override + public String toString(){ + return serializedForm; + } + + @Override + public int compareTo(final FunctionDef def){ + return compareForm.compareTo(def.compareForm); + } + + /** + * <p>Compare this function definition with the given ADQL function item.</p> + * + * <p> + * The comparison is done only on the function name and on rough type of the parameters. + * "Rough type" means here that just the kind of type is tested: numeric, string or geometry. + * Anyway, the return type is never tested by this function, since such information is usually + * not part of a function signature. + * </p> + * + * <p>The notion of "greater" and "less" are defined here according to the three following test steps:</p> + * <ol> + * <li><b>Name test:</b> if the name of both function are equals, next steps are evaluated, otherwise the standard string comparison (case insensitive) result is returned.</li> + * <li><b>Parameters test:</b> parameters are compared individually. Each time parameters (at the same position in both functions) are equals the next parameter can be tested, + * and so on until two parameters are different or the end of the parameters' list is reached. + * Just the kind of type is used for parameter comparison. Each kind of type is tested in the following order: numeric, string and geometry. + * When a kind of type is not equal for both parameters, the function exits with the appropriate value + * (1 if the parameter of this function definition is of the kind of type, -1 otherwise).</li> + * <li><b>Number of parameters test:</b> in the case where this function definition has N parameters and the given ADQL function has M parameters, + * and that the L (= min(N,M)) first parameters have the same type in both functions, the value returns by this function + * will be N-M. Thus, if this function definition has more parameters than the given function, a positive value will be + * returned. Otherwise a negative value will be returned, or 0 if the number of parameters is the same.</li> + * </ol> + * + * @param fct ADQL function item to compare with this function definition. + * + * @return A positive value if this function definition is "greater" than the given {@link ADQLFunction}, + * 0 if they are perfectly matching, + * or a negative value if this function definition is "less" than the given {@link ADQLFunction}. + */ + public int compareTo(final ADQLFunction fct){ + if (fct == null) + throw new NullPointerException("Missing ADQL function with which comparing this function definition!"); + + // Names comparison: + int comp = name.compareToIgnoreCase(fct.getName()); + + // If equals, compare the parameters' type: + if (comp == 0){ + for(int i = 0; comp == 0 && i < nbParams && i < fct.getNbParameters(); i++){ + if (params[i].type.isNumeric() == fct.getParameter(i).isNumeric()){ + if (params[i].type.isString() == fct.getParameter(i).isString()){ + if (params[i].type.isGeometry() == fct.getParameter(i).isGeometry()) + comp = 0; + else + comp = params[i].type.isGeometry() ? 1 : -1; + }else + comp = params[i].type.isString() ? 1 : -1; + }else + comp = params[i].type.isNumeric() ? 1 : -1; + } + + // If the first min(N,M) parameters are of the same type, do the last comparison on the number of parameters: + if (comp == 0 && nbParams != fct.getNbParameters()) + comp = nbParams - fct.getNbParameters(); + } + + return comp; + } +} diff --git a/src/adql/db/STCS.java b/src/adql/db/STCS.java new file mode 100644 index 0000000000000000000000000000000000000000..c4a34e9eb4e3a64dfb08e62a10db0a123e742789 --- /dev/null +++ b/src/adql/db/STCS.java @@ -0,0 +1,1685 @@ +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 2014 - Astronomisches Rechen Institut (ARI) + */ + +import java.util.ArrayList; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import adql.parser.ADQLQueryFactory; +import adql.parser.ParseException; +import adql.query.TextPosition; +import adql.query.operand.ADQLOperand; +import adql.query.operand.NegativeOperand; +import adql.query.operand.NumericConstant; +import adql.query.operand.StringConstant; +import adql.query.operand.function.ADQLFunction; +import adql.query.operand.function.geometry.BoxFunction; +import adql.query.operand.function.geometry.CircleFunction; +import adql.query.operand.function.geometry.GeometryFunction; +import adql.query.operand.function.geometry.PointFunction; +import adql.query.operand.function.geometry.PolygonFunction; +import adql.query.operand.function.geometry.RegionFunction; + +/** + * <p>This class helps dealing with the subset of STC-S expressions described by the section "6 Use of STC-S in TAP (informative)" + * of the TAP Recommendation 1.0 (27th March 2010). This subset is limited to the most common coordinate systems and regions.</p> + * + * <p><i>Note: + * No instance of this class can be created. Its usage is only limited to its static functions and classes. + * </i></p> + * + * <h3>Coordinate system</h3> + * <p> + * The function {@link #parseCoordSys(String)} is able to parse a string containing only the STC-S expression of a coordinate system + * (or an empty string or null which would be interpreted as the default coordinate system - UNKNOWNFRAME UNKNOWNREFPOS SPHERICAL2). + * When successful, this parsing returns an object representation of the coordinate system: {@link CoordSys}. + * </p> + * <p> + * To serialize into STC-S a coordinate system, you have to create a {@link CoordSys} instance with the desired values + * and to call the function {@link CoordSys#toSTCS()}. The static function {@link #toSTCS(CoordSys)} is just calling the + * {@link CoordSys#toSTCS()} on the given coordinate system. + * </p> + * + * <h3>Geometrical region</h3> + * <p> + * As for the coordinate system, there is a static function to parse the STC-S representation of a geometrical region: {@link #parseRegion(String)}. + * Here again, when the parsing is successful an object representation is returned: {@link Region}. + * </p> + * <p> + * This class lets also serializing into STC-S a region. The procedure is the same as with a coordinate system: create a {@link Region} and then + * call {@link Region#toString()}. + * </p> + * <p> + * The class {@link Region} lets also dealing with the {@link ADQLFunction} implementing a region. It is then possible to create a {@link Region} + * object from a such {@link ADQLFunction} and to get the corresponding STC-S representation. The static function {@link #toSTCS(GeometryFunction)} + * is a helpful function which do these both actions in once. + * </p> + * <p><i>Note: + * The conversion from {@link ADQLFunction} to {@link Region} or STC-S is possible only if the {@link ADQLFunction} contains constants as parameter. + * Thus, a such function using a column, a concatenation, a math operation or using another function can not be converted into STC-S using this class. + * </i></p> + * + * @author Grégory Mantelet (ARI) + * @version 1.3 (10/2014) + * @since 1.3 + */ +public final class STCS { + + /** + * Empty private constructor ; in order to prevent any instance creation. + */ + private STCS(){} + + /* ***************** */ + /* COORDINATE SYSTEM */ + /* ***************** */ + + /** Regular expression for a STC-S representation of a coordinate system. It takes into account the fact that each part of + * a coordinate system is optional and so that a full coordinate system expression can be reduced to an empty string. */ + private final static String coordSysRegExp = Frame.regexp + "?\\s*" + RefPos.regexp + "?\\s*" + Flavor.regexp + "?"; + /** Regular expression of an expression exclusively limited to a coordinate system. */ + private final static String onlyCoordSysRegExp = "^\\s*" + coordSysRegExp + "\\s*$"; + /** Regular expression of a default coordinate system: either an empty string or a string containing only default values. */ + private final static String defaultCoordSysRegExp = "^\\s*" + Frame.DEFAULT + "?\\s*" + RefPos.DEFAULT + "?\\s*" + Flavor.DEFAULT + "?\\s*$"; + /** Regular expression of a pattern describing a set of allowed coordinate systems. <i>See {@link #buildAllowedRegExp(String)} for more details.</i> */ + /* With this regular expression, we get the following matching groups: + * 0: All the expression + * 1+(6*N): The N-th part of the coordinate system (N is an unsigned integer between 0 and 2 (included) ; it is reduced to '*' if the two following groups are NULL + * 2+(6*N): A single value for the N-th part + * 3+(6*N): A list of values for the N-th part + * 4+(6*N): First value of the list for the N-th part + * 5+(6*N): All the other values (starting with a |) of the list for the N-th part + * 6+(6*N): Last value of the list for the N-th part. + */ + private final static String allowedCoordSysRegExp = "^\\s*" + buildAllowedRegExp(Frame.regexp) + "\\s+" + buildAllowedRegExp(RefPos.regexp) + "\\s+" + buildAllowedRegExp(Flavor.regexp) + "\\s*$"; + + /** Pattern of an allowed coordinate system pattern. This object has been compiled with {@link #allowedCoordSysRegExp}. */ + private final static Pattern allowedCoordSysPattern = Pattern.compile(allowedCoordSysRegExp); + + /** Human description of the syntax of a full coordinate system expression. */ + private final static String COORD_SYS_SYNTAX = "\"[" + Frame.regexp + "] [" + RefPos.regexp + "] [" + Flavor.regexp + "]\" ; an empty string is also allowed and will be interpreted as the coordinate system locally used"; + + /** + * Build the regular expression of a string defining the allowed values for one part of the whole coordinate system. + * + * @param rootRegExp All allowed part values. + * + * @return The corresponding regular expression. + */ + private static String buildAllowedRegExp(final String rootRegExp){ + return "(" + rootRegExp + "|\\*|(\\(\\s*" + rootRegExp + "\\s*(\\|\\s*" + rootRegExp + "\\s*)*\\)))"; + } + + /** + * <p>List of all possible frames in an STC expression.</p> + * + * <p> + * When no value is specified, the default one is {@link #UNKNOWNFRAME}. + * The default value is also accessible through the attribute {@link #DEFAULT} + * and it is possible to test whether a frame is the default with the function {@link #isDefault()}. + * </p> + * + * <p><i>Note: + * The possible values listed in this enumeration are limited to the subset of STC-S described by the section "6 Use of STC-S in TAP (informative)" + * of the TAP Recommendation 1.0 (27th March 2010). + * </i></p> + * + * @author Grégory Mantelet (ARI) + * @version 1.3 (10/2014) + * @since 1.3 + */ + public static enum Frame{ + ECLIPTIC, FK4, FK5, GALACTIC, ICRS, UNKNOWNFRAME; + + /** Default value for a frame: {@link #UNKNOWNFRAME}. */ + public static final Frame DEFAULT = UNKNOWNFRAME; + + /** Regular expression to test whether a string is a valid frame or not. This regular expression does not take into account + * the case of an empty string (which means "default frame"). */ + public static final String regexp = buildRegexp(Frame.class); + + /** + * Tell whether this frame is the default one. + * + * @return <i>true</i> if this is the default frame, <i>false</i> + */ + public final boolean isDefault(){ + return this == DEFAULT; + } + } + + /** + * <p>List of all possible reference positions in an STC expression.</p> + * + * <p> + * When no value is specified, the default one is {@link #UNKNOWNREFPOS}. + * The default value is also accessible through the attribute {@link #DEFAULT} + * and it is possible to test whether a reference position is the default with the function {@link #isDefault()}. + * </p> + * + * <p><i>Note: + * The possible values listed in this enumeration are limited to the subset of STC-S described by the section "6 Use of STC-S in TAP (informative)" + * of the TAP Recommendation 1.0 (27th March 2010). + * </i></p> + * + * @author Grégory Mantelet (ARI) + * @version 1.3 (10/2014) + * @since 1.3 + */ + public static enum RefPos{ + BARYCENTER, GEOCENTER, HELIOCENTER, LSR, TOPOCENTER, RELOCATABLE, UNKNOWNREFPOS; + + /** Default value for a reference position: {@link #UNKNOWNREFPOS}. */ + public static final RefPos DEFAULT = UNKNOWNREFPOS; + + /** Regular expression to test whether a string is a valid reference position or not. This regular expression does not take into account + * the case of an empty string (which means "default reference position"). */ + public static final String regexp = buildRegexp(RefPos.class); + + /** + * Tell whether this reference position is the default one. + * + * @return <i>true</i> if this is the default reference position, <i>false</i> + */ + public final boolean isDefault(){ + return this == DEFAULT; + } + } + + /** + * <p>List of all possible flavors in an STC expression.</p> + * + * <p> + * When no value is specified, the default one is {@link #SPHERICAL2}. + * The default value is also accessible through the attribute {@link #DEFAULT} + * and it is possible to test whether a flavor is the default with the function {@link #isDefault()}. + * </p> + * + * <p><i>Note: + * The possible values listed in this enumeration are limited to the subset of STC-S described by the section "6 Use of STC-S in TAP (informative)" + * of the TAP Recommendation 1.0 (27th March 2010). + * </i></p> + * + * @author Grégory Mantelet (ARI) + * @version 1.3 (10/2014) + * @since 1.3 + */ + public static enum Flavor{ + CARTESIAN2, CARTESIAN3, SPHERICAL2; + + /** Default value for a flavor: {@link #SPHERICAL2}. */ + public static final Flavor DEFAULT = SPHERICAL2; + + /** Regular expression to test whether a string is a valid flavor or not. This regular expression does not take into account + * the case of an empty string (which means "default flavor"). */ + public static final String regexp = buildRegexp(Flavor.class); + + /** + * Tell whether this flavor is the default one. + * + * @return <i>true</i> if this is the default flavor, <i>false</i> + */ + public final boolean isDefault(){ + return this == DEFAULT; + } + } + + /** + * Build a regular expression covering all possible values of the given enumeration. + * + * @param enumType Class of an enumeration type. + * + * @return The build regular expression or "\s*" if the given enumeration contains no constants/values. + * + * @throws IllegalArgumentException If the given class is not an enumeration type. + */ + private static String buildRegexp(final Class<?> enumType) throws IllegalArgumentException{ + // The given class must be an enumeration type: + if (!enumType.isEnum()) + throw new IllegalArgumentException("An enum class was expected, but a " + enumType.getName() + " has been given!"); + + // Get the enumeration constants/values: + Object[] constants = enumType.getEnumConstants(); + if (constants == null || constants.length == 0) + return "\\s*"; + + // Concatenate all constants with pipe to build a choice regular expression: + StringBuffer buf = new StringBuffer("("); + for(int i = 0; i < constants.length; i++){ + buf.append(constants[i]); + if ((i + 1) < constants.length) + buf.append('|'); + } + return buf.append(')').toString(); + } + + /** + * <p>Object representation of an STC coordinate system.</p> + * + * <p> + * A coordinate system is composed of three parts: a frame ({@link #frame}), + * a reference position ({@link #refpos}) and a flavor ({@link #flavor}). + * </p> + * + * <p> + * The default value - also corresponding to an empty string - should be: + * {@link Frame#UNKNOWNFRAME} {@link RefPos#UNKNOWNREFPOS} {@link Flavor#SPHERICAL2}. + * Once built, it is possible to know whether the coordinate system is the default one + * or not thanks to function {@link #isDefault()}. + * </p> + * + * <p> + * An instance of this class can be easily serialized into STC-S using {@link #toSTCS()}, {@link #toFullSTCS()} + * or {@link #toString()}. {@link #toFullSTCS()} will display default values explicitly + * on the contrary to {@link #toSTCS()} which will replace them by empty strings. + * </p> + * + * <p><i><b>Important note:</b> + * The flavors CARTESIAN2 and CARTESIAN3 can not be used with other frame and reference position than + * UNKNOWNFRAME and UNKNOWNREFPOS. In the contrary case an {@link IllegalArgumentException} is throw. + * </i></p> + * + * @author Grégory Mantelet (ARI) + * @version 1.3 (10/2014) + * @since 1.3 + */ + public static class CoordSys { + /** First item of a coordinate system expression: the frame. */ + public final Frame frame; + + /** Second item of a coordinate system expression: the reference position. */ + public final RefPos refpos; + + /** Third and last item of a coordinate system expression: the flavor. */ + public final Flavor flavor; + + /** Indicate whether all parts of the coordinate system are set to their default value. */ + private final boolean isDefault; + + /** STC-S representation of this coordinate system. Default items are not written (that's to say, they are replaced by an empty string). */ + private final String stcs; + + /** STC-S representation of this coordinate system. Default items are explicitly written. */ + private final String fullStcs; + + /** + * Build a default coordinate system (UNKNOWNFRAME UNKNOWNREFPOS SPHERICAL2). + */ + public CoordSys(){ + this(null, null, null); + } + + /** + * Build a coordinate system with the given parts. + * + * @param fr Frame part. + * @param rp Reference position part. + * @param fl Flavor part. + * + * @throws IllegalArgumentException If a cartesian flavor is used with a frame and reference position other than UNKNOWNFRAME and UNKNOWNREFPOS. + */ + public CoordSys(final Frame fr, final RefPos rp, final Flavor fl) throws IllegalArgumentException{ + frame = (fr == null) ? Frame.DEFAULT : fr; + refpos = (rp == null) ? RefPos.DEFAULT : rp; + flavor = (fl == null) ? Flavor.DEFAULT : fl; + + if (flavor != Flavor.SPHERICAL2 && (frame != Frame.UNKNOWNFRAME || refpos != RefPos.UNKNOWNREFPOS)) + throw new IllegalArgumentException("a coordinate system expressed with a cartesian flavor MUST have an UNKNOWNFRAME and UNKNOWNREFPOS!"); + + isDefault = frame.isDefault() && refpos.isDefault() && flavor.isDefault(); + + stcs = ((!frame.isDefault() ? frame + " " : "") + (!refpos.isDefault() ? refpos + " " : "") + (!flavor.isDefault() ? flavor : "")).trim(); + fullStcs = frame + " " + refpos + " " + flavor; + } + + /** + * Build a coordinate system by parsing the given STC-S expression. + * + * @param coordsys STC-S expression representing a coordinate system. <i>Empty string and NULL are allowed values ; they correspond to a default coordinate system.</i> + * + * @throws ParseException If the syntax of the given STC-S expression is wrong or if it is not a coordinate system only. + */ + public CoordSys(final String coordsys) throws ParseException{ + CoordSys tmp = new STCSParser().parseCoordSys(coordsys); + frame = tmp.frame; + refpos = tmp.refpos; + flavor = tmp.flavor; + isDefault = tmp.isDefault; + stcs = tmp.stcs; + fullStcs = tmp.fullStcs; + } + + /** + * Tell whether this is the default coordinate system (UNKNOWNFRAME UNKNOWNREFPOS SPHERICAL2). + * + * @return <i>true</i> if it is the default coordinate system, <i>false</i> otherwise. + */ + public final boolean isDefault(){ + return isDefault; + } + + /** + * Get the STC-S expression of this coordinate system, + * in which default values are not written (they are replaced by empty strings). + * + * @return STC-S representation of this coordinate system. + */ + public String toSTCS(){ + return stcs; + } + + /** + * Get the STC-S expression of this coordinate system, + * in which default values are explicitly written. + * + * @return STC-S representation of this coordinate system. + */ + public String toFullSTCS(){ + return fullStcs; + } + + /** + * Convert this coordinate system into a STC-S expression. + * + * @see java.lang.Object#toString() + * @see #toSTCS() + */ + @Override + public String toString(){ + return stcs; + } + } + + /** + * Parse the given STC-S representation of a coordinate system. + * + * @param stcs STC-S expression of a coordinate system. <i>Note: a NULL or empty string will be interpreted as a default coordinate system.</i> + * + * @return The object representation of the specified coordinate system. + * + * @throws ParseException If the given expression has a wrong STC-S syntax. + */ + public static CoordSys parseCoordSys(final String stcs) throws ParseException{ + return (new STCSParser().parseCoordSys(stcs)); + } + + /** + * <p>Convert an object representation of a coordinate system into an STC-S expression.</p> + * + * <p><i>Note: + * A NULL object will be interpreted as the default coordinate system and so an empty string will be returned. + * Otherwise, this function is equivalent to {@link CoordSys#toSTCS()} (in which default values for each + * coordinate system part is not displayed). + * </i></p> + * + * @param coordSys The object representation of the coordinate system to convert into STC-S. + * + * @return The corresponding STC-S expression. + * + * @see CoordSys#toSTCS() + * @see CoordSys#toFullSTCS() + */ + public static String toSTCS(final CoordSys coordSys){ + if (coordSys == null) + return ""; + else + return coordSys.toSTCS(); + } + + /** + * <p>Build a big regular expression gathering all of the given coordinate system syntaxes.</p> + * + * <p> + * Each item of the given list must respect a strict syntax. Each part of the coordinate system + * may be a single value, a list of values or a '*' (meaning all values are allowed). + * A list of values must have the following syntax: <code>({value1}|{value2}|...)</code>. + * An empty string is NOT here accepted. + * </p> + * + * <p><i>Example: + * <code>(ICRS|FK4|FK5) * SPHERICAL2</code> is OK, + * but <code>(ICRS|FK4|FK5) *</code> is not valid because the flavor value is not defined. + * </i></p> + * + * <p> + * Since the default value of each part of a coordinate system should always be possible, + * this function ensure these default values are always possible in the returned regular expression. + * Thus, if some values except the default one are specified, the default value is automatically appended. + * </p> + * + * <p><i>Note: + * If the given array is NULL, all coordinate systems are allowed. + * But if the given array is empty, none except an empty string or the default value will be allowed. + * </i></p> + * + * @param allowedCoordSys List of all coordinate systems that are allowed. + * + * @return The corresponding regular expression. + * + * @throws ParseException If the syntax of one of the given allowed coordinate system is wrong. + */ + public static String buildCoordSysRegExp(final String[] allowedCoordSys) throws ParseException{ + // NULL array => all coordinate systems are allowed: + if (allowedCoordSys == null) + return onlyCoordSysRegExp; + // Empty array => no coordinate system (except the default one) is allowed: + else if (allowedCoordSys.length == 0) + return defaultCoordSysRegExp; + + // The final regular expression must be reduced to a coordinate system and nothing else before: + StringBuffer finalRegExp = new StringBuffer("^\\s*("); + + // For each allowed coordinate system: + Matcher m; + int nbCoordSys = 0; + for(int i = 0; i < allowedCoordSys.length; i++){ + + // NULL item => skipped! + if (allowedCoordSys[i] == null) + continue; + else{ + if (nbCoordSys > 0) + finalRegExp.append('|'); + nbCoordSys++; + } + + // Check its syntax and identify all of its parts: + m = allowedCoordSysPattern.matcher(allowedCoordSys[i].toUpperCase()); + if (m.matches()){ + finalRegExp.append('('); + for(int g = 0; g < 3; g++){ // See the comment after the Javadoc of #allowedCoordSysRegExp for a complete list of available groups returned by the pattern. + + // SINGLE VALUE: + if (m.group(2 + (6 * g)) != null) + finalRegExp.append('(').append(defaultChoice(g, m.group(2 + (6 * g)))).append(m.group(2 + (6 * g))).append(')'); + + // LIST OF VALUES: + else if (m.group(3 + (6 * g)) != null) + finalRegExp.append('(').append(defaultChoice(g, m.group(3 + (6 * g)))).append(m.group(3 + (6 * g)).replaceAll("\\s", "").substring(1)); + + // JOKER (*): + else{ + switch(g){ + case 0: + finalRegExp.append(Frame.regexp); + break; + case 1: + finalRegExp.append(RefPos.regexp); + break; + case 2: + finalRegExp.append(Flavor.regexp); + break; + } + finalRegExp.append('?'); + } + finalRegExp.append("\\s*"); + } + finalRegExp.append(')'); + }else + throw new ParseException("Wrong allowed coordinate system syntax for the " + (i + 1) + "-th item: \"" + allowedCoordSys[i] + "\"! Expected: \"frameRegExp refposRegExp flavorRegExp\" ; where each xxxRegExp = (xxx | '*' | '('xxx ('|' xxx)*')'), frame=\"" + Frame.regexp + "\", refpos=\"" + RefPos.regexp + "\" and flavor=\"" + Flavor.regexp + "\" ; an empty string is also allowed and will be interpreted as '*' (so all possible values)."); + } + + // The final regular expression must be reduced to a coordinate system and nothing else after: + finalRegExp.append(")\\s*"); + + return (nbCoordSys > 0) ? finalRegExp.append(")$").toString() : defaultCoordSysRegExp; + } + + /** + * Get the default value appended by a '|' character, ONLY IF the given value does not already contain the default value. + * + * @param g Index of the coordinate system part (0: Frame, 1: RefPos, 2: Flavor, another value will return an empty string). + * @param value Value in which the default value must prefix. + * + * @return A prefix for the given value (the default value and a '|' if the default value is not already in the given value, "" otherwise). + */ + private static String defaultChoice(final int g, final String value){ + switch(g){ + case 0: + return value.contains(Frame.DEFAULT.toString()) ? "" : Frame.DEFAULT + "|"; + case 1: + return value.contains(RefPos.DEFAULT.toString()) ? "" : RefPos.DEFAULT + "|"; + case 2: + return value.contains(Flavor.DEFAULT.toString()) ? "" : Flavor.DEFAULT + "|"; + default: + return ""; + } + } + + /* ****** */ + /* REGION */ + /* ****** */ + + /** + * <p>List all possible region types allowed in an STC-S expression.</p> + * + * <p><i>Note: + * The possible values listed in this enumeration are limited to the subset of STC-S described by the section "6 Use of STC-S in TAP (informative)" + * of the TAP Recommendation 1.0 (27th March 2010). + * </i></p> + * + * @author Grégory Mantelet (ARI) + * @version 1.3 (10/2014) + * @since 1.3 + */ + public static enum RegionType{ + POSITION, CIRCLE, BOX, POLYGON, UNION, INTERSECTION, NOT; + } + + /** + * <p>Object representation of an STC region.</p> + * + * <p> + * This class contains a field for each possible parameter of a region. Depending of the region type + * some are not used. In such case, these unused fields are set to NULL. + * </p> + * + * <p> + * An instance of this class can be easily serialized into STC-S using {@link #toSTCS()}, {@link #toFullSTCS()} + * or {@link #toString()}. {@link #toFullSTCS()} will display default value explicit + * on the contrary to {@link #toSTCS()} which will replace them by empty strings. + * </p> + * + * @author Grégory Mantelet (ARI) + * @version 1.3 (10/2014) + * @since 1.3 + */ + public static class Region { + /** Type of the region. */ + public final RegionType type; + + /** Coordinate system used by this region. + * <i>Note: only the NOT region does not declare a coordinate system ; so only for this region this field is NULL.</i> */ + public final CoordSys coordSys; + + /** List of coordinates' pairs. The second dimension of this array represents a pair of coordinates ; it is then an array of two elements. + * <i>Note: this field is used by POINT, BOX, CIRCLE and POLYGON.</i> */ + public final double[][] coordinates; + + /** Width of the BOX region. */ + public final double width; + + /** Height of the BOX region. */ + public final double height; + + /** Radius of the CIRCLE region. */ + public final double radius; + + /** List of regions unified (UNION), intersected (INTERSECTION) or avoided (NOT). */ + public final Region[] regions; + + /** STC-S representation of this region, in which default values of the coordinate system (if any) are not written (they are replaced by empty strings). + * <i>Note: This attribute is NULL until the first call of the function {@link #toSTCS()} where it is built.</i> */ + private String stcs = null; + + /** STC-S representation of this region, in which default values of the coordinate system (if any) are explicitly written. + * <i>Note: This attribute is NULL until the first call of the function {@link #toFullSTCS()} where it is built.</i> */ + private String fullStcs = null; + + /** The ADQL function object representing this region. + * <i>Note: this attribute is NULL until the first call of the function {@link #toGeometry()} or {@link #toGeometry(ADQLQueryFactory)}.</i> */ + private GeometryFunction geometry = null; + + /** + * <p>Constructor for a POINT/POSITION region.</p> + * + * <p><i><b>Important note:</b> + * The array of coordinates is used like that. No copy is done. + * </i></p> + * + * @param coordSys Coordinate system. <i>note: It MAY BE null ; if so, the default coordinate system will be chosen</li> + * @param coordinates A pair of coordinates ; coordinates[0] and coordinates[1]. + */ + public Region(final CoordSys coordSys, final double[] coordinates){ + this(coordSys, new double[][]{coordinates}); + } + + /** + * <p>Constructor for a POINT/POSITION or a POLYGON region.</p> + * + * <p>Whether it is a polygon or a point depends on the number of given coordinates:</p> + * <ul> + * <li>1 item => POINT/POSITION</li> + * <li>more items => POLYGON</li> + * </ul> + * + * <p><i><b>Important note:</b> + * The array of coordinates is used like that. No copy is done. + * </i></p> + * + * @param coordSys Coordinate system. <i>note: It MAY BE null ; if so, the default coordinate system will be chosen</li> + * @param coordinates List of coordinates' pairs ; coordinates[n] = 1 pair = 2 items (coordinates[n][0] and coordinates[n][1]) ; if 1 pair, it is a POINT/POSITION, but if more, it is a POLYGON. + */ + public Region(final CoordSys coordSys, final double[][] coordinates){ + // Check roughly the coordinates: + if (coordinates == null || coordinates.length == 0) + throw new NullPointerException("Missing coordinates!"); + else if (coordinates[0].length != 2) + throw new IllegalArgumentException("Wrong number of coordinates! Expected at least 2 pairs of coordinates (so coordinates[0], coordinates[1] and coordinates[n].length = 2)."); + + // Decide of the region type in function of the number of coordinates' pairs: + type = (coordinates.length > 1) ? RegionType.POLYGON : RegionType.POSITION; + + // Set the coordinate system (if NULL, choose the default one): + this.coordSys = (coordSys == null ? new CoordSys() : coordSys); + + // Set the coordinates: + this.coordinates = coordinates; + + // Set the other fields as not used: + width = Double.NaN; + height = Double.NaN; + radius = Double.NaN; + regions = null; + } + + /** + * <p>Constructor for a CIRCLE region.</p> + * + * <p><i><b>Important note:</b> + * The array of coordinates is used like that. No copy is done. + * </i></p> + * + * @param coordSys Coordinate system. <i>note: It MAY BE null ; if so, the default coordinate system will be chosen</li> + * @param coordinates A pair of coordinates ; coordinates[0] and coordinates[1]. + * @param radius The circle radius. + */ + public Region(final CoordSys coordSys, final double[] coordinates, final double radius){ + // Check roughly the coordinates: + if (coordinates == null || coordinates.length == 0) + throw new NullPointerException("Missing coordinates!"); + else if (coordinates.length != 2) + throw new IllegalArgumentException("Wrong number of coordinates! Expected exactly 2 values."); + + // Set the region type: + type = RegionType.CIRCLE; + + // Set the coordinate system (if NULL, choose the default one): + this.coordSys = (coordSys == null ? new CoordSys() : coordSys); + + // Set the coordinates: + this.coordinates = new double[][]{coordinates}; + + // Set the radius: + this.radius = radius; + + // Set the other fields as not used: + width = Double.NaN; + height = Double.NaN; + regions = null; + } + + /** + * <p>Constructor for a BOX region.</p> + * + * <p><i><b>Important note:</b> + * The array of coordinates is used like that. No copy is done. + * </i></p> + * + * @param coordSys Coordinate system. <i>note: It MAY BE null ; if so, the default coordinate system will be chosen</li> + * @param coordinates A pair of coordinates ; coordinates[0] and coordinates[1]. + * @param width Width of the box. + * @param height Height of the box. + */ + public Region(final CoordSys coordSys, final double[] coordinates, final double width, final double height){ + // Check roughly the coordinates: + if (coordinates == null || coordinates.length == 0) + throw new NullPointerException("Missing coordinates!"); + else if (coordinates.length != 2) + throw new IllegalArgumentException("Wrong number of coordinates! Expected exactly 2 values."); + + // Set the region type: + type = RegionType.BOX; + + // Set the coordinate system (if NULL, choose the default one): + this.coordSys = (coordSys == null ? new CoordSys() : coordSys); + + // Set the coordinates: + this.coordinates = new double[][]{coordinates}; + + // Set the size of the box: + this.width = width; + this.height = height; + + // Set the other fields as not used: + radius = Double.NaN; + regions = null; + } + + /** + * <p>Constructor for a UNION or INTERSECTION region.</p> + * + * <p><i><b>Important note:</b> + * The array of regions is used like that. No copy is done. + * </i></p> + * + * @param unionOrIntersection Type of the region to create. <i>Note: It can be ONLY a UNION or INTERSECTION. Another value will throw an IllegalArgumentException).</i> + * @param coordSys Coordinate system. <i>note: It MAY BE null ; if so, the default coordinate system will be chosen</li> + * @param regions Regions to unite or to intersect. <i>Note: At least two regions must be provided.</i> + */ + public Region(final RegionType unionOrIntersection, final CoordSys coordSys, final Region[] regions){ + // Check the type: + if (unionOrIntersection == null) + throw new NullPointerException("Missing type of region (UNION or INTERSECTION here)!"); + else if (unionOrIntersection != RegionType.UNION && unionOrIntersection != RegionType.INTERSECTION) + throw new IllegalArgumentException("Wrong region type: \"" + unionOrIntersection + "\"! This constructor lets create only an UNION or INTERSECTION region."); + + // Check the list of regions: + if (regions == null || regions.length == 0) + throw new NullPointerException("Missing regions to " + (unionOrIntersection == RegionType.UNION ? "unite" : "intersect") + "!"); + else if (regions.length < 2) + throw new IllegalArgumentException("Wrong number of regions! Expected at least 2 regions."); + + // Set the region type: + type = unionOrIntersection; + + // Set the coordinate system (if NULL, choose the default one): + this.coordSys = (coordSys == null ? new CoordSys() : coordSys); + + // Set the regions: + this.regions = regions; + + // Set the other fields as not used: + coordinates = null; + radius = Double.NaN; + width = Double.NaN; + height = Double.NaN; + } + + /** + * Constructor for a NOT region. + * + * @param region Any region to not select. + */ + public Region(final Region region){ + // Check the region parameter: + if (region == null) + throw new NullPointerException("Missing region to NOT select!"); + + // Set the region type: + type = RegionType.NOT; + + // Set the regions: + this.regions = new Region[]{region}; + + // Set the other fields as not used: + coordSys = null; + coordinates = null; + radius = Double.NaN; + width = Double.NaN; + height = Double.NaN; + } + + /** + * <p>Build a Region from the given ADQL representation.</p> + * + * <p><i>Note: + * Only {@link PointFunction}, {@link CircleFunction}, {@link BoxFunction}, {@link PolygonFunction} and {@link RegionFunction} + * are accepted here. Other extensions of {@link GeometryFunction} will throw an {@link IllegalArgumentException}. + * </i></p> + * + * @param geometry The ADQL representation of the region to create here. + * + * @throws IllegalArgumentException If the given geometry is neither of {@link PointFunction}, {@link BoxFunction}, {@link PolygonFunction} and {@link RegionFunction}. + * @throws ParseException If the declared coordinate system, the coordinates or the STC-S definition has a wrong syntax. + */ + public Region(final GeometryFunction geometry) throws IllegalArgumentException, ParseException{ + if (geometry == null) + throw new NullPointerException("Missing geometry to convert into STCS.Region!"); + + if (geometry instanceof PointFunction){ + type = RegionType.POSITION; + coordSys = STCS.parseCoordSys(extractString(geometry.getCoordinateSystem())); + coordinates = new double[][]{{extractNumeric(((PointFunction)geometry).getCoord1()),extractNumeric(((PointFunction)geometry).getCoord2())}}; + width = Double.NaN; + height = Double.NaN; + radius = Double.NaN; + regions = null; + }else if (geometry instanceof CircleFunction){ + type = RegionType.CIRCLE; + coordSys = STCS.parseCoordSys(extractString(geometry.getCoordinateSystem())); + coordinates = new double[][]{{extractNumeric(((CircleFunction)geometry).getCoord1()),extractNumeric(((CircleFunction)geometry).getCoord2())}}; + radius = extractNumeric(((CircleFunction)geometry).getRadius()); + width = Double.NaN; + height = Double.NaN; + regions = null; + }else if (geometry instanceof BoxFunction){ + type = RegionType.BOX; + coordSys = STCS.parseCoordSys(extractString(geometry.getCoordinateSystem())); + coordinates = new double[][]{{extractNumeric(((BoxFunction)geometry).getCoord1()),extractNumeric(((BoxFunction)geometry).getCoord2())}}; + width = extractNumeric(((BoxFunction)geometry).getWidth()); + height = extractNumeric(((BoxFunction)geometry).getHeight()); + radius = Double.NaN; + regions = null; + }else if (geometry instanceof PolygonFunction){ + PolygonFunction poly = (PolygonFunction)geometry; + type = RegionType.POLYGON; + coordSys = STCS.parseCoordSys(extractString(poly.getCoordinateSystem())); + coordinates = new double[(poly.getNbParameters() - 1) / 2][2]; + for(int i = 0; i < coordinates.length; i++) + coordinates[i] = new double[]{extractNumeric(poly.getParameter(1 + i * 2)),extractNumeric(poly.getParameter(2 + i * 2))}; + width = Double.NaN; + height = Double.NaN; + radius = Double.NaN; + regions = null; + }else if (geometry instanceof RegionFunction){ + Region r = STCS.parseRegion(extractString(((RegionFunction)geometry).getParameter(0))); + type = r.type; + coordSys = r.coordSys; + coordinates = r.coordinates; + width = r.width; + height = r.height; + radius = r.radius; + regions = r.regions; + }else + throw new IllegalArgumentException("Unknown region type! Only geometrical function PointFunction, CircleFunction, BoxFunction, PolygonFunction and RegionFunction are allowed."); + } + + /** + * Extract a string value from the given {@link ADQLOperand} + * which is <b>expected to be a {@link StringConstant} instance</b>. + * + * @param op A string operand. + * + * @return The string value embedded in the given operand. + * + * @throws ParseException If the given operand is not an instance of {@link StringConstant}. + */ + private static String extractString(final ADQLOperand op) throws ParseException{ + if (op == null) + throw new NullPointerException("Missing operand!"); + else if (op instanceof StringConstant) + return ((StringConstant)op).getValue(); + else + throw new ParseException("Can not convert into STC-S a non string argument (including ADQLColumn and Concatenation)!"); + } + + /** + * Extract a numeric value from the given {@link ADQLOperand} + * which is <b>expected to be a {@link NumericConstant} instance</b> + * or a {@link NegativeOperand} embedding a {@link NumericConstant}. + * + * @param op A numeric operand. + * + * @return The numeric value embedded in the given operand. + * + * @throws ParseException If the given operand is not an instance of {@link NumericConstant} or a {@link NegativeOperand}. + */ + private static double extractNumeric(final ADQLOperand op) throws ParseException{ + if (op == null) + throw new NullPointerException("Missing operand!"); + else if (op instanceof NumericConstant) + return Double.parseDouble(((NumericConstant)op).getValue()); + else if (op instanceof NegativeOperand) + return extractNumeric(((NegativeOperand)op).getOperand()) * -1; + else + throw new ParseException("Can not convert into STC-S a non numeric argument (including ADQLColumn and Operation)!"); + } + + /** + * <p>Get the STC-S representation of this region (in which default values + * of the coordinate system are not written ; they are replaced by empty strings).</p> + * + * <p><i>Note: + * This function build the STC-S just once and store it in a class attribute. + * The value of this attribute is then returned at next calls of this function. + * </i></p> + * + * @return Its STC-S representation. + */ + public String toSTCS(){ + if (stcs != null) + return stcs; + else{ + // Write the region type: + StringBuffer buf = new StringBuffer(type.toString()); + + // Write the coordinate system (except for NOT): + if (type != RegionType.NOT){ + String coordSysStr = coordSys.toSTCS(); + if (coordSysStr != null && coordSysStr.length() > 0) + buf.append(' ').append(coordSysStr); + buf.append(' '); + } + + // Write the other parameters (coordinates, regions, ...): + switch(type){ + case POSITION: + case POLYGON: + appendCoordinates(buf, coordinates); + break; + case CIRCLE: + appendCoordinates(buf, coordinates); + buf.append(' ').append(radius); + break; + case BOX: + appendCoordinates(buf, coordinates); + buf.append(' ').append(width).append(' ').append(height); + break; + case UNION: + case INTERSECTION: + case NOT: + buf.append('('); + appendRegions(buf, regions, false); + buf.append(')'); + break; + } + + // Return the built STC-S: + return (stcs = buf.toString()); + } + } + + /** + * <p>Get the STC-S representation of this region (in which default values + * of the coordinate system are explicitly written).</p> + * + * <p><i>Note: + * This function build the STC-S just once and store it in a class attribute. + * The value of this attribute is then returned at next calls of this function. + * </i></p> + * + * @return Its STC-S representation. + */ + public String toFullSTCS(){ + if (fullStcs != null) + return fullStcs; + else{ + // Write the region type: + StringBuffer buf = new StringBuffer(type.toString()); + + // Write the coordinate system (except for NOT): + if (type != RegionType.NOT){ + String coordSysStr = coordSys.toFullSTCS(); + if (coordSysStr != null && coordSysStr.length() > 0) + buf.append(' ').append(coordSysStr); + buf.append(' '); + } + + // Write the other parameters (coordinates, regions, ...): + switch(type){ + case POSITION: + case POLYGON: + appendCoordinates(buf, coordinates); + break; + case CIRCLE: + appendCoordinates(buf, coordinates); + buf.append(' ').append(radius); + break; + case BOX: + appendCoordinates(buf, coordinates); + buf.append(' ').append(width).append(' ').append(height); + break; + case UNION: + case INTERSECTION: + case NOT: + buf.append('('); + appendRegions(buf, regions, true); + buf.append(')'); + break; + } + + // Return the built STC-S: + return (fullStcs = buf.toString()); + } + } + + /** + * Append all the given coordinates to the given buffer. + * + * @param buf Buffer in which coordinates must be appended. + * @param coords Coordinates to append. + */ + private static void appendCoordinates(final StringBuffer buf, final double[][] coords){ + for(int i = 0; i < coords.length; i++){ + if (i > 0) + buf.append(' '); + buf.append(coords[i][0]).append(' ').append(coords[i][1]); + } + } + + /** + * Append all the given regions in the given buffer. + * + * @param buf Buffer in which regions must be appended. + * @param regions Regions to append. + * @param fullCoordSys Indicate whether the coordinate system of the regions must explicitly display the default values. + */ + private static void appendRegions(final StringBuffer buf, final Region[] regions, final boolean fullCoordSys){ + for(int i = 0; i < regions.length; i++){ + if (i > 0) + buf.append(' '); + if (fullCoordSys) + buf.append(regions[i].toFullSTCS()); + else + buf.append(regions[i].toSTCS()); + } + } + + @Override + public String toString(){ + return toSTCS(); + } + + /** + * <p>Convert this region into its corresponding ADQL representation.</p> + * + * <ul> + * <li><b>POSITION:</b> {@link PointFunction}</li> + * <li><b>CIRCLE:</b> {@link CircleFunction}</li> + * <li><b>BOX:</b> {@link BoxFunction}</li> + * <li><b>POLYGON:</b> {@link PolygonFunction}</li> + * <li><b>UNION, INTERSECTION, NOT:</b> {@link RegionFunction}</li> + * </ul> + * + * <p><i>Note: + * This function is using the default ADQL factory, built using {@link ADQLQueryFactory#ADQLQueryFactory()}. + * </i></p> + * + * @return The corresponding ADQL representation. + * + * @see #toGeometry(ADQLQueryFactory) + */ + public GeometryFunction toGeometry(){ + return toGeometry(null); + } + + /** + * <p>Convert this region into its corresponding ADQL representation.</p> + * + * <ul> + * <li><b>POSITION:</b> {@link PointFunction}</li> + * <li><b>CIRCLE:</b> {@link CircleFunction}</li> + * <li><b>BOX:</b> {@link BoxFunction}</li> + * <li><b>POLYGON:</b> {@link PolygonFunction}</li> + * <li><b>UNION, INTERSECTION, NOT:</b> {@link RegionFunction}</li> + * </ul> + * + * <p><i>Note: + * This function build the ADQL representation just once and store it in a class attribute. + * The value of this attribute is then returned at next calls of this function. + * </i></p> + * + * @param factory The factory of ADQL objects to use. + * + * @return The corresponding ADQL representation. + */ + public GeometryFunction toGeometry(ADQLQueryFactory factory){ + if (factory == null) + factory = new ADQLQueryFactory(); + + try{ + if (geometry != null) + return geometry; + else{ + StringConstant coordSysObj = factory.createStringConstant(coordSys == null ? "" : coordSys.toString()); + switch(type){ + case POSITION: + return (geometry = factory.createPoint(coordSysObj, toNumericObj(coordinates[0][0], factory), toNumericObj(coordinates[0][1], factory))); + case CIRCLE: + return (geometry = factory.createCircle(coordSysObj, toNumericObj(coordinates[0][0], factory), toNumericObj(coordinates[0][1], factory), toNumericObj(radius, factory))); + case BOX: + return (geometry = factory.createBox(coordSysObj, toNumericObj(coordinates[0][0], factory), toNumericObj(coordinates[0][1], factory), toNumericObj(width, factory), toNumericObj(height, factory))); + case POLYGON: + ArrayList<ADQLOperand> coords = new ArrayList<ADQLOperand>(coordinates.length * 2); + for(int i = 0; i < coordinates.length; i++){ + coords.add(toNumericObj(coordinates[i][0], factory)); + coords.add(toNumericObj(coordinates[i][1], factory)); + } + return (geometry = factory.createPolygon(coordSysObj, coords)); + default: + return (geometry = factory.createRegion(factory.createStringConstant(toString()))); + } + } + }catch(Exception pe){ + return null; + } + } + + /** + * <p>Convert a numeric value into an ADQL representation:</p> + * + * <ul> + * <li>If negative: NegativeOperand(NumericConstant(val))</li> + * <li>Otherwise: NumericConstant(val)</li> + * </ul> + * + * @param val The value to embed in an ADQL object. + * @param factory The factory to use to created ADQL objects. + * + * @return The representing ADQL representation. + * + * @throws Exception If an error occurs while creating the ADQL object. + */ + private ADQLOperand toNumericObj(final double val, final ADQLQueryFactory factory) throws Exception{ + if (val >= 0) + return factory.createNumericConstant("" + val); + else + return factory.createNegativeOperand(factory.createNumericConstant("" + (val * -1))); + } + } + + /** + * Parse the given STC-S expression representing a geometrical region. + * + * @param stcsRegion STC-S expression of a region. <i>Note: MUST be different from NULL.</i> + * + * @return The object representation of the specified geometrical region. + * + * @throws ParseException If the given expression is NULL, empty string or if the STC-S syntax is wrong. + */ + public static Region parseRegion(final String stcsRegion) throws ParseException{ + if (stcsRegion == null || stcsRegion.trim().length() == 0) + throw new ParseException("Missing STC-S expression to parse!"); + return (new STCSParser().parseRegion(stcsRegion)); + } + + /** + * Convert into STC-S the given object representation of a geometrical region. + * + * @param region Region to convert into STC-S. + * + * @return The corresponding STC-S expression. + */ + public static String toSTCS(final Region region){ + if (region == null) + throw new NullPointerException("Missing region to serialize into STC-S!"); + return region.toSTCS(); + } + + /** + * <p>Convert into STC-S the given ADQL representation of a geometrical function.</p> + * + * <p><i><b>Important note:</b> + * Only {@link PointFunction}, {@link CircleFunction}, {@link BoxFunction}, {@link PolygonFunction} + * and {@link RegionFunction} are accepted here. Other extensions of {@link GeometryFunction} will + * throw an {@link IllegalArgumentException}. + * </i></p> + * + * @param region ADQL representation of the region to convert into STC-S. + * + * @return The corresponding STC-S expression. + * + * @throws ParseException If the given object is NULL or not of the good type. + * + * @see {@link Region#Region(GeometryFunction)} + */ + public static String toSTCS(final GeometryFunction region) throws ParseException{ + if (region == null) + throw new NullPointerException("Missing region to serialize into STC-S!"); + return (new Region(region)).toSTCS(); + } + + /* *************************** */ + /* PARSER OF STC-S EXPRESSIONS */ + /* *************************** */ + + /** + * Let parse any STC-S expression. + * + * @author Grégory Mantelet (ARI) + * @version 1.3 (10/2014) + * @since 1.3 + */ + private static class STCSParser { + /** Regular expression of a numerical value. */ + private final static String numericRegExp = "(\\+|-)?(\\d+(\\.\\d*)?|\\.\\d+)([Ee](\\+|-)?\\d+)?"; + + /** Position of the next characters to read in the STC-S expression to parse. */ + private int pos; + /** Full STC-S expression to parse. */ + private String stcs; + /** Last read token (can be a numeric, a string, a region type, ...). */ + private String token; + /** Buffer used to read tokens. */ + private StringBuffer buffer; + + /** + * Exception sent when the end of the expression + * (EOE = End Of Expression) is reached. + * + * @author Grégory Mantelet (ARI) + * @version 1.3 (10/2014) + * @since 1.3 + */ + private static class EOEException extends ParseException { + private static final long serialVersionUID = 1L; + + /** Build a simple EOEException. */ + public EOEException(){ + super("Unexpected End Of Expression!"); + } + } + + /** + * Build the STC-S parser. + */ + public STCSParser(){} + + /** + * Parse the given STC-S expression, expected as a coordinate system. + * + * @param stcs The STC-S expression to parse. + * + * @return The corresponding object representation of the specified coordinate system. + * + * @throws ParseException If the syntax of the given STC-S expression is wrong or if it is not a coordinate system. + */ + public CoordSys parseCoordSys(final String stcs) throws ParseException{ + init(stcs); + CoordSys coordsys = null; + try{ + coordsys = coordSys(); + end(COORD_SYS_SYNTAX); + return coordsys; + }catch(EOEException ex){ + ex.printStackTrace(); + return new CoordSys(); + } + } + + /** + * Parse the given STC-S expression, expected as a geometrical region. + * + * @param stcs The STC-S expression to parse. + * + * @return The corresponding object representation of the specified geometrical region. + * + * @throws ParseException If the syntax of the given STC-S expression is wrong or if it is not a geometrical region. + */ + public Region parseRegion(final String stcs) throws ParseException{ + init(stcs); + Region region = region(); + end("\"POSITION <coordsys> <coordPair>\", \"CIRCLE <coordSys> <coordPair> <numeric>\", \"BOX <coordSys> <coordPair> <coordPair>\", \"POLYGON <coordSys> <coordPair> <coordPair> <coordPair> [<coordPair> ...]\", \"UNION <coordSys> ( <region> <region> [<region> ...] )\", \"INTERSECTION [<coordSys>] ( <region> <region> [<region> ...] )\" or \"NOT ( <region> )\""); + return region; + } + + /** + * Prepare the parser in order to read the given STC-S expression. + * + * @param newStcs New STC-S expression to parse from now. + */ + private void init(final String newStcs){ + stcs = (newStcs == null) ? "" : newStcs.replaceAll("\\s", " "); + token = null; + buffer = new StringBuffer(); + pos = 0; + } + + /** + * Finalize the parsing. + * No more characters (except eventually some space characters) should remain in the STC-S expression to parse. + * + * @param expectedSyntax Description of the good syntax expected. This description is used only to write the + * {@link ParseException} in case other non-space characters are found among the remaining characters. + * + * @throws ParseException If other non-space characters remains. + */ + private void end(final String expectedSyntax) throws ParseException{ + // Skip all spaces: + skipSpaces(); + + // If there is still some characters, they are not expected, and so throw an exception: + if (stcs.length() > 0 && pos < stcs.length()) + throw new ParseException("Incorrect syntax: \"" + stcs.substring(pos) + "\" was unexpected! Expected syntax: " + expectedSyntax + ".", new TextPosition(1, pos, 1, stcs.length())); + + // Reset the buffer, token and the STC-S expression to parse: + buffer = null; + stcs = null; + token = null; + } + + /** + * Tool function which skip all next space characters until the next meaningful characters. + */ + private void skipSpaces(){ + while(pos < stcs.length() && stcs.charAt(pos) == ' ') + pos++; + } + + /** + * <p>Get the next meaningful word. This word can be a numeric, any string constant or a region type.</p> + * + * <p> + * In case the end of the expression is reached before getting any meaningful character, an {@link EOEException} is thrown. + * </p> + * + * @return The full read word/token. + * + * @throws EOEException If the end of the STC-S expression is reached before getting any meaningful character. + */ + private String nextToken() throws EOEException{ + // Skip all spaces: + skipSpaces(); + + // Fetch all characters until word separator (a space or a open/close parenthesis): + while(pos < stcs.length() && stcs.charAt(pos) != ' ' && stcs.charAt(pos) != '(' && stcs.charAt(pos) != ')') + buffer.append(stcs.charAt(pos++)); + + // If no character has been fetched while at least one was expected, throw an exception: + if (buffer.length() == 0) + throw new EOEException(); + + // Save the read token and reset the buffer: + token = buffer.toString(); + buffer.delete(0, token.length()); + + return token; + } + + /** + * Read the next token as a numeric. + * If not a numeric, a {@link ParseException} is thrown. + * + * @return The read numerical value. + * + * @throws ParseException If the next token is not a numerical expression. + */ + private double numeric() throws ParseException{ + if (nextToken().matches(numericRegExp)) + return Double.parseDouble(token); + else + throw new ParseException("a numeric was expected!", new TextPosition(1, pos - token.length(), 1, pos)); // TODO Check the begin and end! + } + + /** + * Read the next 2 tokens as a coordinate pairs (so as 2 numerical values). + * If not 2 numeric, a {@link ParseException} is thrown. + * + * @return The read coordinate pairs. + * + * @throws ParseException If the next 2 tokens are not 2 numerical expressions. + */ + private double[] coordPair() throws ParseException{ + skipSpaces(); + int startPos = pos; + try{ + return new double[]{numeric(),numeric()}; + }catch(ParseException pe){ + if (pe instanceof EOEException) + throw pe; + else + throw new ParseException("a coordinates pair (2 numerics separated by one or more spaces) was expected!", new TextPosition(1, startPos, 1, pos)); // TODO Check the begin and end! + } + } + + /** + * Read and parse the next tokens as a coordinate system expression. + * If they do not match, a {@link ParseException} is thrown. + * + * @return The object representation of the read coordinate system. + * + * @throws ParseException If the next tokens are not representing a valid coordinate system. + */ + private CoordSys coordSys() throws ParseException{ + // Skip all spaces: + skipSpaces(); + + // Backup the current position: + /* (because every parts of a coordinate system are optional ; + * like this, it will be possible to go back in the expression + * to parse if optional parts are not written) */ + String oldToken = token; + int startPos = pos; + + Frame fr = null; + RefPos rp = null; + Flavor fl = null; + + try{ + // Read the token: + nextToken(); + // Try to parse it as a frame: + if ((fr = frame()) != null){ + // if success, go the next token: + startPos = pos; + oldToken = token; + nextToken(); + } + // Try to parse the last read token as a reference position: + if ((rp = refpos()) != null){ + // if success, go the next token: + startPos = pos; + oldToken = token; + nextToken(); + } + // Try to parse the last read token as a flavor: + if ((fl = flavor()) == null){ + // if NOT a success, go back "in time" (go back to the position before reading the token): + pos = startPos; + token = oldToken; + } + }catch(EOEException ex){ + /* End Of Expression may happen here since all parts of a coordinate system are optional. + * So, there is no need to treat the error. */ + } + + // Build the object representation of the read coordinate system: + /* Note: if nothing has been read for one or all parts of the coordinate system, + * the NULL value will be replaced automatically in the constructor + * by the default value of the corresponding part(s). */ + try{ + return new CoordSys(fr, rp, fl); + }catch(IllegalArgumentException iae){ + throw new ParseException(iae.getMessage(), new TextPosition(1, startPos, 1, pos)); + } + } + + /** + * Parse the last read token as FRAME. + * + * @return The corresponding enumeration item, or NULL if the last token is not a valid FRAME item. + */ + private Frame frame(){ + try{ + return Frame.valueOf(token.toUpperCase()); + }catch(IllegalArgumentException iae){ + return null; + } + } + + /** + * Parse the last read token as REFERENCE POSITION. + * + * @return The corresponding enumeration item, or NULL if the last token is not a valid REFERENCE POSITION item. + */ + private RefPos refpos(){ + try{ + return RefPos.valueOf(token.toUpperCase()); + }catch(IllegalArgumentException iae){ + return null; + } + } + + /** + * Parse the last read token as FLAVOR. + * + * @return The corresponding enumeration item, or NULL if the last token is not a valid FLAVOR item. + */ + private Flavor flavor(){ + try{ + return Flavor.valueOf(token.toUpperCase()); + }catch(IllegalArgumentException iae){ + return null; + } + } + + /** + * Read and parse the next tokens as a geometrical region. + * If they do not match, a {@link ParseException} is thrown. + * + * @return The object representation of the read geometrical region. + * + * @throws ParseException If the next tokens are not representing a valid geometrical region. + */ + private Region region() throws ParseException{ + // Skip all spaces: + skipSpaces(); + + // Read the next token (it should be the region type): + int startPos = pos; + token = nextToken().toUpperCase(); + + /* Identify the region type, next the expected parameters and finally build the corresponding object representation */ + // POSITION case: + if (token.equals("POSITION")){ + try{ + CoordSys coordSys = coordSys(); + double[] coords = coordPair(); + return new Region(coordSys, coords); + }catch(Exception e){ + throw buildException(e, "\"POSITION <coordSys> <coordPair>\", where coordPair=\"<numeric> <numeric>\" and coordSys=" + COORD_SYS_SYNTAX, startPos); + } + } + // CIRCLE case: + else if (token.equals("CIRCLE")){ + try{ + CoordSys coordSys = coordSys(); + double[] coords = coordPair(); + double radius = numeric(); + return new Region(coordSys, coords, radius); + }catch(Exception e){ + throw buildException(e, "\"CIRCLE <coordSys> <coordPair> <radius>\", where coordPair=\"<numeric> <numeric>\", radius=\"<numeric>\" and coordSys=" + COORD_SYS_SYNTAX, startPos); + } + } + // BOX case: + else if (token.equals("BOX")){ + try{ + CoordSys coordSys = coordSys(); + double[] coords = coordPair(); + double width = numeric(), height = numeric(); + return new Region(coordSys, coords, width, height); + }catch(Exception e){ + throw buildException(e, "\"BOX <coordSys> <coordPair> <width> <height>\", where coordPair=\"<numeric> <numeric>\", width and height=\"<numeric>\" and coordSys=" + COORD_SYS_SYNTAX, startPos); + } + } + // POLYGON case: + else if (token.equals("POLYGON")){ + try{ + CoordSys coordSys = coordSys(); + ArrayList<Double> coordinates = new ArrayList<Double>(6); + double[] coords; + for(int i = 0; i < 3; i++){ + coords = coordPair(); + coordinates.add(coords[0]); + coordinates.add(coords[1]); + } + boolean moreCoord = true; + int posBackup; + do{ + posBackup = pos; + try{ + coords = coordPair(); + coordinates.add(coords[0]); + coordinates.add(coords[1]); + }catch(ParseException pe){ + moreCoord = false; + pos = posBackup; + } + }while(moreCoord); + double[][] allCoords = new double[coordinates.size() / 2][2]; + for(int i = 0; i < coordinates.size() && i + 1 < coordinates.size(); i += 2) + allCoords[i / 2] = new double[]{coordinates.get(i),coordinates.get(i + 1)}; + return new Region(coordSys, allCoords); + }catch(Exception e){ + throw buildException(e, "\"POLYGON <coordSys> <coordPair> <coordPair> <coordPair> [<coordPair> ...]\", where coordPair=\"<numeric> <numeric>\" and coordSys=" + COORD_SYS_SYNTAX, startPos); + } + } + // UNION & INTERSECTION cases: + else if (token.equals("UNION") || token.equals("INTERSECTION")){ + RegionType type = (token.equals("UNION") ? RegionType.UNION : RegionType.INTERSECTION); + try{ + CoordSys coordSys = coordSys(); + ArrayList<Region> regions = new ArrayList<Region>(2); + + skipSpaces(); + if (stcs.charAt(pos) != '(') + throw buildException(new ParseException("a opening parenthesis - ( - was expected!", new TextPosition(1, pos, 1, pos + 1)), "\"" + type + " <coordSys> ( <region> <region> [<region> ...] )\", where coordSys=" + COORD_SYS_SYNTAX, startPos); + else + pos++; + + // parse and add the FIRST region: + regions.add(region()); + + // parse and add the SECOND region: + regions.add(region()); + + skipSpaces(); + while(stcs.charAt(pos) != ')'){ + regions.add(region()); + skipSpaces(); + } + pos++; + + return new Region(type, coordSys, regions.toArray(new Region[regions.size()])); + }catch(Exception e){ + if (e instanceof ParseException && e.getMessage().startsWith("Incorrect syntax: \"")) + throw (ParseException)e; + else + throw buildException(e, "\"" + type + " <coordSys> ( <region> <region> [<region> ...] )\", where coordSys=" + COORD_SYS_SYNTAX, startPos); + } + } + // NOT case: + else if (token.equals("NOT")){ + try{ + skipSpaces(); + if (stcs.charAt(pos) != '(') + throw buildException(new ParseException("an opening parenthesis - ( - was expected!", new TextPosition(1, pos, 1, pos + 1)), "\"NOT ( <region> )\"", startPos); + else + pos++; + Region region = region(); + skipSpaces(); + if (stcs.charAt(pos) != ')') + throw buildException(new ParseException("a closing parenthesis - ) - was expected!", new TextPosition(1, pos, 1, pos + 1)), "\"NOT ( <region> )\"", startPos); + else + pos++; + return new Region(region); + }catch(Exception e){ + if (e instanceof ParseException && e.getMessage().startsWith("Incorrect syntax: ")) + throw (ParseException)e; + else + throw buildException(e, "\"NOT ( <region> )\"", startPos); + } + } + // Otherwise, the region type is not known and so a ParseException is thrown: + else + throw new ParseException("Unknown STC region type: \"" + token + "\"!", new TextPosition(1, startPos, 1, pos)); + } + + /** + * Build a {@link ParseException} based on the given one and by adding the human description of what was expected, if needed. + * + * @param ex Root exception. + * @param expectedSyntax Human description of what was expected. + * @param startPos Position of the first character of the wrong part of expression. + * + * @return The build exception. + */ + private ParseException buildException(final Exception ex, final String expectedSyntax, int startPos){ + if (ex instanceof EOEException) + return new ParseException("Unexpected End Of Expression! Expected syntax: " + expectedSyntax + ".", new TextPosition(1, startPos, 1, pos)); + else if (ex instanceof ParseException) + return new ParseException("Incorrect syntax: " + ex.getMessage() + " Expected syntax: " + expectedSyntax + ".", (((ParseException)ex).getPosition() != null ? ((ParseException)ex).getPosition() : new TextPosition(1, startPos, 1, pos))); + else + return new ParseException(ex.getMessage(), new TextPosition(1, startPos, 1, pos)); + } + } +} diff --git a/src/adql/db/SearchColumnList.java b/src/adql/db/SearchColumnList.java index 8411e4be31d939e6fc6670230eb1210b8fc33fcb..e385cb7890b2f632018538f2060d666da64528e5 100644 --- a/src/adql/db/SearchColumnList.java +++ b/src/adql/db/SearchColumnList.java @@ -17,7 +17,7 @@ package adql.db; * along with ADQLLibrary. If not, see <http://www.gnu.org/licenses/>. * * Copyright 2012-2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS), - * Astronomishes Rechen Institut (ARI) + * Astronomisches Rechen Institut (ARI) */ import java.util.ArrayList; diff --git a/src/adql/db/exception/UnresolvedFunction.java b/src/adql/db/exception/UnresolvedFunction.java new file mode 100644 index 0000000000000000000000000000000000000000..b6eb4597a2dcbb7f5c83b606386df762b07f37a0 --- /dev/null +++ b/src/adql/db/exception/UnresolvedFunction.java @@ -0,0 +1,124 @@ +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 2014 - Astronomisches Rechen Institut (ARI) + */ + +import adql.parser.ParseException; +import adql.query.operand.function.ADQLFunction; + +/** + * Exception thrown when a function can not be resolved by the library. + * + * @author Grégory Mantelet (ARI) + * @version 1.3 (10/2014) + * @since 1.3 + */ +public class UnresolvedFunction extends ParseException { + private static final long serialVersionUID = 1L; + + /** Function which can not be resolved. */ + protected final ADQLFunction functionInError; + + /** + * Build the exception with just a message. + * + * @param message Description of the error. + */ + public UnresolvedFunction(final String message){ + super(message); + functionInError = null; + } + + /** + * Build the exception with the unresolved function in parameter. + * The position of this function in the ADQL query can be retrieved and used afterwards. + * + * @param fct The unresolved function. + */ + public UnresolvedFunction(final ADQLFunction fct){ + super("Unresolved function: \"" + fct.toADQL() + "\"! No UDF has been defined or found with the signature: " + getFctSignature(fct) + "."); // TODO Add the position of the function in the ADQL query! + functionInError = fct; + } + + /** + * Build the exception with a message but also with the unresolved function in parameter. + * The position of this function in the ADQL query can be retrieved and used afterwards. + * + * @param message Description of the error. + * @param fct The unresolved function. + */ + public UnresolvedFunction(final String message, final ADQLFunction fct){ + super(message); // TODO Add the position of the function in the ADQL query! + functionInError = fct; + } + + /** + * Get the unresolved function at the origin of this exception. + * + * @return The unresolved function. <i>Note: MAY be NULL</i> + */ + public final ADQLFunction getFunction(){ + return functionInError; + } + + /** + * <p>Get the signature of the function given in parameter.</p> + * + * <p> + * In this signature, just the name and the type of all the parameters are written. + * The return type is never part of a function signature. + * </p> + * + * <p><i>Note 1: + * A parameter type can be either "NUMERIC", "STRING" or "GEOMETRY". In order to be the most generic has possible, + * no more precision about a type is returned here. If the parameter is none of these type kinds, "???" is returned. + * </i></p> + * + * <p><i>Note 2: + * If the given object is NULL, an empty string is returned. + * </i></p> + * + * @param fct Function whose the signature must be returned. + * + * @return The corresponding signature. + */ + public static String getFctSignature(final ADQLFunction fct){ + if (fct == null) + return ""; + + StringBuffer buf = new StringBuffer(fct.getName().toLowerCase()); + buf.append('('); + for(int i = 0; i < fct.getNbParameters(); i++){ + if (fct.getParameter(i).isNumeric()) + buf.append("NUMERIC"); + else if (fct.getParameter(i).isString()) + buf.append("STRING"); + else if (fct.getParameter(i).isGeometry()) + buf.append("GEOMETRY"); + else + buf.append("???"); + + if ((i + 1) < fct.getNbParameters()) + buf.append(", "); + } + buf.append(')'); + return buf.toString(); + } + +} diff --git a/src/adql/db/exception/UnresolvedIdentifiersException.java b/src/adql/db/exception/UnresolvedIdentifiersException.java index b141befb55700ffa2a51f0d39fcba06d58d61d0f..8c201871deaee87e6a31245c461edab207b34a59 100644 --- a/src/adql/db/exception/UnresolvedIdentifiersException.java +++ b/src/adql/db/exception/UnresolvedIdentifiersException.java @@ -71,6 +71,10 @@ public class UnresolvedIdentifiersException extends ParseException implements It String tableName = ((UnresolvedTableException)pe).getTableName(); if (tableName != null && !tableName.trim().isEmpty()) addIdentifierName(tableName + " " + pe.getPosition()); + /*}else if (pe instanceof UnresolvedFunction){ // TODO MANAGE ALSO THE UNRESOLVED_FUNCTIONs! + String fctName = (((UnresolvedFunction)pe).getFunction() == null) ? null : ((UnresolvedFunction)pe).getFunction().getName(); + if (fctName != null && !fctName.trim().isEmpty()) + addIdentifierName(fctName + " " + pe.getPosition());*/ }else if (pe instanceof UnresolvedIdentifiersException) addIdentifierName(((UnresolvedIdentifiersException)pe).unresolvedIdentifiers); } @@ -109,6 +113,7 @@ public class UnresolvedIdentifiersException extends ParseException implements It return exceptions.iterator(); } + @Override public final Iterator<ParseException> iterator(){ return getErrors(); } @@ -120,7 +125,11 @@ public class UnresolvedIdentifiersException extends ParseException implements It */ @Override public String getMessage(){ - return exceptions.size() + " unresolved identifiers" + ((unresolvedIdentifiers != null) ? (": " + unresolvedIdentifiers) : "") + " !"; + StringBuffer buf = new StringBuffer(); + buf.append(exceptions.size()).append(" unresolved identifiers").append(((unresolvedIdentifiers != null) ? (": " + unresolvedIdentifiers) : "")).append('!'); + for(ParseException pe : exceptions) + buf.append("\n - ").append(pe.getMessage()); + return buf.toString(); } } diff --git a/src/adql/db/exception/UnresolvedJoin.java b/src/adql/db/exception/UnresolvedJoin.java index c92440ece0b61b79c525f697c642783ccfc6049c..819beaa17211c3496ad0faacfc6957298b6c9470 100644 --- a/src/adql/db/exception/UnresolvedJoin.java +++ b/src/adql/db/exception/UnresolvedJoin.java @@ -16,7 +16,7 @@ package adql.db.exception; * 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 2013-2014 - Astronomishes Rechen Institut (ARI) + * Copyright 2013-2014 - Astronomisches Rechen Institut (ARI) */ import adql.parser.ParseException; diff --git a/src/adql/parser/ADQLParser.java b/src/adql/parser/ADQLParser.java index b1649f8a3a5e508e0ee2b99ab910b198977687c1..b454aadd5a94c66214739a5d97528e934f5e2a8a 100644 --- a/src/adql/parser/ADQLParser.java +++ b/src/adql/parser/ADQLParser.java @@ -4,7 +4,6 @@ package adql.parser; import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; -import java.util.Collection; import java.util.Stack; import java.util.Vector; @@ -32,7 +31,6 @@ import adql.query.operand.ADQLColumn; import adql.query.operand.ADQLOperand; import adql.query.operand.Concatenation; import adql.query.operand.OperationType; -import adql.query.operand.StringConstant; import adql.query.operand.function.ADQLFunction; import adql.query.operand.function.MathFunction; import adql.query.operand.function.MathFunctionType; @@ -61,7 +59,7 @@ import adql.translator.TranslationException; * @see ADQLQueryFactory * * @author Grégory Mantelet (CDS;ARI) - gmantele@ari.uni-heidelberg.de -* @version 1.2 (03/2014) +* @version 1.3 (10/2014) */ public class ADQLParser implements ADQLParserConstants { @@ -80,9 +78,6 @@ public class ADQLParser implements ADQLParserConstants { /** The first token of a table/column name. This token is extracted by {@link #Identifier()}. */ private Token currentIdentifierToken = null; - /** List of all allowed coordinate systems. */ - private ArrayList<String> allowedCoordSys = new ArrayList<String>(); - /** * Builds an ADQL parser without a query to parse. */ @@ -320,24 +315,6 @@ public class ADQLParser implements ADQLParserConstants { return Query(); } - public final void addCoordinateSystem(final String coordSys){ - allowedCoordSys.add(coordSys); - } - - public final void setCoordinateSystems(final Collection<String> coordSys){ - allowedCoordSys.clear(); - if (coordSys != null) - allowedCoordSys.addAll(coordSys); - } - - public final boolean isAllowedCoordSys(final String coordSys){ - for(String cs : allowedCoordSys){ - if (cs.equalsIgnoreCase(coordSys)) - return true; - } - return false; - } - public final void setDebug(boolean debug){ if (debug) enable_tracing(); @@ -493,1190 +470,1598 @@ public class ADQLParser implements ADQLParserConstants { * @throws ParseException If the query syntax is incorrect. */ final public ADQLQuery Query() throws ParseException{ - trace_call("Query"); + ADQLQuery q = null; + q = QueryExpression(); + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case 0: + jj_consume_token(0); + break; + case EOQ: + jj_consume_token(EOQ); + break; + default: + jj_la1[0] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + // check the query: + if (queryChecker != null) + queryChecker.check(q); + + { + if (true) + return q; + } + throw new Error("Missing return statement in function"); + } + + final public ADQLQuery QueryExpression() throws ParseException{ try{ - ADQLQuery q = null; - q = QueryExpression(); + // create the query: + query = queryFactory.createQuery(); + stackQuery.push(query); + }catch(Exception ex){ + { + if (true) + throw generateParseException(ex); + } + } + Select(); + From(); + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case WHERE: + Where(); + break; + default: + jj_la1[1] = jj_gen; + ; + } + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case GROUP_BY: + GroupBy(); + break; + default: + jj_la1[2] = jj_gen; + ; + } + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case HAVING: + Having(); + break; + default: + jj_la1[3] = jj_gen; + ; + } + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case ORDER_BY: + OrderBy(); + break; + default: + jj_la1[4] = jj_gen; + ; + } + // get the previous query (!= null if the current query is a sub-query): + ADQLQuery previousQuery = stackQuery.pop(); + if (stackQuery.isEmpty()) + query = null; + else + query = stackQuery.peek(); + + { + if (true) + return previousQuery; + } + throw new Error("Missing return statement in function"); + } + + final public ADQLQuery SubQueryExpression() throws ParseException{ + ADQLQuery q = null; + jj_consume_token(LEFT_PAR); + q = QueryExpression(); + jj_consume_token(RIGHT_PAR); + { + if (true) + return q; + } + throw new Error("Missing return statement in function"); + } + + final public void Select() throws ParseException{ + ClauseSelect select = query.getSelect(); + SelectItem item = null; + Token t = null; + jj_consume_token(SELECT); + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case QUANTIFIER: + t = jj_consume_token(QUANTIFIER); + select.setDistinctColumns(t.image.equalsIgnoreCase("DISTINCT")); + break; + default: + jj_la1[5] = jj_gen; + ; + } + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case TOP: + jj_consume_token(TOP); + t = jj_consume_token(UNSIGNED_INTEGER); + try{ + select.setLimit(Integer.parseInt(t.image)); + }catch(NumberFormatException nfe){ + { + if (true) + throw new ParseException("[l." + t.beginLine + ";c." + t.beginColumn + "] The TOP limit (\u005c"" + t.image + "\u005c") isn't a regular unsigned integer !"); + } + } + break; + default: + jj_la1[6] = jj_gen; + ; + } + item = SelectItem(); + select.add(item); + label_1: while(true){ switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case 0: - jj_consume_token(0); - break; - case EOQ: - jj_consume_token(EOQ); + case COMMA: + ; break; default: - jj_la1[0] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); + jj_la1[7] = jj_gen; + break label_1; } - // check the query: - if (queryChecker != null) - queryChecker.check(q); + jj_consume_token(COMMA); + item = SelectItem(); + select.add(item); + } + } + final public SelectItem SelectItem() throws ParseException{ + IdentifierItems identifiers = new IdentifierItems(true); + IdentifierItem id = null, label = null; + ADQLOperand op = null; + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case ASTERISK: + jj_consume_token(ASTERISK); + { + if (true) + return new SelectAllColumns(query); + } + break; + default: + jj_la1[11] = jj_gen; + if (jj_2_1(7)){ + id = Identifier(); + jj_consume_token(DOT); + identifiers.append(id); + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case DELIMITED_IDENTIFIER: + case REGULAR_IDENTIFIER: + id = Identifier(); + jj_consume_token(DOT); + identifiers.append(id); + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case DELIMITED_IDENTIFIER: + case REGULAR_IDENTIFIER: + id = Identifier(); + jj_consume_token(DOT); + identifiers.append(id); + break; + default: + jj_la1[8] = jj_gen; + ; + } + break; + default: + jj_la1[9] = jj_gen; + ; + } + jj_consume_token(ASTERISK); + try{ + ; + { + if (true) + return new SelectAllColumns(queryFactory.createTable(identifiers, null)); + } + }catch(Exception ex){ + { + if (true) + throw generateParseException(ex); + } + } + }else{ + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case LEFT_PAR: + case PLUS: + case MINUS: + case AVG: + case MAX: + case MIN: + case SUM: + case COUNT: + case BOX: + case CENTROID: + case CIRCLE: + case POINT: + case POLYGON: + case REGION: + case CONTAINS: + case INTERSECTS: + case AREA: + case COORD1: + case COORD2: + case COORDSYS: + case DISTANCE: + case ABS: + case CEILING: + case DEGREES: + case EXP: + case FLOOR: + case LOG: + case LOG10: + case MOD: + case PI: + case POWER: + case RADIANS: + case RAND: + case ROUND: + case SQRT: + case TRUNCATE: + case ACOS: + case ASIN: + case ATAN: + case ATAN2: + case COS: + case COT: + case SIN: + case TAN: + case STRING_LITERAL: + case DELIMITED_IDENTIFIER: + case REGULAR_IDENTIFIER: + case SCIENTIFIC_NUMBER: + case UNSIGNED_FLOAT: + case UNSIGNED_INTEGER: + op = ValueExpression(); + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case AS: + jj_consume_token(AS); + label = Identifier(); + break; + default: + jj_la1[10] = jj_gen; + ; + } + break; + default: + jj_la1[12] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + } + } + try{ + SelectItem item = queryFactory.createSelectItem(op, (label == null) ? null : label.identifier); + if (label != null) + item.setCaseSensitive(label.caseSensitivity); { if (true) - return q; + return item; + } + }catch(Exception ex){ + { + if (true) + throw generateParseException(ex); } - throw new Error("Missing return statement in function"); - }finally{ - trace_return("Query"); } + throw new Error("Missing return statement in function"); } - final public ADQLQuery QueryExpression() throws ParseException{ - trace_call("QueryExpression"); + final public void From() throws ParseException{ + FromContent content = null, content2 = null; try{ - try{ - // create the query: - query = queryFactory.createQuery(); - stackQuery.push(query); - }catch(Exception ex){ - { - if (true) - throw generateParseException(ex); + jj_consume_token(FROM); + content = TableRef(); + label_2: while(true){ + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case COMMA: + ; + break; + default: + jj_la1[13] = jj_gen; + break label_2; } + jj_consume_token(COMMA); + content2 = TableRef(); + content = queryFactory.createJoin(JoinType.CROSS, content, content2); } - Select(); - From(); - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case WHERE: - Where(); - break; - default: - jj_la1[1] = jj_gen; - ; + query.setFrom(content); + }catch(Exception ex){ + { + if (true) + throw generateParseException(ex); } + } + } + + final public void Where() throws ParseException{ + ClauseConstraints where = query.getWhere(); + ADQLConstraint condition; + jj_consume_token(WHERE); + ConditionsList(where); + } + + final public void GroupBy() throws ParseException{ + ClauseADQL<ColumnReference> groupBy = query.getGroupBy(); + ColumnReference colRef = null; + jj_consume_token(GROUP_BY); + colRef = ColumnRef(); + groupBy.add(colRef); + label_3: while(true){ switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case GROUP_BY: - GroupBy(); - break; - default: - jj_la1[2] = jj_gen; + case COMMA: ; - } - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case HAVING: - Having(); break; default: - jj_la1[3] = jj_gen; - ; + jj_la1[14] = jj_gen; + break label_3; } + jj_consume_token(COMMA); + colRef = ColumnRef(); + groupBy.add(colRef); + } + } + + final public void Having() throws ParseException{ + ClauseConstraints having = query.getHaving(); + jj_consume_token(HAVING); + ConditionsList(having); + } + + final public void OrderBy() throws ParseException{ + ClauseADQL<ADQLOrder> orderBy = query.getOrderBy(); + ADQLOrder order = null; + jj_consume_token(ORDER_BY); + order = OrderItem(); + orderBy.add(order); + label_4: while(true){ switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case ORDER_BY: - OrderBy(); + case COMMA: + ; break; default: - jj_la1[4] = jj_gen; - ; + jj_la1[15] = jj_gen; + break label_4; } - // get the previous query (!= null if the current query is a sub-query): - ADQLQuery previousQuery = stackQuery.pop(); - if (stackQuery.isEmpty()) - query = null; - else - query = stackQuery.peek(); + jj_consume_token(COMMA); + order = OrderItem(); + orderBy.add(order); + } + } - { - if (true) - return previousQuery; - } - throw new Error("Missing return statement in function"); - }finally{ - trace_return("QueryExpression"); + /* *************************** */ + /* COLUMN AND TABLE REFERENCES */ + /* *************************** */ + final public IdentifierItem Identifier() throws ParseException{ + Token t; + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case REGULAR_IDENTIFIER: + t = jj_consume_token(REGULAR_IDENTIFIER); + { + if (true) + return new IdentifierItem(t, false); + } + break; + case DELIMITED_IDENTIFIER: + t = jj_consume_token(DELIMITED_IDENTIFIER); + { + if (true) + return new IdentifierItem(t, true); + } + break; + default: + jj_la1[16] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); } + throw new Error("Missing return statement in function"); } - final public ADQLQuery SubQueryExpression() throws ParseException{ - trace_call("SubQueryExpression"); + /** + * Extracts the name of a table with its possible catalog and schema prefixes. + * + * @return A {@link IdentifierItems} which contains at most three items: catalogName, schemaName and tableName. + */ + final public IdentifierItems TableName() throws ParseException{ + IdentifierItems identifiers = new IdentifierItems(true); + IdentifierItem id = null; + id = Identifier(); + identifiers.append(id); + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case DOT: + jj_consume_token(DOT); + id = Identifier(); + identifiers.append(id); + break; + default: + jj_la1[17] = jj_gen; + ; + } + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case DOT: + jj_consume_token(DOT); + id = Identifier(); + identifiers.append(id); + break; + default: + jj_la1[18] = jj_gen; + ; + } + { + if (true) + return identifiers; + } + throw new Error("Missing return statement in function"); + } + + /** + * Extracts the name of a column with its possible catalog, schema and table prefixes. + * + * @return A {@link IdentifierItems} which contains at most four items: catalogName, schemaName, tableName and columnName. + */ + final public IdentifierItems ColumnName() throws ParseException{ + IdentifierItem id; + IdentifierItems table = null, identifiers = new IdentifierItems(false); + id = Identifier(); + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case DOT: + jj_consume_token(DOT); + table = TableName(); + break; + default: + jj_la1[19] = jj_gen; + ; + } + identifiers.append(id); + if (table != null){ + for(int i = 0; i < table.size(); i++) + identifiers.append(table.get(i)); + } + { + if (true) + return identifiers; + } + throw new Error("Missing return statement in function"); + } + + final public ADQLColumn Column() throws ParseException{ + IdentifierItems identifiers; + identifiers = ColumnName(); try{ - ADQLQuery q = null; - jj_consume_token(LEFT_PAR); - q = QueryExpression(); - jj_consume_token(RIGHT_PAR); { if (true) - return q; + return queryFactory.createColumn(identifiers); + } + }catch(Exception ex){ + { + if (true) + throw generateParseException(ex); } - throw new Error("Missing return statement in function"); - }finally{ - trace_return("SubQueryExpression"); } + throw new Error("Missing return statement in function"); } - final public void Select() throws ParseException{ - trace_call("Select"); + final public ColumnReference ColumnRef() throws ParseException{ + IdentifierItems identifiers = null; + Token ind = null; + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case DELIMITED_IDENTIFIER: + case REGULAR_IDENTIFIER: + identifiers = ColumnName(); + break; + case UNSIGNED_INTEGER: + ind = jj_consume_token(UNSIGNED_INTEGER); + break; + default: + jj_la1[20] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } try{ - ClauseSelect select = query.getSelect(); - SelectItem item = null; - Token t = null; - jj_consume_token(SELECT); - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case QUANTIFIER: - t = jj_consume_token(QUANTIFIER); - select.setDistinctColumns(t.image.equalsIgnoreCase("DISTINCT")); - break; - default: - jj_la1[5] = jj_gen; - ; + ColumnReference colRef = null; + if (identifiers != null) + colRef = queryFactory.createColRef(identifiers); + else + colRef = queryFactory.createColRef(Integer.parseInt(ind.image), new TextPosition(ind)); + { + if (true) + return colRef; } - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case TOP: - jj_consume_token(TOP); - t = jj_consume_token(UNSIGNED_INTEGER); - try{ - select.setLimit(Integer.parseInt(t.image)); - }catch(NumberFormatException nfe){ - { - if (true) - throw new ParseException("[l." + t.beginLine + ";c." + t.beginColumn + "] The TOP limit (\u005c"" + t.image + "\u005c") isn't a regular unsigned integer !"); - } - } - break; - default: - jj_la1[6] = jj_gen; - ; + }catch(Exception ex){ + { + if (true) + throw generateParseException(ex); } - item = SelectItem(); - select.add(item); - label_1: while(true){ + } + throw new Error("Missing return statement in function"); + } + + final public ADQLOrder OrderItem() throws ParseException{ + IdentifierItems identifiers = null; + Token ind = null, desc = null; + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case DELIMITED_IDENTIFIER: + case REGULAR_IDENTIFIER: + identifiers = ColumnName(); + break; + case UNSIGNED_INTEGER: + ind = jj_consume_token(UNSIGNED_INTEGER); + break; + default: + jj_la1[21] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case ASC: + case DESC: switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case COMMA: - ; + case ASC: + jj_consume_token(ASC); + break; + case DESC: + desc = jj_consume_token(DESC); break; default: - jj_la1[7] = jj_gen; - break label_1; + jj_la1[22] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); } - jj_consume_token(COMMA); - item = SelectItem(); - select.add(item); + break; + default: + jj_la1[23] = jj_gen; + ; + } + try{ + ADQLOrder order = null; + if (identifiers != null) + order = queryFactory.createOrder(identifiers, desc != null); + else + order = queryFactory.createOrder(Integer.parseInt(ind.image), desc != null, new TextPosition(ind)); + { + if (true) + return order; + } + }catch(Exception ex){ + { + if (true) + throw generateParseException(ex); } - }finally{ - trace_return("Select"); } + throw new Error("Missing return statement in function"); } - final public SelectItem SelectItem() throws ParseException{ - trace_call("SelectItem"); + final public FromContent SimpleTableRef() throws ParseException{ + IdentifierItem alias = null; + IdentifierItems identifiers = null; + ADQLQuery subQuery = null; + FromContent content = null; try{ - IdentifierItems identifiers = new IdentifierItems(true); - IdentifierItem id = null, label = null; - ADQLOperand op = null; switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case ASTERISK: - jj_consume_token(ASTERISK); + case DELIMITED_IDENTIFIER: + case REGULAR_IDENTIFIER: + identifiers = TableName(); + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case AS: + case DELIMITED_IDENTIFIER: + case REGULAR_IDENTIFIER: + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case AS: + jj_consume_token(AS); + break; + default: + jj_la1[24] = jj_gen; + ; + } + alias = Identifier(); + break; + default: + jj_la1[25] = jj_gen; + ; + } { if (true) - return new SelectAllColumns(query); + return queryFactory.createTable(identifiers, alias); } break; default: - jj_la1[11] = jj_gen; - if (jj_2_1(7)){ - id = Identifier(); - jj_consume_token(DOT); - identifiers.append(id); + jj_la1[27] = jj_gen; + if (jj_2_2(2)){ + subQuery = SubQueryExpression(); switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case DELIMITED_IDENTIFIER: - case REGULAR_IDENTIFIER: - id = Identifier(); - jj_consume_token(DOT); - identifiers.append(id); - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case DELIMITED_IDENTIFIER: - case REGULAR_IDENTIFIER: - id = Identifier(); - jj_consume_token(DOT); - identifiers.append(id); - break; - default: - jj_la1[8] = jj_gen; - ; - } + case AS: + jj_consume_token(AS); break; default: - jj_la1[9] = jj_gen; + jj_la1[26] = jj_gen; ; } - jj_consume_token(ASTERISK); - try{ - ; - { - if (true) - return new SelectAllColumns(queryFactory.createTable(identifiers, null)); - } - }catch(Exception ex){ - { - if (true) - throw generateParseException(ex); - } + alias = Identifier(); + { + if (true) + return queryFactory.createTable(subQuery, alias); } }else{ switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ case LEFT_PAR: - case PLUS: - case MINUS: - case AVG: - case MAX: - case MIN: - case SUM: - case COUNT: - case BOX: - case CENTROID: - case CIRCLE: - case POINT: - case POLYGON: - case REGION: - case CONTAINS: - case INTERSECTS: - case AREA: - case COORD1: - case COORD2: - case COORDSYS: - case DISTANCE: - case ABS: - case CEILING: - case DEGREES: - case EXP: - case FLOOR: - case LOG: - case LOG10: - case MOD: - case PI: - case POWER: - case RADIANS: - case RAND: - case ROUND: - case SQRT: - case TRUNCATE: - case ACOS: - case ASIN: - case ATAN: - case ATAN2: - case COS: - case COT: - case SIN: - case TAN: - case STRING_LITERAL: - case DELIMITED_IDENTIFIER: - case REGULAR_IDENTIFIER: - case SCIENTIFIC_NUMBER: - case UNSIGNED_FLOAT: - case UNSIGNED_INTEGER: - op = ValueExpression(); - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case AS: - jj_consume_token(AS); - label = Identifier(); - break; - default: - jj_la1[10] = jj_gen; - ; + jj_consume_token(LEFT_PAR); + content = JoinedTable(); + jj_consume_token(RIGHT_PAR); + { + if (true) + return content; } break; default: - jj_la1[12] = jj_gen; + jj_la1[28] = jj_gen; jj_consume_token(-1); throw new ParseException(); } } } - try{ - SelectItem item = queryFactory.createSelectItem(op, (label == null) ? null : label.identifier); - if (label != null) - item.setCaseSensitive(label.caseSensitivity); - { - if (true) - return item; - } - }catch(Exception ex){ - { - if (true) - throw generateParseException(ex); - } + }catch(Exception ex){ + { + if (true) + throw generateParseException(ex); } - throw new Error("Missing return statement in function"); - }finally{ - trace_return("SelectItem"); } + throw new Error("Missing return statement in function"); } - final public void From() throws ParseException{ - trace_call("From"); - try{ - FromContent content = null, content2 = null; - try{ - jj_consume_token(FROM); - content = TableRef(); - label_2: while(true){ - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case COMMA: - ; - break; - default: - jj_la1[13] = jj_gen; - break label_2; - } - jj_consume_token(COMMA); - content2 = TableRef(); - content = queryFactory.createJoin(JoinType.CROSS, content, content2); - } - query.setFrom(content); - }catch(Exception ex){ - { - if (true) - throw generateParseException(ex); - } + final public FromContent TableRef() throws ParseException{ + FromContent content; + content = SimpleTableRef(); + label_5: while(true){ + if (jj_2_3(2)){ + ; + }else{ + break label_5; } - }finally{ - trace_return("From"); + content = JoinSpecification(content); } - } - - final public void Where() throws ParseException{ - trace_call("Where"); - try{ - ClauseConstraints where = query.getWhere(); - ADQLConstraint condition; - jj_consume_token(WHERE); - ConditionsList(where); - }finally{ - trace_return("Where"); + { + if (true) + return content; } + throw new Error("Missing return statement in function"); } - final public void GroupBy() throws ParseException{ - trace_call("GroupBy"); - try{ - ClauseADQL<ColumnReference> groupBy = query.getGroupBy(); - ColumnReference colRef = null; - jj_consume_token(GROUP_BY); - colRef = ColumnRef(); - groupBy.add(colRef); - label_3: while(true){ - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case COMMA: - ; - break; - default: - jj_la1[14] = jj_gen; - break label_3; - } - jj_consume_token(COMMA); - colRef = ColumnRef(); - groupBy.add(colRef); + final public FromContent JoinedTable() throws ParseException{ + FromContent content; + content = SimpleTableRef(); + label_6: while(true){ + content = JoinSpecification(content); + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case NATURAL: + case INNER: + case RIGHT: + case LEFT: + case FULL: + case JOIN: + ; + break; + default: + jj_la1[29] = jj_gen; + break label_6; } - }finally{ - trace_return("GroupBy"); - } - } - - final public void Having() throws ParseException{ - trace_call("Having"); - try{ - ClauseConstraints having = query.getHaving(); - jj_consume_token(HAVING); - ConditionsList(having); - }finally{ - trace_return("Having"); } - } - - final public void OrderBy() throws ParseException{ - trace_call("OrderBy"); - try{ - ClauseADQL<ADQLOrder> orderBy = query.getOrderBy(); - ADQLOrder order = null; - jj_consume_token(ORDER_BY); - order = OrderItem(); - orderBy.add(order); - label_4: while(true){ - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case COMMA: - ; - break; - default: - jj_la1[15] = jj_gen; - break label_4; - } - jj_consume_token(COMMA); - order = OrderItem(); - orderBy.add(order); - } - }finally{ - trace_return("OrderBy"); + { + if (true) + return content; } + throw new Error("Missing return statement in function"); } - /* *************************** */ - /* COLUMN AND TABLE REFERENCES */ - /* *************************** */ - final public IdentifierItem Identifier() throws ParseException{ - trace_call("Identifier"); + final public ADQLJoin JoinSpecification(FromContent leftTable) throws ParseException{ + boolean natural = false; + JoinType type = JoinType.INNER; + ClauseConstraints condition = new ClauseConstraints("ON"); + ArrayList<ADQLColumn> lstColumns = new ArrayList<ADQLColumn>(); + IdentifierItem id; + FromContent rightTable; try{ - Token t; switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case REGULAR_IDENTIFIER: - t = jj_consume_token(REGULAR_IDENTIFIER); + case NATURAL: + jj_consume_token(NATURAL); + natural = true; + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case INNER: + case RIGHT: + case LEFT: + case FULL: + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case INNER: + jj_consume_token(INNER); + break; + case RIGHT: + case LEFT: + case FULL: + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case LEFT: + jj_consume_token(LEFT); + type = JoinType.OUTER_LEFT; + break; + case RIGHT: + jj_consume_token(RIGHT); + type = JoinType.OUTER_RIGHT; + break; + case FULL: + jj_consume_token(FULL); + type = JoinType.OUTER_FULL; + break; + default: + jj_la1[30] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case OUTER: + jj_consume_token(OUTER); + break; + default: + jj_la1[31] = jj_gen; + ; + } + break; + default: + jj_la1[32] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + break; + default: + jj_la1[33] = jj_gen; + ; + } + jj_consume_token(JOIN); + rightTable = TableRef(); { if (true) - return new IdentifierItem(t, false); + return queryFactory.createJoin(type, leftTable, rightTable); } break; - case DELIMITED_IDENTIFIER: - t = jj_consume_token(DELIMITED_IDENTIFIER); - { - if (true) - return new IdentifierItem(t, true); + case INNER: + case RIGHT: + case LEFT: + case FULL: + case JOIN: + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case INNER: + case RIGHT: + case LEFT: + case FULL: + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case INNER: + jj_consume_token(INNER); + break; + case RIGHT: + case LEFT: + case FULL: + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case LEFT: + jj_consume_token(LEFT); + type = JoinType.OUTER_LEFT; + break; + case RIGHT: + jj_consume_token(RIGHT); + type = JoinType.OUTER_RIGHT; + break; + case FULL: + jj_consume_token(FULL); + type = JoinType.OUTER_FULL; + break; + default: + jj_la1[34] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case OUTER: + jj_consume_token(OUTER); + break; + default: + jj_la1[35] = jj_gen; + ; + } + break; + default: + jj_la1[36] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + break; + default: + jj_la1[37] = jj_gen; + ; + } + jj_consume_token(JOIN); + rightTable = TableRef(); + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case ON: + jj_consume_token(ON); + ConditionsList(condition); + { + if (true) + return queryFactory.createJoin(type, leftTable, rightTable, condition); + } + break; + case USING: + jj_consume_token(USING); + jj_consume_token(LEFT_PAR); + id = Identifier(); + lstColumns.add(queryFactory.createColumn(id)); + label_7: while(true){ + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case COMMA: + ; + break; + default: + jj_la1[38] = jj_gen; + break label_7; + } + jj_consume_token(COMMA); + id = Identifier(); + lstColumns.add(queryFactory.createColumn(id)); + } + jj_consume_token(RIGHT_PAR); + { + if (true) + return queryFactory.createJoin(type, leftTable, rightTable, lstColumns); + } + break; + default: + jj_la1[39] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); } break; default: - jj_la1[16] = jj_gen; + jj_la1[40] = jj_gen; jj_consume_token(-1); throw new ParseException(); } - throw new Error("Missing return statement in function"); - }finally{ - trace_return("Identifier"); + }catch(Exception ex){ + { + if (true) + throw generateParseException(ex); + } } + throw new Error("Missing return statement in function"); } - /** - * Extracts the name of a table with its possible catalog and schema prefixes. - * - * @return A {@link IdentifierItems} which contains at most three items: catalogName, schemaName and tableName. - */ - final public IdentifierItems TableName() throws ParseException{ - trace_call("TableName"); - try{ - IdentifierItems identifiers = new IdentifierItems(true); - IdentifierItem id = null; - id = Identifier(); - identifiers.append(id); + /* ****** */ + /* STRING */ + /* ****** */ + final public String String() throws ParseException{ + Token t; + String str = ""; + label_8: while(true){ + t = jj_consume_token(STRING_LITERAL); + str += t.image.substring(1, t.image.length() - 1).replaceAll("''", "'"); switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case DOT: - jj_consume_token(DOT); - id = Identifier(); - identifiers.append(id); - break; - default: - jj_la1[17] = jj_gen; + case STRING_LITERAL: ; - } - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case DOT: - jj_consume_token(DOT); - id = Identifier(); - identifiers.append(id); break; default: - jj_la1[18] = jj_gen; - ; - } - { - if (true) - return identifiers; + jj_la1[41] = jj_gen; + break label_8; } - throw new Error("Missing return statement in function"); - }finally{ - trace_return("TableName"); } + { + if (true) + return str; + } + throw new Error("Missing return statement in function"); } - /** - * Extracts the name of a column with its possible catalog, schema and table prefixes. - * - * @return A {@link IdentifierItems} which contains at most four items: catalogName, schemaName, tableName and columnName. - */ - final public IdentifierItems ColumnName() throws ParseException{ - trace_call("ColumnName"); - try{ - IdentifierItem id; - IdentifierItems table = null, identifiers = new IdentifierItems(false); - id = Identifier(); - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case DOT: - jj_consume_token(DOT); - table = TableName(); - break; - default: - jj_la1[19] = jj_gen; - ; - } - identifiers.append(id); - if (table != null){ - for(int i = 0; i < table.size(); i++) - identifiers.append(table.get(i)); - } - { - if (true) - return identifiers; - } - throw new Error("Missing return statement in function"); - }finally{ - trace_return("ColumnName"); + /* ************* */ + /* NUMERIC TYPES */ + /* ************* */ + final public String UnsignedNumeric() throws ParseException{ + Token t; + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case SCIENTIFIC_NUMBER: + t = jj_consume_token(SCIENTIFIC_NUMBER); + break; + case UNSIGNED_FLOAT: + t = jj_consume_token(UNSIGNED_FLOAT); + break; + case UNSIGNED_INTEGER: + t = jj_consume_token(UNSIGNED_INTEGER); + break; + default: + jj_la1[42] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + { + if (true) + return t.image; } + throw new Error("Missing return statement in function"); } - final public ADQLColumn Column() throws ParseException{ - trace_call("Column"); - try{ - IdentifierItems identifiers; - identifiers = ColumnName(); - try{ - { - if (true) - return queryFactory.createColumn(identifiers); - } - }catch(Exception ex){ - { - if (true) - throw generateParseException(ex); + final public String UnsignedFloat() throws ParseException{ + Token t; + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case UNSIGNED_INTEGER: + t = jj_consume_token(UNSIGNED_INTEGER); + break; + case UNSIGNED_FLOAT: + t = jj_consume_token(UNSIGNED_FLOAT); + break; + default: + jj_la1[43] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + { + if (true) + return t.image; + } + throw new Error("Missing return statement in function"); + } + + final public String SignedInteger() throws ParseException{ + Token sign = null, number; + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case PLUS: + case MINUS: + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case PLUS: + sign = jj_consume_token(PLUS); + break; + case MINUS: + sign = jj_consume_token(MINUS); + break; + default: + jj_la1[44] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); } - } - throw new Error("Missing return statement in function"); - }finally{ - trace_return("Column"); + break; + default: + jj_la1[45] = jj_gen; + ; + } + number = jj_consume_token(UNSIGNED_INTEGER); + { + if (true) + return ((sign == null) ? "" : sign.image) + number.image; } + throw new Error("Missing return statement in function"); } - final public ColumnReference ColumnRef() throws ParseException{ - trace_call("ColumnRef"); + /* *********** */ + /* EXPRESSIONS */ + /* *********** */ + final public ADQLOperand NumericValueExpressionPrimary() throws ParseException{ + String expr; + ADQLColumn column; + ADQLOperand op; try{ - IdentifierItems identifiers = null; - Token ind = null; switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case SCIENTIFIC_NUMBER: + case UNSIGNED_FLOAT: + case UNSIGNED_INTEGER: + // unsigned_value_specification + expr = UnsignedNumeric(); + { + if (true) + return queryFactory.createNumericConstant(expr); + } + break; case DELIMITED_IDENTIFIER: case REGULAR_IDENTIFIER: - identifiers = ColumnName(); + column = Column(); + column.setExpectedType('N'); + { + if (true) + return column; + } break; - case UNSIGNED_INTEGER: - ind = jj_consume_token(UNSIGNED_INTEGER); + case AVG: + case MAX: + case MIN: + case SUM: + case COUNT: + op = SqlFunction(); + { + if (true) + return op; + } + break; + case LEFT_PAR: + jj_consume_token(LEFT_PAR); + op = NumericExpression(); + jj_consume_token(RIGHT_PAR); + { + if (true) + return queryFactory.createWrappedOperand(op); + } break; default: - jj_la1[20] = jj_gen; + jj_la1[46] = jj_gen; jj_consume_token(-1); throw new ParseException(); } - try{ - ColumnReference colRef = null; - if (identifiers != null) - colRef = queryFactory.createColRef(identifiers); - else - colRef = queryFactory.createColRef(Integer.parseInt(ind.image), new TextPosition(ind)); - { - if (true) - return colRef; - } - }catch(Exception ex){ - { - if (true) - throw generateParseException(ex); - } + }catch(Exception ex){ + { + if (true) + throw generateParseException(ex); } - throw new Error("Missing return statement in function"); - }finally{ - trace_return("ColumnRef"); } + throw new Error("Missing return statement in function"); } - final public ADQLOrder OrderItem() throws ParseException{ - trace_call("OrderItem"); + final public ADQLOperand StringValueExpressionPrimary() throws ParseException{ + String expr; + ADQLColumn column; + ADQLOperand op; try{ - IdentifierItems identifiers = null; - Token ind = null, desc = null; switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case STRING_LITERAL: + // string + expr = String(); + { + if (true) + return queryFactory.createStringConstant(expr); + } + break; case DELIMITED_IDENTIFIER: case REGULAR_IDENTIFIER: - identifiers = ColumnName(); + column = Column(); + column.setExpectedType('S'); + { + if (true) + return column; + } break; - case UNSIGNED_INTEGER: - ind = jj_consume_token(UNSIGNED_INTEGER); + case LEFT_PAR: + jj_consume_token(LEFT_PAR); + op = StringExpression(); + jj_consume_token(RIGHT_PAR); + { + if (true) + return queryFactory.createWrappedOperand(op); + } break; default: - jj_la1[21] = jj_gen; + jj_la1[47] = jj_gen; jj_consume_token(-1); throw new ParseException(); } - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case ASC: - case DESC: - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case ASC: - jj_consume_token(ASC); - break; - case DESC: - desc = jj_consume_token(DESC); - break; - default: - jj_la1[22] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - break; - default: - jj_la1[23] = jj_gen; - ; - } - try{ - ADQLOrder order = null; - if (identifiers != null) - order = queryFactory.createOrder(identifiers, desc != null); - else - order = queryFactory.createOrder(Integer.parseInt(ind.image), desc != null, new TextPosition(ind)); - { - if (true) - return order; - } - }catch(Exception ex){ - { - if (true) - throw generateParseException(ex); - } + }catch(Exception ex){ + { + if (true) + throw generateParseException(ex); } - throw new Error("Missing return statement in function"); - }finally{ - trace_return("OrderItem"); } + throw new Error("Missing return statement in function"); } - final public FromContent SimpleTableRef() throws ParseException{ - trace_call("SimpleTableRef"); + final public ADQLOperand ValueExpression() throws ParseException{ + ADQLOperand valueExpr = null; try{ - IdentifierItem alias = null; - IdentifierItems identifiers = null; - ADQLQuery subQuery = null; - FromContent content = null; - try{ + if (jj_2_4(2147483647)){ + valueExpr = NumericExpression(); + }else if (jj_2_5(2147483647)){ + valueExpr = StringExpression(); + }else if (jj_2_6(2147483647)){ + jj_consume_token(LEFT_PAR); + valueExpr = ValueExpression(); + jj_consume_token(RIGHT_PAR); + valueExpr = queryFactory.createWrappedOperand(valueExpr); + }else if (jj_2_7(2147483647)){ + valueExpr = UserDefinedFunction(); + }else{ switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case DELIMITED_IDENTIFIER: - case REGULAR_IDENTIFIER: - identifiers = TableName(); - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case AS: - case DELIMITED_IDENTIFIER: - case REGULAR_IDENTIFIER: - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case AS: - jj_consume_token(AS); - break; - default: - jj_la1[24] = jj_gen; - ; - } - alias = Identifier(); - break; - default: - jj_la1[25] = jj_gen; - ; - } - { - if (true) - return queryFactory.createTable(identifiers, alias); - } + case BOX: + case CENTROID: + case CIRCLE: + case POINT: + case POLYGON: + case REGION: + valueExpr = GeometryValueFunction(); break; default: - jj_la1[27] = jj_gen; - if (jj_2_2(2)){ - subQuery = SubQueryExpression(); - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case AS: - jj_consume_token(AS); - break; - default: - jj_la1[26] = jj_gen; - ; - } - alias = Identifier(); - { - if (true) - return queryFactory.createTable(subQuery, alias); - } + jj_la1[48] = jj_gen; + if (jj_2_8(2147483647)){ + valueExpr = Column(); + }else if (jj_2_9(2147483647)){ + valueExpr = StringFactor(); }else{ switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ case LEFT_PAR: - jj_consume_token(LEFT_PAR); - content = JoinedTable(); - jj_consume_token(RIGHT_PAR); - { - if (true) - return content; - } + case PLUS: + case MINUS: + case AVG: + case MAX: + case MIN: + case SUM: + case COUNT: + case CONTAINS: + case INTERSECTS: + case AREA: + case COORD1: + case COORD2: + case DISTANCE: + case ABS: + case CEILING: + case DEGREES: + case EXP: + case FLOOR: + case LOG: + case LOG10: + case MOD: + case PI: + case POWER: + case RADIANS: + case RAND: + case ROUND: + case SQRT: + case TRUNCATE: + case ACOS: + case ASIN: + case ATAN: + case ATAN2: + case COS: + case COT: + case SIN: + case TAN: + case DELIMITED_IDENTIFIER: + case REGULAR_IDENTIFIER: + case SCIENTIFIC_NUMBER: + case UNSIGNED_FLOAT: + case UNSIGNED_INTEGER: + valueExpr = Factor(); break; default: - jj_la1[28] = jj_gen; + jj_la1[49] = jj_gen; jj_consume_token(-1); throw new ParseException(); } } } - }catch(Exception ex){ - { - if (true) - throw generateParseException(ex); - } - } - throw new Error("Missing return statement in function"); - }finally{ - trace_return("SimpleTableRef"); - } - } - - final public FromContent TableRef() throws ParseException{ - trace_call("TableRef"); - try{ - FromContent content; - content = SimpleTableRef(); - label_5: while(true){ - if (jj_2_3(2)){ - ; - }else{ - break label_5; - } - content = JoinSpecification(content); } { if (true) - return content; + return valueExpr; + } + }catch(Exception ex){ + { + if (true) + throw generateParseException(ex); } - throw new Error("Missing return statement in function"); - }finally{ - trace_return("TableRef"); } + throw new Error("Missing return statement in function"); } - final public FromContent JoinedTable() throws ParseException{ - trace_call("JoinedTable"); - try{ - FromContent content; - content = SimpleTableRef(); - label_6: while(true){ - content = JoinSpecification(content); + final public ADQLOperand NumericExpression() throws ParseException{ + Token sign = null; + ADQLOperand leftOp, rightOp = null; + leftOp = NumericTerm(); + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case PLUS: + case MINUS: switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case NATURAL: - case INNER: - case RIGHT: - case LEFT: - case FULL: - case JOIN: - ; + case PLUS: + sign = jj_consume_token(PLUS); + break; + case MINUS: + sign = jj_consume_token(MINUS); break; default: - jj_la1[29] = jj_gen; - break label_6; + jj_la1[50] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + rightOp = NumericExpression(); + break; + default: + jj_la1[51] = jj_gen; + ; + } + if (sign == null){ + if (true) + return leftOp; + }else{ + try{ + { + if (true) + return queryFactory.createOperation(leftOp, OperationType.getOperator(sign.image), rightOp); + } + }catch(Exception ex){ + { + if (true) + throw generateParseException(ex); } } - { - if (true) - return content; - } - throw new Error("Missing return statement in function"); - }finally{ - trace_return("JoinedTable"); } + throw new Error("Missing return statement in function"); } - final public ADQLJoin JoinSpecification(FromContent leftTable) throws ParseException{ - trace_call("JoinSpecification"); - try{ - boolean natural = false; - JoinType type = JoinType.INNER; - ClauseConstraints condition = new ClauseConstraints("ON"); - ArrayList<ADQLColumn> lstColumns = new ArrayList<ADQLColumn>(); - IdentifierItem id; - FromContent rightTable; - try{ + final public ADQLOperand NumericTerm() throws ParseException{ + Token sign = null; + ADQLOperand leftOp, rightOp = null; + leftOp = Factor(); + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case ASTERISK: + case DIVIDE: switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case NATURAL: - jj_consume_token(NATURAL); - natural = true; - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case INNER: - case RIGHT: - case LEFT: - case FULL: - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case INNER: - jj_consume_token(INNER); - break; - case RIGHT: - case LEFT: - case FULL: - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case LEFT: - jj_consume_token(LEFT); - type = JoinType.OUTER_LEFT; - break; - case RIGHT: - jj_consume_token(RIGHT); - type = JoinType.OUTER_RIGHT; - break; - case FULL: - jj_consume_token(FULL); - type = JoinType.OUTER_FULL; - break; - default: - jj_la1[30] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case OUTER: - jj_consume_token(OUTER); - break; - default: - jj_la1[31] = jj_gen; - ; - } - break; - default: - jj_la1[32] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - break; - default: - jj_la1[33] = jj_gen; - ; - } - jj_consume_token(JOIN); - rightTable = TableRef(); - { - if (true) - return queryFactory.createJoin(type, leftTable, rightTable); - } + case ASTERISK: + sign = jj_consume_token(ASTERISK); break; - case INNER: - case RIGHT: - case LEFT: - case FULL: - case JOIN: - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case INNER: - case RIGHT: - case LEFT: - case FULL: - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case INNER: - jj_consume_token(INNER); - break; - case RIGHT: - case LEFT: - case FULL: - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case LEFT: - jj_consume_token(LEFT); - type = JoinType.OUTER_LEFT; - break; - case RIGHT: - jj_consume_token(RIGHT); - type = JoinType.OUTER_RIGHT; - break; - case FULL: - jj_consume_token(FULL); - type = JoinType.OUTER_FULL; - break; - default: - jj_la1[34] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case OUTER: - jj_consume_token(OUTER); - break; - default: - jj_la1[35] = jj_gen; - ; - } - break; - default: - jj_la1[36] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - break; - default: - jj_la1[37] = jj_gen; - ; - } - jj_consume_token(JOIN); - rightTable = TableRef(); - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case ON: - jj_consume_token(ON); - ConditionsList(condition); - { - if (true) - return queryFactory.createJoin(type, leftTable, rightTable, condition); - } - break; - case USING: - jj_consume_token(USING); - jj_consume_token(LEFT_PAR); - id = Identifier(); - lstColumns.add(queryFactory.createColumn(id)); - label_7: while(true){ - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case COMMA: - ; - break; - default: - jj_la1[38] = jj_gen; - break label_7; - } - jj_consume_token(COMMA); - id = Identifier(); - lstColumns.add(queryFactory.createColumn(id)); - } - jj_consume_token(RIGHT_PAR); - { - if (true) - return queryFactory.createJoin(type, leftTable, rightTable, lstColumns); - } - break; - default: - jj_la1[39] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } + case DIVIDE: + sign = jj_consume_token(DIVIDE); break; default: - jj_la1[40] = jj_gen; + jj_la1[52] = jj_gen; jj_consume_token(-1); throw new ParseException(); } + rightOp = NumericTerm(); + break; + default: + jj_la1[53] = jj_gen; + ; + } + if (sign == null){ + if (true) + return leftOp; + }else{ + try{ + { + if (true) + return queryFactory.createOperation(leftOp, OperationType.getOperator(sign.image), rightOp); + } }catch(Exception ex){ { if (true) throw generateParseException(ex); } } - throw new Error("Missing return statement in function"); - }finally{ - trace_return("JoinSpecification"); } + throw new Error("Missing return statement in function"); } - /* ****** */ - /* STRING */ - /* ****** */ - final public String String() throws ParseException{ - trace_call("String"); - try{ - Token t; - String str = ""; - label_8: while(true){ - t = jj_consume_token(STRING_LITERAL); - str += t.image; + final public ADQLOperand Factor() throws ParseException{ + boolean negative = false;; + ADQLOperand op; + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case PLUS: + case MINUS: switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case STRING_LITERAL: - ; + case PLUS: + jj_consume_token(PLUS); + break; + case MINUS: + jj_consume_token(MINUS); + negative = true; break; default: - jj_la1[41] = jj_gen; - break label_8; + jj_la1[54] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); } - } - { - if (true) - return (str != null) ? str.substring(1, str.length() - 1) : str; - } - throw new Error("Missing return statement in function"); - }finally{ - trace_return("String"); + break; + default: + jj_la1[55] = jj_gen; + ; } - } - - /* ************* */ - /* NUMERIC TYPES */ - /* ************* */ - final public String UnsignedNumeric() throws ParseException{ - trace_call("UnsignedNumeric"); - try{ - Token t; + if (jj_2_10(2)){ + op = NumericFunction(); + }else{ switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case LEFT_PAR: + case AVG: + case MAX: + case MIN: + case SUM: + case COUNT: + case DELIMITED_IDENTIFIER: + case REGULAR_IDENTIFIER: case SCIENTIFIC_NUMBER: - t = jj_consume_token(SCIENTIFIC_NUMBER); - break; case UNSIGNED_FLOAT: - t = jj_consume_token(UNSIGNED_FLOAT); - break; case UNSIGNED_INTEGER: - t = jj_consume_token(UNSIGNED_INTEGER); + op = NumericValueExpressionPrimary(); break; default: - jj_la1[42] = jj_gen; + jj_la1[56] = jj_gen; jj_consume_token(-1); throw new ParseException(); } - { - if (true) - return t.image; + } + if (negative){ + try{ + op = queryFactory.createNegativeOperand(op); + }catch(Exception ex){ + { + if (true) + throw generateParseException(ex); + } } - throw new Error("Missing return statement in function"); - }finally{ - trace_return("UnsignedNumeric"); } + + { + if (true) + return op; + } + throw new Error("Missing return statement in function"); } - final public String UnsignedFloat() throws ParseException{ - trace_call("UnsignedFloat"); - try{ - Token t; + final public ADQLOperand StringExpression() throws ParseException{ + ADQLOperand leftOp; + ADQLOperand rightOp = null; + leftOp = StringFactor(); + label_9: while(true){ switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case UNSIGNED_INTEGER: - t = jj_consume_token(UNSIGNED_INTEGER); - break; - case UNSIGNED_FLOAT: - t = jj_consume_token(UNSIGNED_FLOAT); + case CONCAT: + ; break; default: - jj_la1[43] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); + jj_la1[57] = jj_gen; + break label_9; } - { - if (true) - return t.image; + jj_consume_token(CONCAT); + rightOp = StringFactor(); + if (!(leftOp instanceof Concatenation)){ + try{ + ADQLOperand temp = leftOp; + leftOp = queryFactory.createConcatenation(); + ((Concatenation)leftOp).add(temp); + }catch(Exception ex){ + { + if (true) + throw generateParseException(ex); + } + } } - throw new Error("Missing return statement in function"); - }finally{ - trace_return("UnsignedFloat"); + ((Concatenation)leftOp).add(rightOp); } + { + if (true) + return leftOp; + } + throw new Error("Missing return statement in function"); } - final public String SignedInteger() throws ParseException{ - trace_call("SignedInteger"); - try{ - Token sign = null, number; - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case PLUS: - case MINUS: + final public ADQLOperand StringFactor() throws ParseException{ + ADQLOperand op; + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case COORDSYS: + op = ExtractCoordSys(); + break; + default: + jj_la1[58] = jj_gen; + if (jj_2_11(2)){ + op = UserDefinedFunction(); + ((UserDefinedFunction)op).setExpectedType('S'); + }else{ switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case PLUS: - sign = jj_consume_token(PLUS); - break; - case MINUS: - sign = jj_consume_token(MINUS); + case LEFT_PAR: + case STRING_LITERAL: + case DELIMITED_IDENTIFIER: + case REGULAR_IDENTIFIER: + op = StringValueExpressionPrimary(); break; default: - jj_la1[44] = jj_gen; + jj_la1[59] = jj_gen; jj_consume_token(-1); throw new ParseException(); } - break; - default: - jj_la1[45] = jj_gen; - ; - } - number = jj_consume_token(UNSIGNED_INTEGER); + } + } + { + if (true) + return op; + } + throw new Error("Missing return statement in function"); + } + + final public GeometryValue<GeometryFunction> GeometryExpression() throws ParseException{ + ADQLColumn col = null; + GeometryFunction gf = null; + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case DELIMITED_IDENTIFIER: + case REGULAR_IDENTIFIER: + col = Column(); + break; + case BOX: + case CENTROID: + case CIRCLE: + case POINT: + case POLYGON: + case REGION: + gf = GeometryValueFunction(); + break; + default: + jj_la1[60] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + if (col != null){ + col.setExpectedType('G'); { if (true) - return ((sign == null) ? "" : sign.image) + number.image; + return new GeometryValue<GeometryFunction>(col); } - throw new Error("Missing return statement in function"); - }finally{ - trace_return("SignedInteger"); + }else{ + if (true) + return new GeometryValue<GeometryFunction>(gf); } + throw new Error("Missing return statement in function"); } - /* *********** */ - /* EXPRESSIONS */ - /* *********** */ - final public ADQLOperand ValueExpressionPrimary() throws ParseException{ - trace_call("ValueExpressionPrimary"); + /* ********************************** */ + /* BOOLEAN EXPRESSIONS (WHERE clause) */ + /* ********************************** */ + final public ClauseConstraints ConditionsList(ClauseConstraints clause) throws ParseException{ + ADQLConstraint constraint = null; + Token op = null; + boolean notOp = false; try{ - String expr; - ADQLColumn column; - ADQLOperand op; - try{ + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case NOT: + jj_consume_token(NOT); + notOp = true; + break; + default: + jj_la1[61] = jj_gen; + ; + } + constraint = Constraint(); + if (notOp) + constraint = queryFactory.createNot(constraint); + notOp = false; + if (clause instanceof ADQLConstraint) + clause.add(constraint); + else + clause.add(constraint); + label_10: while(true){ switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case SCIENTIFIC_NUMBER: - case UNSIGNED_FLOAT: - case UNSIGNED_INTEGER: - // unsigned_value_specification - expr = UnsignedNumeric(); - { - if (true) - return queryFactory.createNumericConstant(expr); - } - break; - case STRING_LITERAL: - expr = String(); - { - if (true) - return queryFactory.createStringConstant(expr); - } - break; - case DELIMITED_IDENTIFIER: - case REGULAR_IDENTIFIER: - column = Column(); - { - if (true) - return column; - } + case AND: + case OR: + ; break; - case AVG: - case MAX: - case MIN: - case SUM: - case COUNT: - op = SqlFunction(); - { - if (true) - return op; - } + default: + jj_la1[62] = jj_gen; + break label_10; + } + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case AND: + op = jj_consume_token(AND); break; - case LEFT_PAR: - jj_consume_token(LEFT_PAR); - op = ValueExpression(); - jj_consume_token(RIGHT_PAR); - { - if (true) - return queryFactory.createWrappedOperand(op); - } + case OR: + op = jj_consume_token(OR); break; default: - jj_la1[46] = jj_gen; + jj_la1[63] = jj_gen; jj_consume_token(-1); throw new ParseException(); } - }catch(Exception ex){ - { - if (true) - throw generateParseException(ex); + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case NOT: + jj_consume_token(NOT); + notOp = true; + break; + default: + jj_la1[64] = jj_gen; + ; } + constraint = Constraint(); + if (notOp) + constraint = queryFactory.createNot(constraint); + notOp = false; + if (clause instanceof ADQLConstraint) + clause.add(op.image, constraint); + else + clause.add(op.image, constraint); } - throw new Error("Missing return statement in function"); - }finally{ - trace_return("ValueExpressionPrimary"); + }catch(Exception ex){ + { + if (true) + throw generateParseException(ex); + } + } + { + if (true) + return clause; } + throw new Error("Missing return statement in function"); } - final public ADQLOperand ValueExpression() throws ParseException{ - trace_call("ValueExpression"); - try{ - ADQLOperand valueExpr = null; + final public ADQLConstraint Constraint() throws ParseException{ + ADQLConstraint constraint = null; + if (jj_2_12(2147483647)){ + constraint = Predicate(); + }else{ switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case BOX: - case CENTROID: - case CIRCLE: - case POINT: - case POLYGON: - case REGION: - valueExpr = GeometryValueFunction(); - break; - default: - jj_la1[47] = jj_gen; - if (jj_2_4(2147483647)){ - valueExpr = NumericExpression(); - }else if (jj_2_5(2147483647)){ - valueExpr = StringExpression(); - }else if (jj_2_6(2147483647)){ - valueExpr = StringExpression(); - }else{ + case LEFT_PAR: + jj_consume_token(LEFT_PAR); + try{ + constraint = queryFactory.createGroupOfConstraints(); + }catch(Exception ex){ + { + if (true) + throw generateParseException(ex); + } + } + ConditionsList((ConstraintsGroup)constraint); + jj_consume_token(RIGHT_PAR); + break; + default: + jj_la1[65] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + } + { + if (true) + return constraint; + } + throw new Error("Missing return statement in function"); + } + + final public ADQLConstraint Predicate() throws ParseException{ + ADQLQuery q = null; + ADQLColumn column = null; + ADQLOperand strExpr1 = null, strExpr2 = null; + ADQLOperand op; + Token notToken = null; + ADQLConstraint constraint = null; + try{ + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case EXISTS: + jj_consume_token(EXISTS); + q = SubQueryExpression(); + { + if (true) + return queryFactory.createExists(q); + } + break; + default: + jj_la1[70] = jj_gen; + if (jj_2_14(2147483647)){ + column = Column(); + jj_consume_token(IS); + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case NOT: + notToken = jj_consume_token(NOT); + break; + default: + jj_la1[66] = jj_gen; + ; + } + jj_consume_token(NULL); + { + if (true) + return queryFactory.createIsNull((notToken != null), column); + } + }else if (jj_2_15(2147483647)){ + strExpr1 = StringExpression(); + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case NOT: + notToken = jj_consume_token(NOT); + break; + default: + jj_la1[67] = jj_gen; + ; + } + jj_consume_token(LIKE); + strExpr2 = StringExpression(); + { + if (true) + return queryFactory.createComparison(strExpr1, (notToken == null) ? ComparisonOperator.LIKE : ComparisonOperator.NOTLIKE, strExpr2); + } + }else{ switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ case LEFT_PAR: case PLUS: @@ -1686,11 +2071,18 @@ public class ADQLParser implements ADQLParserConstants { case MIN: case SUM: case COUNT: + case BOX: + case CENTROID: + case CIRCLE: + case POINT: + case POLYGON: + case REGION: case CONTAINS: case INTERSECTS: case AREA: case COORD1: case COORD2: + case COORDSYS: case DISTANCE: case ABS: case CEILING: @@ -1721,1548 +2113,866 @@ public class ADQLParser implements ADQLParserConstants { case SCIENTIFIC_NUMBER: case UNSIGNED_FLOAT: case UNSIGNED_INTEGER: - valueExpr = NumericExpression(); + op = ValueExpression(); + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case EQUAL: + case NOT_EQUAL: + case LESS_THAN: + case LESS_EQUAL_THAN: + case GREATER_THAN: + case GREATER_EQUAL_THAN: + constraint = ComparisonEnd(op); + break; + default: + jj_la1[68] = jj_gen; + if (jj_2_13(2)){ + constraint = BetweenEnd(op); + }else{ + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case NOT: + case IN: + constraint = InEnd(op); + break; + default: + jj_la1[69] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + } + } break; default: - jj_la1[48] = jj_gen; + jj_la1[71] = jj_gen; jj_consume_token(-1); throw new ParseException(); } } } + }catch(Exception ex){ { if (true) - return valueExpr; + throw generateParseException(ex); } - throw new Error("Missing return statement in function"); - }finally{ - trace_return("ValueExpression"); } + { + if (true) + return constraint; + } + throw new Error("Missing return statement in function"); } - final public ADQLOperand NumericExpression() throws ParseException{ - trace_call("NumericExpression"); + final public Comparison ComparisonEnd(ADQLOperand leftOp) throws ParseException{ + Token comp; + ADQLOperand rightOp; + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case EQUAL: + comp = jj_consume_token(EQUAL); + break; + case NOT_EQUAL: + comp = jj_consume_token(NOT_EQUAL); + break; + case LESS_THAN: + comp = jj_consume_token(LESS_THAN); + break; + case LESS_EQUAL_THAN: + comp = jj_consume_token(LESS_EQUAL_THAN); + break; + case GREATER_THAN: + comp = jj_consume_token(GREATER_THAN); + break; + case GREATER_EQUAL_THAN: + comp = jj_consume_token(GREATER_EQUAL_THAN); + break; + default: + jj_la1[72] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + rightOp = ValueExpression(); + try{ + { + if (true) + return queryFactory.createComparison(leftOp, ComparisonOperator.getOperator(comp.image), rightOp); + } + }catch(Exception ex){ + { + if (true) + throw generateParseException(ex); + } + } + throw new Error("Missing return statement in function"); + } + + final public Between BetweenEnd(ADQLOperand leftOp) throws ParseException{ + Token notToken = null; + ADQLOperand min, max; + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case NOT: + notToken = jj_consume_token(NOT); + break; + default: + jj_la1[73] = jj_gen; + ; + } + jj_consume_token(BETWEEN); + min = ValueExpression(); + jj_consume_token(AND); + max = ValueExpression(); try{ - Token sign = null; - ADQLOperand leftOp, rightOp = null; - leftOp = NumericTerm(); + { + if (true) + return queryFactory.createBetween((notToken != null), leftOp, min, max); + } + }catch(Exception ex){ + { + if (true) + throw generateParseException(ex); + } + } + throw new Error("Missing return statement in function"); + } + + final public In InEnd(ADQLOperand leftOp) throws ParseException{ + Token not = null; + ADQLQuery q = null; + ADQLOperand item; + Vector<ADQLOperand> items = new Vector<ADQLOperand>(); + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case NOT: + not = jj_consume_token(NOT); + break; + default: + jj_la1[74] = jj_gen; + ; + } + jj_consume_token(IN); + if (jj_2_16(2)){ + q = SubQueryExpression(); + }else{ switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case PLUS: - case MINUS: - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case PLUS: - sign = jj_consume_token(PLUS); - break; - case MINUS: - sign = jj_consume_token(MINUS); - break; - default: - jj_la1[49] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); + case LEFT_PAR: + jj_consume_token(LEFT_PAR); + item = ValueExpression(); + items.add(item); + label_11: while(true){ + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case COMMA: + ; + break; + default: + jj_la1[75] = jj_gen; + break label_11; + } + jj_consume_token(COMMA); + item = ValueExpression(); + items.add(item); } - rightOp = NumericExpression(); + jj_consume_token(RIGHT_PAR); break; default: - jj_la1[50] = jj_gen; - ; + jj_la1[76] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); } - if (sign == null){ + } + try{ + if (q != null){ if (true) - return leftOp; + return queryFactory.createIn(leftOp, q, not != null); }else{ - try{ - { - if (true) - return queryFactory.createOperation(leftOp, OperationType.getOperator(sign.image), rightOp); - } - }catch(Exception ex){ - { - if (true) - throw generateParseException(ex); - } + ADQLOperand[] list = new ADQLOperand[items.size()]; + int i = 0; + for(ADQLOperand op : items) + list[i++] = op; + { + if (true) + return queryFactory.createIn(leftOp, list, not != null); } } - throw new Error("Missing return statement in function"); - }finally{ - trace_return("NumericExpression"); + }catch(Exception ex){ + { + if (true) + throw generateParseException(ex); + } } + throw new Error("Missing return statement in function"); } - final public ADQLOperand NumericTerm() throws ParseException{ - trace_call("NumericTerm"); + /* ************* */ + /* SQL FUNCTIONS */ + /* ************* */ + final public SQLFunction SqlFunction() throws ParseException{ + Token fct, all = null, distinct = null; + ADQLOperand op = null; + SQLFunction funct = null; try{ - Token sign = null; - ADQLOperand leftOp, rightOp = null; - leftOp = Factor(); switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case ASTERISK: - case DIVIDE: + case COUNT: + jj_consume_token(COUNT); + jj_consume_token(LEFT_PAR); + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case QUANTIFIER: + distinct = jj_consume_token(QUANTIFIER); + break; + default: + jj_la1[77] = jj_gen; + ; + } switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ case ASTERISK: - sign = jj_consume_token(ASTERISK); + all = jj_consume_token(ASTERISK); break; - case DIVIDE: - sign = jj_consume_token(DIVIDE); + case LEFT_PAR: + case PLUS: + case MINUS: + case AVG: + case MAX: + case MIN: + case SUM: + case COUNT: + case BOX: + case CENTROID: + case CIRCLE: + case POINT: + case POLYGON: + case REGION: + case CONTAINS: + case INTERSECTS: + case AREA: + case COORD1: + case COORD2: + case COORDSYS: + case DISTANCE: + case ABS: + case CEILING: + case DEGREES: + case EXP: + case FLOOR: + case LOG: + case LOG10: + case MOD: + case PI: + case POWER: + case RADIANS: + case RAND: + case ROUND: + case SQRT: + case TRUNCATE: + case ACOS: + case ASIN: + case ATAN: + case ATAN2: + case COS: + case COT: + case SIN: + case TAN: + case STRING_LITERAL: + case DELIMITED_IDENTIFIER: + case REGULAR_IDENTIFIER: + case SCIENTIFIC_NUMBER: + case UNSIGNED_FLOAT: + case UNSIGNED_INTEGER: + op = ValueExpression(); break; default: - jj_la1[51] = jj_gen; + jj_la1[78] = jj_gen; jj_consume_token(-1); throw new ParseException(); } - rightOp = NumericTerm(); + jj_consume_token(RIGHT_PAR); + funct = queryFactory.createSQLFunction((all != null) ? SQLFunctionType.COUNT_ALL : SQLFunctionType.COUNT, op, distinct != null && distinct.image.equalsIgnoreCase("distinct")); break; - default: - jj_la1[52] = jj_gen; - ; - } - if (sign == null){ - if (true) - return leftOp; - }else{ - try{ - { - if (true) - return queryFactory.createOperation(leftOp, OperationType.getOperator(sign.image), rightOp); - } - }catch(Exception ex){ - { - if (true) - throw generateParseException(ex); - } - } - } - throw new Error("Missing return statement in function"); - }finally{ - trace_return("NumericTerm"); - } - } - - final public ADQLOperand Factor() throws ParseException{ - trace_call("Factor"); - try{ - boolean negative = false;; - ADQLOperand op; - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case PLUS: - case MINUS: + case AVG: + case MAX: + case MIN: + case SUM: switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case PLUS: - jj_consume_token(PLUS); + case AVG: + fct = jj_consume_token(AVG); break; - case MINUS: - jj_consume_token(MINUS); - negative = true; + case MAX: + fct = jj_consume_token(MAX); + break; + case MIN: + fct = jj_consume_token(MIN); + break; + case SUM: + fct = jj_consume_token(SUM); break; default: - jj_la1[53] = jj_gen; + jj_la1[79] = jj_gen; jj_consume_token(-1); throw new ParseException(); } + jj_consume_token(LEFT_PAR); + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case QUANTIFIER: + distinct = jj_consume_token(QUANTIFIER); + break; + default: + jj_la1[80] = jj_gen; + ; + } + op = ValueExpression(); + jj_consume_token(RIGHT_PAR); + funct = queryFactory.createSQLFunction(SQLFunctionType.valueOf(fct.image.toUpperCase()), op, distinct != null && distinct.image.equalsIgnoreCase("distinct")); break; default: - jj_la1[54] = jj_gen; - ; - } - if (jj_2_7(2)){ - op = NumericFunction(); - }else{ - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case LEFT_PAR: - case AVG: - case MAX: - case MIN: - case SUM: - case COUNT: - case STRING_LITERAL: - case DELIMITED_IDENTIFIER: - case REGULAR_IDENTIFIER: - case SCIENTIFIC_NUMBER: - case UNSIGNED_FLOAT: - case UNSIGNED_INTEGER: - op = ValueExpressionPrimary(); - break; - default: - jj_la1[55] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - } - if (negative){ - try{ - op = queryFactory.createNegativeOperand(op); - }catch(Exception ex){ - { - if (true) - throw generateParseException(ex); - } - } + jj_la1[81] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); } - + }catch(Exception ex){ { if (true) - return op; + throw generateParseException(ex); } - throw new Error("Missing return statement in function"); - }finally{ - trace_return("Factor"); } + { + if (true) + return funct; + } + throw new Error("Missing return statement in function"); } - final public ADQLOperand StringExpression() throws ParseException{ - trace_call("StringExpression"); - try{ - ADQLOperand leftOp; - ADQLOperand rightOp = null; - leftOp = StringFactor(); - label_9: while(true){ - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case CONCAT: - ; - break; - default: - jj_la1[56] = jj_gen; - break label_9; - } - jj_consume_token(CONCAT); - rightOp = StringFactor(); - if (!(leftOp instanceof Concatenation)){ - try{ - ADQLOperand temp = leftOp; - leftOp = queryFactory.createConcatenation(); - ((Concatenation)leftOp).add(temp); - }catch(Exception ex){ - { - if (true) - throw generateParseException(ex); - } - } - } - ((Concatenation)leftOp).add(rightOp); - } - { - if (true) - return leftOp; - } - throw new Error("Missing return statement in function"); - }finally{ - trace_return("StringExpression"); + /* ************** */ + /* ADQL FUNCTIONS */ + /* ************** */ + final public ADQLOperand[] Coordinates() throws ParseException{ + ADQLOperand[] ops = new ADQLOperand[2]; + ops[0] = NumericExpression(); + jj_consume_token(COMMA); + ops[1] = NumericExpression(); + { + if (true) + return ops; } + throw new Error("Missing return statement in function"); } - final public ADQLOperand StringFactor() throws ParseException{ - trace_call("StringFactor"); + final public GeometryFunction GeometryFunction() throws ParseException{ + Token t = null; + GeometryValue<GeometryFunction> gvf1, gvf2; + GeometryValue<PointFunction> gvp1, gvp2; + GeometryFunction gf = null; + PointFunction p1 = null, p2 = null; + ADQLColumn col1 = null, col2 = null; try{ - ADQLOperand op; switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case COORDSYS: - op = ExtractCoordSys(); + case CONTAINS: + case INTERSECTS: + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case CONTAINS: + t = jj_consume_token(CONTAINS); + break; + case INTERSECTS: + t = jj_consume_token(INTERSECTS); + break; + default: + jj_la1[82] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + jj_consume_token(LEFT_PAR); + gvf1 = GeometryExpression(); + jj_consume_token(COMMA); + gvf2 = GeometryExpression(); + jj_consume_token(RIGHT_PAR); + if (t.image.equalsIgnoreCase("contains")) + gf = queryFactory.createContains(gvf1, gvf2); + else + gf = queryFactory.createIntersects(gvf1, gvf2); break; - default: - jj_la1[57] = jj_gen; - if (jj_2_8(2)){ - op = UserDefinedFunction(); - }else{ - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case LEFT_PAR: - case AVG: - case MAX: - case MIN: - case SUM: - case COUNT: - case STRING_LITERAL: - case DELIMITED_IDENTIFIER: - case REGULAR_IDENTIFIER: - case SCIENTIFIC_NUMBER: - case UNSIGNED_FLOAT: - case UNSIGNED_INTEGER: - op = ValueExpressionPrimary(); - break; - default: - jj_la1[58] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - } - } - { - if (true) - return op; - } - throw new Error("Missing return statement in function"); - }finally{ - trace_return("StringFactor"); - } - } - - final public GeometryValue<GeometryFunction> GeometryExpression() throws ParseException{ - trace_call("GeometryExpression"); - try{ - ADQLColumn col = null; - GeometryFunction gf = null; - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case DELIMITED_IDENTIFIER: - case REGULAR_IDENTIFIER: - col = Column(); + case AREA: + jj_consume_token(AREA); + jj_consume_token(LEFT_PAR); + gvf1 = GeometryExpression(); + jj_consume_token(RIGHT_PAR); + gf = queryFactory.createArea(gvf1); break; - case BOX: - case CENTROID: - case CIRCLE: - case POINT: - case POLYGON: - case REGION: - gf = GeometryValueFunction(); + case COORD1: + jj_consume_token(COORD1); + jj_consume_token(LEFT_PAR); + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case POINT: + p1 = Point(); + gf = queryFactory.createCoord1(p1); + break; + case DELIMITED_IDENTIFIER: + case REGULAR_IDENTIFIER: + col1 = Column(); + col1.setExpectedType('G'); + gf = queryFactory.createCoord1(col1); + break; + default: + jj_la1[83] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + jj_consume_token(RIGHT_PAR); break; - default: - jj_la1[59] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - if (col != null){ - if (true) - return new GeometryValue<GeometryFunction>(col); - }else{ - if (true) - return new GeometryValue<GeometryFunction>(gf); - } - throw new Error("Missing return statement in function"); - }finally{ - trace_return("GeometryExpression"); - } - } - - /* ********************************** */ - /* BOOLEAN EXPRESSIONS (WHERE clause) */ - /* ********************************** */ - final public ClauseConstraints ConditionsList(ClauseConstraints clause) throws ParseException{ - trace_call("ConditionsList"); - try{ - ADQLConstraint constraint = null; - Token op = null; - boolean notOp = false; - try{ - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case NOT: - jj_consume_token(NOT); - notOp = true; - break; - default: - jj_la1[60] = jj_gen; - ; - } - constraint = Constraint(); - if (notOp) - constraint = queryFactory.createNot(constraint); - notOp = false; - if (clause instanceof ADQLConstraint) - clause.add(constraint); - else - clause.add(constraint); - label_10: while(true){ + case COORD2: + jj_consume_token(COORD2); + jj_consume_token(LEFT_PAR); switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case AND: - case OR: - ; + case POINT: + p1 = Point(); + gf = queryFactory.createCoord2(p1); + break; + case DELIMITED_IDENTIFIER: + case REGULAR_IDENTIFIER: + col1 = Column(); + col1.setExpectedType('G'); + gf = queryFactory.createCoord2(col1); break; default: - jj_la1[61] = jj_gen; - break label_10; + jj_la1[84] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); } + jj_consume_token(RIGHT_PAR); + break; + case DISTANCE: + jj_consume_token(DISTANCE); + jj_consume_token(LEFT_PAR); switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case AND: - op = jj_consume_token(AND); + case POINT: + p1 = Point(); break; - case OR: - op = jj_consume_token(OR); + case DELIMITED_IDENTIFIER: + case REGULAR_IDENTIFIER: + col1 = Column(); break; default: - jj_la1[62] = jj_gen; + jj_la1[85] = jj_gen; jj_consume_token(-1); throw new ParseException(); } + if (p1 != null) + gvp1 = new GeometryValue<PointFunction>(p1); + else{ + col1.setExpectedType('G'); + gvp1 = new GeometryValue<PointFunction>(col1); + } + jj_consume_token(COMMA); switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case NOT: - jj_consume_token(NOT); - notOp = true; + case POINT: + p2 = Point(); + break; + case DELIMITED_IDENTIFIER: + case REGULAR_IDENTIFIER: + col2 = Column(); break; default: - jj_la1[63] = jj_gen; - ; + jj_la1[86] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); } - constraint = Constraint(); - if (notOp) - constraint = queryFactory.createNot(constraint); - notOp = false; - if (clause instanceof ADQLConstraint) - clause.add(op.image, constraint); - else - clause.add(op.image, constraint); - } - }catch(Exception ex){ - { - if (true) - throw generateParseException(ex); - } + if (p2 != null) + gvp2 = new GeometryValue<PointFunction>(p2); + else{ + col2.setExpectedType('G'); + gvp2 = new GeometryValue<PointFunction>(col2); + } + jj_consume_token(RIGHT_PAR); + gf = queryFactory.createDistance(gvp1, gvp2); + break; + default: + jj_la1[87] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); } + }catch(Exception ex){ { if (true) - return clause; + throw generateParseException(ex); } - throw new Error("Missing return statement in function"); - }finally{ - trace_return("ConditionsList"); } - } - - final public ADQLConstraint Constraint() throws ParseException{ - trace_call("Constraint"); - try{ - ADQLConstraint constraint = null; - if (jj_2_9(2147483647)){ - constraint = Predicate(); - }else{ - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case LEFT_PAR: - jj_consume_token(LEFT_PAR); - try{ - constraint = queryFactory.createGroupOfConstraints(); - }catch(Exception ex){ - { - if (true) - throw generateParseException(ex); - } - } - ConditionsList((ConstraintsGroup)constraint); - jj_consume_token(RIGHT_PAR); - break; - default: - jj_la1[64] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - } - { - if (true) - return constraint; - } - throw new Error("Missing return statement in function"); - }finally{ - trace_return("Constraint"); + { + if (true) + return gf; } + throw new Error("Missing return statement in function"); } - final public ADQLConstraint Predicate() throws ParseException{ - trace_call("Predicate"); - try{ - ADQLQuery q = null; - ADQLColumn column = null; - ADQLOperand strExpr1 = null, strExpr2 = null; - ADQLOperand op; - Token notToken = null; - ADQLConstraint constraint = null; - try{ - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case EXISTS: - jj_consume_token(EXISTS); - q = SubQueryExpression(); - { - if (true) - return queryFactory.createExists(q); - } - break; - default: - jj_la1[69] = jj_gen; - if (jj_2_11(2147483647)){ - column = Column(); - jj_consume_token(IS); - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case NOT: - notToken = jj_consume_token(NOT); - break; - default: - jj_la1[65] = jj_gen; - ; - } - jj_consume_token(NULL); - { - if (true) - return queryFactory.createIsNull((notToken != null), column); - } - }else if (jj_2_12(2147483647)){ - strExpr1 = StringExpression(); - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case NOT: - notToken = jj_consume_token(NOT); - break; - default: - jj_la1[66] = jj_gen; - ; - } - jj_consume_token(LIKE); - strExpr2 = StringExpression(); - { - if (true) - return queryFactory.createComparison(strExpr1, (notToken == null) ? ComparisonOperator.LIKE : ComparisonOperator.NOTLIKE, strExpr2); - } - }else{ - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case LEFT_PAR: - case PLUS: - case MINUS: - case AVG: - case MAX: - case MIN: - case SUM: - case COUNT: - case BOX: - case CENTROID: - case CIRCLE: - case POINT: - case POLYGON: - case REGION: - case CONTAINS: - case INTERSECTS: - case AREA: - case COORD1: - case COORD2: - case COORDSYS: - case DISTANCE: - case ABS: - case CEILING: - case DEGREES: - case EXP: - case FLOOR: - case LOG: - case LOG10: - case MOD: - case PI: - case POWER: - case RADIANS: - case RAND: - case ROUND: - case SQRT: - case TRUNCATE: - case ACOS: - case ASIN: - case ATAN: - case ATAN2: - case COS: - case COT: - case SIN: - case TAN: - case STRING_LITERAL: - case DELIMITED_IDENTIFIER: - case REGULAR_IDENTIFIER: - case SCIENTIFIC_NUMBER: - case UNSIGNED_FLOAT: - case UNSIGNED_INTEGER: - op = ValueExpression(); - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case EQUAL: - case NOT_EQUAL: - case LESS_THAN: - case LESS_EQUAL_THAN: - case GREATER_THAN: - case GREATER_EQUAL_THAN: - constraint = ComparisonEnd(op); - break; - default: - jj_la1[67] = jj_gen; - if (jj_2_10(2)){ - constraint = BetweenEnd(op); - }else{ - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case NOT: - case IN: - constraint = InEnd(op); - break; - default: - jj_la1[68] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - } - } - break; - default: - jj_la1[70] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - } - } - }catch(Exception ex){ - { - if (true) - throw generateParseException(ex); - } - } - { - if (true) - return constraint; - } - throw new Error("Missing return statement in function"); - }finally{ - trace_return("Predicate"); + final public ADQLOperand CoordinateSystem() throws ParseException{ + ADQLOperand coordSys = null; + coordSys = StringExpression(); + { + if (true) + return coordSys; } + throw new Error("Missing return statement in function"); } - final public Comparison ComparisonEnd(ADQLOperand leftOp) throws ParseException{ - trace_call("ComparisonEnd"); + final public GeometryFunction GeometryValueFunction() throws ParseException{ + ADQLOperand coordSys; + ADQLOperand width, height; + ADQLOperand[] coords, tmp; + Vector<ADQLOperand> vCoords; + ADQLOperand op = null; + GeometryValue<GeometryFunction> gvf = null; + GeometryFunction gf = null; try{ - Token comp; - ADQLOperand rightOp; switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case EQUAL: - comp = jj_consume_token(EQUAL); - break; - case NOT_EQUAL: - comp = jj_consume_token(NOT_EQUAL); - break; - case LESS_THAN: - comp = jj_consume_token(LESS_THAN); - break; - case LESS_EQUAL_THAN: - comp = jj_consume_token(LESS_EQUAL_THAN); - break; - case GREATER_THAN: - comp = jj_consume_token(GREATER_THAN); - break; - case GREATER_EQUAL_THAN: - comp = jj_consume_token(GREATER_EQUAL_THAN); + case BOX: + jj_consume_token(BOX); + jj_consume_token(LEFT_PAR); + coordSys = CoordinateSystem(); + jj_consume_token(COMMA); + coords = Coordinates(); + jj_consume_token(COMMA); + width = NumericExpression(); + jj_consume_token(COMMA); + height = NumericExpression(); + jj_consume_token(RIGHT_PAR); + gf = queryFactory.createBox(coordSys, coords[0], coords[1], width, height); break; - default: - jj_la1[71] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - rightOp = ValueExpression(); - try{ - { - if (true) - return queryFactory.createComparison(leftOp, ComparisonOperator.getOperator(comp.image), rightOp); - } - }catch(Exception ex){ - { - if (true) - throw generateParseException(ex); - } - } - throw new Error("Missing return statement in function"); - }finally{ - trace_return("ComparisonEnd"); - } - } - - final public Between BetweenEnd(ADQLOperand leftOp) throws ParseException{ - trace_call("BetweenEnd"); - try{ - Token notToken = null; - ADQLOperand min, max; - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case NOT: - notToken = jj_consume_token(NOT); - break; - default: - jj_la1[72] = jj_gen; - ; - } - jj_consume_token(BETWEEN); - min = ValueExpression(); - jj_consume_token(AND); - max = ValueExpression(); - try{ - { - if (true) - return queryFactory.createBetween((notToken != null), leftOp, min, max); - } - }catch(Exception ex){ - { - if (true) - throw generateParseException(ex); - } - } - throw new Error("Missing return statement in function"); - }finally{ - trace_return("BetweenEnd"); - } - } - - final public In InEnd(ADQLOperand leftOp) throws ParseException{ - trace_call("InEnd"); - try{ - Token not = null; - ADQLQuery q = null; - ADQLOperand item; - Vector<ADQLOperand> items = new Vector<ADQLOperand>(); - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case NOT: - not = jj_consume_token(NOT); - break; - default: - jj_la1[73] = jj_gen; - ; - } - jj_consume_token(IN); - if (jj_2_13(2)){ - q = SubQueryExpression(); - }else{ - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case LEFT_PAR: - jj_consume_token(LEFT_PAR); - item = ValueExpression(); - items.add(item); - label_11: while(true){ - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case COMMA: - ; - break; - default: - jj_la1[74] = jj_gen; - break label_11; - } - jj_consume_token(COMMA); - item = ValueExpression(); - items.add(item); - } - jj_consume_token(RIGHT_PAR); - break; - default: - jj_la1[75] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - } - try{ - if (q != null){ - if (true) - return queryFactory.createIn(leftOp, q, not != null); - }else{ - ADQLOperand[] list = new ADQLOperand[items.size()]; - int i = 0; - for(ADQLOperand op : items) - list[i++] = op; - { - if (true) - return queryFactory.createIn(leftOp, list, not != null); - } - } - }catch(Exception ex){ - { - if (true) - throw generateParseException(ex); - } - } - throw new Error("Missing return statement in function"); - }finally{ - trace_return("InEnd"); - } - } - - /* ************* */ - /* SQL FUNCTIONS */ - /* ************* */ - final public SQLFunction SqlFunction() throws ParseException{ - trace_call("SqlFunction"); - try{ - Token fct, all = null, distinct = null; - ADQLOperand op = null; - SQLFunction funct = null; - try{ - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case COUNT: - jj_consume_token(COUNT); - jj_consume_token(LEFT_PAR); - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case QUANTIFIER: - distinct = jj_consume_token(QUANTIFIER); - break; - default: - jj_la1[76] = jj_gen; - ; - } - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case ASTERISK: - all = jj_consume_token(ASTERISK); - break; - case LEFT_PAR: - case PLUS: - case MINUS: - case AVG: - case MAX: - case MIN: - case SUM: - case COUNT: - case BOX: - case CENTROID: - case CIRCLE: - case POINT: - case POLYGON: - case REGION: - case CONTAINS: - case INTERSECTS: - case AREA: - case COORD1: - case COORD2: - case COORDSYS: - case DISTANCE: - case ABS: - case CEILING: - case DEGREES: - case EXP: - case FLOOR: - case LOG: - case LOG10: - case MOD: - case PI: - case POWER: - case RADIANS: - case RAND: - case ROUND: - case SQRT: - case TRUNCATE: - case ACOS: - case ASIN: - case ATAN: - case ATAN2: - case COS: - case COT: - case SIN: - case TAN: - case STRING_LITERAL: - case DELIMITED_IDENTIFIER: - case REGULAR_IDENTIFIER: - case SCIENTIFIC_NUMBER: - case UNSIGNED_FLOAT: - case UNSIGNED_INTEGER: - op = ValueExpression(); - break; - default: - jj_la1[77] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - jj_consume_token(RIGHT_PAR); - funct = queryFactory.createSQLFunction((all != null) ? SQLFunctionType.COUNT_ALL : SQLFunctionType.COUNT, op, distinct != null && distinct.image.equalsIgnoreCase("distinct")); - break; - case AVG: - case MAX: - case MIN: - case SUM: - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case AVG: - fct = jj_consume_token(AVG); - break; - case MAX: - fct = jj_consume_token(MAX); - break; - case MIN: - fct = jj_consume_token(MIN); - break; - case SUM: - fct = jj_consume_token(SUM); - break; - default: - jj_la1[78] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - jj_consume_token(LEFT_PAR); - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case QUANTIFIER: - distinct = jj_consume_token(QUANTIFIER); - break; - default: - jj_la1[79] = jj_gen; - ; - } - op = ValueExpression(); - jj_consume_token(RIGHT_PAR); - funct = queryFactory.createSQLFunction(SQLFunctionType.valueOf(fct.image.toUpperCase()), op, distinct != null && distinct.image.equalsIgnoreCase("distinct")); - break; - default: - jj_la1[80] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - }catch(Exception ex){ - { - if (true) - throw generateParseException(ex); - } - } - { - if (true) - return funct; - } - throw new Error("Missing return statement in function"); - }finally{ - trace_return("SqlFunction"); - } - } - - /* ************** */ - /* ADQL FUNCTIONS */ - /* ************** */ - final public ADQLOperand[] Coordinates() throws ParseException{ - trace_call("Coordinates"); - try{ - ADQLOperand[] ops = new ADQLOperand[2]; - ops[0] = NumericExpression(); - jj_consume_token(COMMA); - ops[1] = NumericExpression(); - { - if (true) - return ops; - } - throw new Error("Missing return statement in function"); - }finally{ - trace_return("Coordinates"); - } - } - - final public GeometryFunction GeometryFunction() throws ParseException{ - trace_call("GeometryFunction"); - try{ - Token t = null; - GeometryValue<GeometryFunction> gvf1, gvf2; - GeometryValue<PointFunction> gvp1, gvp2; - GeometryFunction gf = null; - PointFunction p1 = null, p2 = null; - ADQLColumn col1 = null, col2 = null; - try{ - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case CONTAINS: - case INTERSECTS: - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case CONTAINS: - t = jj_consume_token(CONTAINS); - break; - case INTERSECTS: - t = jj_consume_token(INTERSECTS); - break; - default: - jj_la1[81] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - jj_consume_token(LEFT_PAR); - gvf1 = GeometryExpression(); - jj_consume_token(COMMA); - gvf2 = GeometryExpression(); - jj_consume_token(RIGHT_PAR); - if (t.image.equalsIgnoreCase("contains")) - gf = queryFactory.createContains(gvf1, gvf2); - else - gf = queryFactory.createIntersects(gvf1, gvf2); - break; - case AREA: - jj_consume_token(AREA); - jj_consume_token(LEFT_PAR); - gvf1 = GeometryExpression(); - jj_consume_token(RIGHT_PAR); - gf = queryFactory.createArea(gvf1); - break; - case COORD1: - jj_consume_token(COORD1); - jj_consume_token(LEFT_PAR); - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case POINT: - p1 = Point(); - gf = queryFactory.createCoord1(p1); - break; - case DELIMITED_IDENTIFIER: - case REGULAR_IDENTIFIER: - col1 = Column(); - gf = queryFactory.createCoord1(col1); - break; - default: - jj_la1[82] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - jj_consume_token(RIGHT_PAR); - break; - case COORD2: - jj_consume_token(COORD2); - jj_consume_token(LEFT_PAR); - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case POINT: - p1 = Point(); - gf = queryFactory.createCoord2(p1); - break; - case DELIMITED_IDENTIFIER: - case REGULAR_IDENTIFIER: - col1 = Column(); - gf = queryFactory.createCoord2(col1); - break; - default: - jj_la1[83] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - jj_consume_token(RIGHT_PAR); - break; - case DISTANCE: - jj_consume_token(DISTANCE); - jj_consume_token(LEFT_PAR); - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case POINT: - p1 = Point(); - break; - case DELIMITED_IDENTIFIER: - case REGULAR_IDENTIFIER: - col1 = Column(); - break; - default: - jj_la1[84] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - if (p1 != null) - gvp1 = new GeometryValue<PointFunction>(p1); - else - gvp1 = new GeometryValue<PointFunction>(col1); - jj_consume_token(COMMA); - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case POINT: - p2 = Point(); - break; - case DELIMITED_IDENTIFIER: - case REGULAR_IDENTIFIER: - col2 = Column(); - break; - default: - jj_la1[85] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - if (p2 != null) - gvp2 = new GeometryValue<PointFunction>(p2); - else - gvp2 = new GeometryValue<PointFunction>(col2); - jj_consume_token(RIGHT_PAR); - gf = queryFactory.createDistance(gvp1, gvp2); - break; - default: - jj_la1[86] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - }catch(Exception ex){ - { - if (true) - throw generateParseException(ex); - } - } - { - if (true) - return gf; - } - throw new Error("Missing return statement in function"); - }finally{ - trace_return("GeometryFunction"); - } - } - - final public ADQLOperand CoordinateSystem() throws ParseException{ - trace_call("CoordinateSystem"); - try{ - Token oldToken = token; - ADQLOperand coordSys = null; - coordSys = StringExpression(); - if (allowedCoordSys.size() > 0){ - TextPosition position = new TextPosition(oldToken.next, token); - if (coordSys == null){ - if (true) - throw new ParseException("A coordinate system must always be provided !", position); - } - if (coordSys instanceof StringConstant && !isAllowedCoordSys(((StringConstant)coordSys).getValue())){ - if (true) - throw new ParseException("\u005c"" + coordSys.toADQL() + "\u005c" is not an allowed coordinate systems !", position); - } - } - - { - if (true) - return coordSys; - } - throw new Error("Missing return statement in function"); - }finally{ - trace_return("CoordinateSystem"); - } - } - - final public GeometryFunction GeometryValueFunction() throws ParseException{ - trace_call("GeometryValueFunction"); - try{ - ADQLOperand coordSys; - ADQLOperand width, height; - ADQLOperand[] coords, tmp; - Vector<ADQLOperand> vCoords; - ADQLOperand op = null; - GeometryValue<GeometryFunction> gvf = null; - GeometryFunction gf = null; - try{ - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case BOX: - jj_consume_token(BOX); - jj_consume_token(LEFT_PAR); - coordSys = CoordinateSystem(); - jj_consume_token(COMMA); - coords = Coordinates(); - jj_consume_token(COMMA); - width = NumericExpression(); - jj_consume_token(COMMA); - height = NumericExpression(); - jj_consume_token(RIGHT_PAR); - gf = queryFactory.createBox(coordSys, coords[0], coords[1], width, height); - break; - case CENTROID: - jj_consume_token(CENTROID); - jj_consume_token(LEFT_PAR); - gvf = GeometryExpression(); - jj_consume_token(RIGHT_PAR); - gf = queryFactory.createCentroid(gvf); - break; - case CIRCLE: - jj_consume_token(CIRCLE); - jj_consume_token(LEFT_PAR); - coordSys = CoordinateSystem(); - jj_consume_token(COMMA); - coords = Coordinates(); - jj_consume_token(COMMA); - width = NumericExpression(); - jj_consume_token(RIGHT_PAR); - gf = queryFactory.createCircle(coordSys, coords[0], coords[1], width); - break; - case POINT: - gf = Point(); - break; - case POLYGON: - jj_consume_token(POLYGON); - jj_consume_token(LEFT_PAR); - coordSys = CoordinateSystem(); - vCoords = new Vector<ADQLOperand>(); - jj_consume_token(COMMA); - tmp = Coordinates(); - vCoords.add(tmp[0]); - vCoords.add(tmp[1]); - jj_consume_token(COMMA); - tmp = Coordinates(); - vCoords.add(tmp[0]); - vCoords.add(tmp[1]); - jj_consume_token(COMMA); - tmp = Coordinates(); - vCoords.add(tmp[0]); - vCoords.add(tmp[1]); - label_12: while(true){ - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case COMMA: - ; - break; - default: - jj_la1[87] = jj_gen; - break label_12; - } - jj_consume_token(COMMA); - tmp = Coordinates(); - vCoords.add(tmp[0]); - vCoords.add(tmp[1]); - } - jj_consume_token(RIGHT_PAR); - gf = queryFactory.createPolygon(coordSys, vCoords); - break; - case REGION: - jj_consume_token(REGION); - jj_consume_token(LEFT_PAR); - op = StringExpression(); - jj_consume_token(RIGHT_PAR); - gf = queryFactory.createRegion(op); - break; - default: - jj_la1[88] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - }catch(Exception ex){ - { - if (true) - throw generateParseException(ex); - } - } - { - if (true) - return gf; - } - throw new Error("Missing return statement in function"); - }finally{ - trace_return("GeometryValueFunction"); - } - } - - final public PointFunction Point() throws ParseException{ - trace_call("Point"); - try{ - ADQLOperand coordSys; - ADQLOperand[] coords; - jj_consume_token(POINT); - jj_consume_token(LEFT_PAR); - coordSys = CoordinateSystem(); - jj_consume_token(COMMA); - coords = Coordinates(); - jj_consume_token(RIGHT_PAR); - try{ - { - if (true) - return queryFactory.createPoint(coordSys, coords[0], coords[1]); - } - }catch(Exception ex){ - { - if (true) - throw generateParseException(ex); - } - } - throw new Error("Missing return statement in function"); - }finally{ - trace_return("Point"); - } - } - - final public GeometryFunction ExtractCoordSys() throws ParseException{ - trace_call("ExtractCoordSys"); - try{ - GeometryValue<GeometryFunction> gvf; - jj_consume_token(COORDSYS); - jj_consume_token(LEFT_PAR); - gvf = GeometryExpression(); - jj_consume_token(RIGHT_PAR); - try{ - { - if (true) - return queryFactory.createExtractCoordSys(gvf); - } - }catch(Exception ex){ - { - if (true) - throw generateParseException(ex); - } - } - throw new Error("Missing return statement in function"); - }finally{ - trace_return("ExtractCoordSys"); - } - } - - /* ***************** */ - /* NUMERIC FUNCTIONS */ - /* ***************** */ - final public ADQLFunction NumericFunction() throws ParseException{ - trace_call("NumericFunction"); - try{ - ADQLFunction fct; - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case ABS: - case CEILING: - case DEGREES: - case EXP: - case FLOOR: - case LOG: - case LOG10: - case MOD: - case PI: - case POWER: - case RADIANS: - case RAND: - case ROUND: - case SQRT: - case TRUNCATE: - fct = MathFunction(); + case CENTROID: + jj_consume_token(CENTROID); + jj_consume_token(LEFT_PAR); + gvf = GeometryExpression(); + jj_consume_token(RIGHT_PAR); + gf = queryFactory.createCentroid(gvf); break; - case ACOS: - case ASIN: - case ATAN: - case ATAN2: - case COS: - case COT: - case SIN: - case TAN: - fct = TrigFunction(); + case CIRCLE: + jj_consume_token(CIRCLE); + jj_consume_token(LEFT_PAR); + coordSys = CoordinateSystem(); + jj_consume_token(COMMA); + coords = Coordinates(); + jj_consume_token(COMMA); + width = NumericExpression(); + jj_consume_token(RIGHT_PAR); + gf = queryFactory.createCircle(coordSys, coords[0], coords[1], width); break; - case CONTAINS: - case INTERSECTS: - case AREA: - case COORD1: - case COORD2: - case DISTANCE: - fct = GeometryFunction(); + case POINT: + gf = Point(); break; - case REGULAR_IDENTIFIER: - fct = UserDefinedFunction(); + case POLYGON: + jj_consume_token(POLYGON); + jj_consume_token(LEFT_PAR); + coordSys = CoordinateSystem(); + vCoords = new Vector<ADQLOperand>(); + jj_consume_token(COMMA); + tmp = Coordinates(); + vCoords.add(tmp[0]); + vCoords.add(tmp[1]); + jj_consume_token(COMMA); + tmp = Coordinates(); + vCoords.add(tmp[0]); + vCoords.add(tmp[1]); + jj_consume_token(COMMA); + tmp = Coordinates(); + vCoords.add(tmp[0]); + vCoords.add(tmp[1]); + label_12: while(true){ + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case COMMA: + ; + break; + default: + jj_la1[88] = jj_gen; + break label_12; + } + jj_consume_token(COMMA); + tmp = Coordinates(); + vCoords.add(tmp[0]); + vCoords.add(tmp[1]); + } + jj_consume_token(RIGHT_PAR); + gf = queryFactory.createPolygon(coordSys, vCoords); + break; + case REGION: + jj_consume_token(REGION); + jj_consume_token(LEFT_PAR); + op = StringExpression(); + jj_consume_token(RIGHT_PAR); + gf = queryFactory.createRegion(op); break; default: jj_la1[89] = jj_gen; jj_consume_token(-1); throw new ParseException(); } + }catch(Exception ex){ { if (true) - return fct; + throw generateParseException(ex); } - throw new Error("Missing return statement in function"); - }finally{ - trace_return("NumericFunction"); } + { + if (true) + return gf; + } + throw new Error("Missing return statement in function"); } - final public MathFunction MathFunction() throws ParseException{ - trace_call("MathFunction"); + final public PointFunction Point() throws ParseException{ + ADQLOperand coordSys; + ADQLOperand[] coords; + jj_consume_token(POINT); + jj_consume_token(LEFT_PAR); + coordSys = CoordinateSystem(); + jj_consume_token(COMMA); + coords = Coordinates(); + jj_consume_token(RIGHT_PAR); try{ - Token fct = null; - ADQLOperand param1 = null, param2 = null; - String integerValue = null; - try{ - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case ABS: - fct = jj_consume_token(ABS); - jj_consume_token(LEFT_PAR); - param1 = NumericExpression(); - jj_consume_token(RIGHT_PAR); - break; - case CEILING: - fct = jj_consume_token(CEILING); - jj_consume_token(LEFT_PAR); - param1 = NumericExpression(); - jj_consume_token(RIGHT_PAR); - break; - case DEGREES: - fct = jj_consume_token(DEGREES); - jj_consume_token(LEFT_PAR); - param1 = NumericExpression(); - jj_consume_token(RIGHT_PAR); - break; - case EXP: - fct = jj_consume_token(EXP); - jj_consume_token(LEFT_PAR); - param1 = NumericExpression(); - jj_consume_token(RIGHT_PAR); - break; - case FLOOR: - fct = jj_consume_token(FLOOR); - jj_consume_token(LEFT_PAR); - param1 = NumericExpression(); - jj_consume_token(RIGHT_PAR); - break; - case LOG: - fct = jj_consume_token(LOG); - jj_consume_token(LEFT_PAR); - param1 = NumericExpression(); - jj_consume_token(RIGHT_PAR); - break; - case LOG10: - fct = jj_consume_token(LOG10); - jj_consume_token(LEFT_PAR); - param1 = NumericExpression(); - jj_consume_token(RIGHT_PAR); - break; - case MOD: - fct = jj_consume_token(MOD); - jj_consume_token(LEFT_PAR); - param1 = NumericExpression(); - jj_consume_token(COMMA); - param2 = NumericExpression(); - jj_consume_token(RIGHT_PAR); - break; - case PI: - fct = jj_consume_token(PI); - jj_consume_token(LEFT_PAR); - jj_consume_token(RIGHT_PAR); - break; - case POWER: - fct = jj_consume_token(POWER); - jj_consume_token(LEFT_PAR); - param1 = NumericExpression(); - jj_consume_token(COMMA); - param2 = NumericExpression(); - jj_consume_token(RIGHT_PAR); - break; - case RADIANS: - fct = jj_consume_token(RADIANS); - jj_consume_token(LEFT_PAR); - param1 = NumericExpression(); - jj_consume_token(RIGHT_PAR); - break; - case RAND: - fct = jj_consume_token(RAND); - jj_consume_token(LEFT_PAR); - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case LEFT_PAR: - case PLUS: - case MINUS: - case AVG: - case MAX: - case MIN: - case SUM: - case COUNT: - case CONTAINS: - case INTERSECTS: - case AREA: - case COORD1: - case COORD2: - case DISTANCE: - case ABS: - case CEILING: - case DEGREES: - case EXP: - case FLOOR: - case LOG: - case LOG10: - case MOD: - case PI: - case POWER: - case RADIANS: - case RAND: - case ROUND: - case SQRT: - case TRUNCATE: - case ACOS: - case ASIN: - case ATAN: - case ATAN2: - case COS: - case COT: - case SIN: - case TAN: - case STRING_LITERAL: - case DELIMITED_IDENTIFIER: - case REGULAR_IDENTIFIER: - case SCIENTIFIC_NUMBER: - case UNSIGNED_FLOAT: - case UNSIGNED_INTEGER: - param1 = NumericExpression(); - break; - default: - jj_la1[90] = jj_gen; - ; - } - jj_consume_token(RIGHT_PAR); - break; - case ROUND: - fct = jj_consume_token(ROUND); - jj_consume_token(LEFT_PAR); - param1 = NumericExpression(); - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case COMMA: - jj_consume_token(COMMA); - integerValue = SignedInteger(); - param2 = queryFactory.createNumericConstant(integerValue); - break; - default: - jj_la1[91] = jj_gen; - ; - } - jj_consume_token(RIGHT_PAR); - break; - case SQRT: - fct = jj_consume_token(SQRT); - jj_consume_token(LEFT_PAR); - param1 = NumericExpression(); - jj_consume_token(RIGHT_PAR); - break; - case TRUNCATE: - fct = jj_consume_token(TRUNCATE); - jj_consume_token(LEFT_PAR); - param1 = NumericExpression(); - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case COMMA: - jj_consume_token(COMMA); - integerValue = SignedInteger(); - param2 = queryFactory.createNumericConstant(integerValue); - break; - default: - jj_la1[92] = jj_gen; - ; - } - jj_consume_token(RIGHT_PAR); - break; - default: - jj_la1[93] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } - if (param1 != null){ - if (true) - return queryFactory.createMathFunction(MathFunctionType.valueOf(fct.image.toUpperCase()), param1, param2); - }else{ - if (true) - return null; - } - }catch(Exception ex){ - { - if (true) - throw generateParseException(ex); - } + { + if (true) + return queryFactory.createPoint(coordSys, coords[0], coords[1]); + } + }catch(Exception ex){ + { + if (true) + throw generateParseException(ex); } - throw new Error("Missing return statement in function"); - }finally{ - trace_return("MathFunction"); } + throw new Error("Missing return statement in function"); } - final public MathFunction TrigFunction() throws ParseException{ - trace_call("TrigFunction"); + final public GeometryFunction ExtractCoordSys() throws ParseException{ + GeometryValue<GeometryFunction> gvf; + jj_consume_token(COORDSYS); + jj_consume_token(LEFT_PAR); + gvf = GeometryExpression(); + jj_consume_token(RIGHT_PAR); + try{ + { + if (true) + return queryFactory.createExtractCoordSys(gvf); + } + }catch(Exception ex){ + { + if (true) + throw generateParseException(ex); + } + } + throw new Error("Missing return statement in function"); + } + + /* ***************** */ + /* NUMERIC FUNCTIONS */ + /* ***************** */ + final public ADQLFunction NumericFunction() throws ParseException{ + ADQLFunction fct; + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case ABS: + case CEILING: + case DEGREES: + case EXP: + case FLOOR: + case LOG: + case LOG10: + case MOD: + case PI: + case POWER: + case RADIANS: + case RAND: + case ROUND: + case SQRT: + case TRUNCATE: + fct = MathFunction(); + break; + case ACOS: + case ASIN: + case ATAN: + case ATAN2: + case COS: + case COT: + case SIN: + case TAN: + fct = TrigFunction(); + break; + case CONTAINS: + case INTERSECTS: + case AREA: + case COORD1: + case COORD2: + case DISTANCE: + fct = GeometryFunction(); + break; + case REGULAR_IDENTIFIER: + fct = UserDefinedFunction(); + ((UserDefinedFunction)fct).setExpectedType('N'); + break; + default: + jj_la1[90] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + { + if (true) + return fct; + } + throw new Error("Missing return statement in function"); + } + + final public MathFunction MathFunction() throws ParseException{ + Token fct = null; + ADQLOperand param1 = null, param2 = null; + String integerValue = null; try{ - Token fct = null; - ADQLOperand param1 = null, param2 = null; switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case ACOS: - fct = jj_consume_token(ACOS); + case ABS: + fct = jj_consume_token(ABS); + jj_consume_token(LEFT_PAR); + param1 = NumericExpression(); + jj_consume_token(RIGHT_PAR); + break; + case CEILING: + fct = jj_consume_token(CEILING); + jj_consume_token(LEFT_PAR); + param1 = NumericExpression(); + jj_consume_token(RIGHT_PAR); + break; + case DEGREES: + fct = jj_consume_token(DEGREES); + jj_consume_token(LEFT_PAR); + param1 = NumericExpression(); + jj_consume_token(RIGHT_PAR); + break; + case EXP: + fct = jj_consume_token(EXP); + jj_consume_token(LEFT_PAR); + param1 = NumericExpression(); + jj_consume_token(RIGHT_PAR); + break; + case FLOOR: + fct = jj_consume_token(FLOOR); + jj_consume_token(LEFT_PAR); + param1 = NumericExpression(); + jj_consume_token(RIGHT_PAR); + break; + case LOG: + fct = jj_consume_token(LOG); jj_consume_token(LEFT_PAR); param1 = NumericExpression(); jj_consume_token(RIGHT_PAR); break; - case ASIN: - fct = jj_consume_token(ASIN); + case LOG10: + fct = jj_consume_token(LOG10); jj_consume_token(LEFT_PAR); param1 = NumericExpression(); jj_consume_token(RIGHT_PAR); break; - case ATAN: - fct = jj_consume_token(ATAN); + case MOD: + fct = jj_consume_token(MOD); jj_consume_token(LEFT_PAR); param1 = NumericExpression(); + jj_consume_token(COMMA); + param2 = NumericExpression(); + jj_consume_token(RIGHT_PAR); + break; + case PI: + fct = jj_consume_token(PI); + jj_consume_token(LEFT_PAR); jj_consume_token(RIGHT_PAR); break; - case ATAN2: - fct = jj_consume_token(ATAN2); + case POWER: + fct = jj_consume_token(POWER); jj_consume_token(LEFT_PAR); param1 = NumericExpression(); jj_consume_token(COMMA); param2 = NumericExpression(); jj_consume_token(RIGHT_PAR); break; - case COS: - fct = jj_consume_token(COS); + case RADIANS: + fct = jj_consume_token(RADIANS); jj_consume_token(LEFT_PAR); param1 = NumericExpression(); jj_consume_token(RIGHT_PAR); break; - case COT: - fct = jj_consume_token(COT); + case RAND: + fct = jj_consume_token(RAND); + jj_consume_token(LEFT_PAR); + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case LEFT_PAR: + case PLUS: + case MINUS: + case AVG: + case MAX: + case MIN: + case SUM: + case COUNT: + case CONTAINS: + case INTERSECTS: + case AREA: + case COORD1: + case COORD2: + case DISTANCE: + case ABS: + case CEILING: + case DEGREES: + case EXP: + case FLOOR: + case LOG: + case LOG10: + case MOD: + case PI: + case POWER: + case RADIANS: + case RAND: + case ROUND: + case SQRT: + case TRUNCATE: + case ACOS: + case ASIN: + case ATAN: + case ATAN2: + case COS: + case COT: + case SIN: + case TAN: + case DELIMITED_IDENTIFIER: + case REGULAR_IDENTIFIER: + case SCIENTIFIC_NUMBER: + case UNSIGNED_FLOAT: + case UNSIGNED_INTEGER: + param1 = NumericExpression(); + break; + default: + jj_la1[91] = jj_gen; + ; + } + jj_consume_token(RIGHT_PAR); + break; + case ROUND: + fct = jj_consume_token(ROUND); jj_consume_token(LEFT_PAR); param1 = NumericExpression(); + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case COMMA: + jj_consume_token(COMMA); + integerValue = SignedInteger(); + param2 = queryFactory.createNumericConstant(integerValue); + break; + default: + jj_la1[92] = jj_gen; + ; + } jj_consume_token(RIGHT_PAR); break; - case SIN: - fct = jj_consume_token(SIN); + case SQRT: + fct = jj_consume_token(SQRT); jj_consume_token(LEFT_PAR); param1 = NumericExpression(); jj_consume_token(RIGHT_PAR); break; - case TAN: - fct = jj_consume_token(TAN); + case TRUNCATE: + fct = jj_consume_token(TRUNCATE); jj_consume_token(LEFT_PAR); param1 = NumericExpression(); + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case COMMA: + jj_consume_token(COMMA); + integerValue = SignedInteger(); + param2 = queryFactory.createNumericConstant(integerValue); + break; + default: + jj_la1[93] = jj_gen; + ; + } jj_consume_token(RIGHT_PAR); break; default: @@ -3270,131 +2980,203 @@ public class ADQLParser implements ADQLParserConstants { jj_consume_token(-1); throw new ParseException(); } - try{ - if (param1 != null){ - if (true) - return queryFactory.createMathFunction(MathFunctionType.valueOf(fct.image.toUpperCase()), param1, param2); - }else{ - if (true) - return null; - } - }catch(Exception ex){ - { - if (true) - throw generateParseException(ex); - } + if (param1 != null){ + if (true) + return queryFactory.createMathFunction(MathFunctionType.valueOf(fct.image.toUpperCase()), param1, param2); + }else{ + if (true) + return null; + } + }catch(Exception ex){ + { + if (true) + throw generateParseException(ex); + } + } + throw new Error("Missing return statement in function"); + } + + final public MathFunction TrigFunction() throws ParseException{ + Token fct = null; + ADQLOperand param1 = null, param2 = null; + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case ACOS: + fct = jj_consume_token(ACOS); + jj_consume_token(LEFT_PAR); + param1 = NumericExpression(); + jj_consume_token(RIGHT_PAR); + break; + case ASIN: + fct = jj_consume_token(ASIN); + jj_consume_token(LEFT_PAR); + param1 = NumericExpression(); + jj_consume_token(RIGHT_PAR); + break; + case ATAN: + fct = jj_consume_token(ATAN); + jj_consume_token(LEFT_PAR); + param1 = NumericExpression(); + jj_consume_token(RIGHT_PAR); + break; + case ATAN2: + fct = jj_consume_token(ATAN2); + jj_consume_token(LEFT_PAR); + param1 = NumericExpression(); + jj_consume_token(COMMA); + param2 = NumericExpression(); + jj_consume_token(RIGHT_PAR); + break; + case COS: + fct = jj_consume_token(COS); + jj_consume_token(LEFT_PAR); + param1 = NumericExpression(); + jj_consume_token(RIGHT_PAR); + break; + case COT: + fct = jj_consume_token(COT); + jj_consume_token(LEFT_PAR); + param1 = NumericExpression(); + jj_consume_token(RIGHT_PAR); + break; + case SIN: + fct = jj_consume_token(SIN); + jj_consume_token(LEFT_PAR); + param1 = NumericExpression(); + jj_consume_token(RIGHT_PAR); + break; + case TAN: + fct = jj_consume_token(TAN); + jj_consume_token(LEFT_PAR); + param1 = NumericExpression(); + jj_consume_token(RIGHT_PAR); + break; + default: + jj_la1[95] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + try{ + if (param1 != null){ + if (true) + return queryFactory.createMathFunction(MathFunctionType.valueOf(fct.image.toUpperCase()), param1, param2); + }else{ + if (true) + return null; + } + }catch(Exception ex){ + { + if (true) + throw generateParseException(ex); } - throw new Error("Missing return statement in function"); - }finally{ - trace_return("TrigFunction"); } + throw new Error("Missing return statement in function"); } - /* /!\ WARNING: The function name may be prefixed by "udf_" but there is no way to check it here ! */ final public UserDefinedFunction UserDefinedFunction() throws ParseException{ - trace_call("UserDefinedFunction"); - try{ - Token fct; - Vector<ADQLOperand> params = new Vector<ADQLOperand>(); - ADQLOperand op; - fct = jj_consume_token(REGULAR_IDENTIFIER); - jj_consume_token(LEFT_PAR); - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case LEFT_PAR: - case PLUS: - case MINUS: - case AVG: - case MAX: - case MIN: - case SUM: - case COUNT: - case BOX: - case CENTROID: - case CIRCLE: - case POINT: - case POLYGON: - case REGION: - case CONTAINS: - case INTERSECTS: - case AREA: - case COORD1: - case COORD2: - case COORDSYS: - case DISTANCE: - case ABS: - case CEILING: - case DEGREES: - case EXP: - case FLOOR: - case LOG: - case LOG10: - case MOD: - case PI: - case POWER: - case RADIANS: - case RAND: - case ROUND: - case SQRT: - case TRUNCATE: - case ACOS: - case ASIN: - case ATAN: - case ATAN2: - case COS: - case COT: - case SIN: - case TAN: - case STRING_LITERAL: - case DELIMITED_IDENTIFIER: - case REGULAR_IDENTIFIER: - case SCIENTIFIC_NUMBER: - case UNSIGNED_FLOAT: - case UNSIGNED_INTEGER: + Token fct; + Vector<ADQLOperand> params = new Vector<ADQLOperand>(); + ADQLOperand op; + fct = jj_consume_token(REGULAR_IDENTIFIER); + jj_consume_token(LEFT_PAR); + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case LEFT_PAR: + case PLUS: + case MINUS: + case AVG: + case MAX: + case MIN: + case SUM: + case COUNT: + case BOX: + case CENTROID: + case CIRCLE: + case POINT: + case POLYGON: + case REGION: + case CONTAINS: + case INTERSECTS: + case AREA: + case COORD1: + case COORD2: + case COORDSYS: + case DISTANCE: + case ABS: + case CEILING: + case DEGREES: + case EXP: + case FLOOR: + case LOG: + case LOG10: + case MOD: + case PI: + case POWER: + case RADIANS: + case RAND: + case ROUND: + case SQRT: + case TRUNCATE: + case ACOS: + case ASIN: + case ATAN: + case ATAN2: + case COS: + case COT: + case SIN: + case TAN: + case STRING_LITERAL: + case DELIMITED_IDENTIFIER: + case REGULAR_IDENTIFIER: + case SCIENTIFIC_NUMBER: + case UNSIGNED_FLOAT: + case UNSIGNED_INTEGER: + op = ValueExpression(); + params.add(op); + label_13: while(true){ + switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ + case COMMA: + ; + break; + default: + jj_la1[96] = jj_gen; + break label_13; + } + jj_consume_token(COMMA); op = ValueExpression(); params.add(op); - label_13: while(true){ - switch((jj_ntk == -1) ? jj_ntk() : jj_ntk){ - case COMMA: - ; - break; - default: - jj_la1[95] = jj_gen; - break label_13; - } - jj_consume_token(COMMA); - op = ValueExpression(); - params.add(op); - } - break; - default: - jj_la1[96] = jj_gen; - ; - } - jj_consume_token(RIGHT_PAR); - //System.out.println("INFO [ADQLParser]: \""+fct.image+"\" (from line "+fct.beginLine+" and column "+fct.beginColumn+" to line "+token.endLine+" and column "+(token.endColumn+1)+") is considered as an user defined function !"); - try{ - ADQLOperand[] parameters = new ADQLOperand[params.size()]; - for(int i = 0; i < params.size(); i++) - parameters[i] = params.get(i); - { - if (true) - return queryFactory.createUserDefinedFunction(fct.image, parameters); - } - }catch(UnsupportedOperationException uoe){ - { - if (true) - throw new ParseException(uoe.getMessage(), new TextPosition(fct, token)); - } - }catch(Exception ex){ - { - if (true) - throw generateParseException(ex); } + break; + default: + jj_la1[97] = jj_gen; + ; + } + jj_consume_token(RIGHT_PAR); + //System.out.println("INFO [ADQLParser]: \""+fct.image+"\" (from line "+fct.beginLine+" and column "+fct.beginColumn+" to line "+token.endLine+" and column "+(token.endColumn+1)+") is considered as an user defined function !"); + try{ + // Build the parameters list: + ADQLOperand[] parameters = new ADQLOperand[params.size()]; + for(int i = 0; i < params.size(); i++) + parameters[i] = params.get(i); + + // Create the UDF function: + { + if (true) + return queryFactory.createUserDefinedFunction(fct.image, parameters); + } + }catch(UnsupportedOperationException uoe){ + /* This catch clause is just for backward compatibility: + * if the createUserDefinedFunction(...) is overridden and + * the function can not be identified a such exception may be thrown). */ + { + if (true) + throw new ParseException(uoe.getMessage(), new TextPosition(fct, token)); + } + }catch(Exception ex){ + { + if (true) + throw generateParseException(ex); } - throw new Error("Missing return statement in function"); - }finally{ - trace_return("UserDefinedFunction"); } + throw new Error("Missing return statement in function"); } private boolean jj_2_1(int xla){ @@ -3553,32 +3335,94 @@ public class ADQLParser implements ADQLParserConstants { } } - private boolean jj_3R_16(){ - if (jj_scan_token(LEFT_PAR)) + private boolean jj_2_14(int xla){ + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try{ + return !jj_3_14(); + }catch(LookaheadSuccess ls){ return true; - if (jj_3R_28()) + }finally{ + jj_save(13, xla); + } + } + + private boolean jj_2_15(int xla){ + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try{ + return !jj_3_15(); + }catch(LookaheadSuccess ls){ return true; - if (jj_scan_token(RIGHT_PAR)) + }finally{ + jj_save(14, xla); + } + } + + private boolean jj_2_16(int xla){ + jj_la = xla; + jj_lastpos = jj_scanpos = token; + try{ + return !jj_3_16(); + }catch(LookaheadSuccess ls){ + return true; + }finally{ + jj_save(15, xla); + } + } + + private boolean jj_3R_185(){ + if (jj_scan_token(NOT)) return true; return false; } - private boolean jj_3R_113(){ - if (jj_3R_101()) + private boolean jj_3R_146(){ + if (jj_scan_token(COMMA)) + return true; + if (jj_3R_46()) return true; return false; } - private boolean jj_3R_152(){ + private boolean jj_3R_149(){ Token xsp; xsp = jj_scanpos; - if (jj_3R_164()) + if (jj_3R_161()){ + jj_scanpos = xsp; + if (jj_3_1()){ + jj_scanpos = xsp; + if (jj_3R_162()) + return true; + } + } + return false; + } + + private boolean jj_3R_150(){ + if (jj_scan_token(COMMA)) + return true; + if (jj_3R_149()) + return true; + return false; + } + + private boolean jj_3R_145(){ + if (jj_3R_109()) + return true; + return false; + } + + private boolean jj_3R_163(){ + Token xsp; + xsp = jj_scanpos; + if (jj_3R_185()) jj_scanpos = xsp; - if (jj_3R_165()) + if (jj_3R_186()) return true; while(true){ xsp = jj_scanpos; - if (jj_3R_166()){ + if (jj_3R_187()){ jj_scanpos = xsp; break; } @@ -3586,113 +3430,138 @@ public class ADQLParser implements ADQLParserConstants { return false; } - private boolean jj_3R_122(){ - if (jj_3R_144()) + private boolean jj_3R_148(){ + if (jj_scan_token(TOP)) + return true; + if (jj_scan_token(UNSIGNED_INTEGER)) return true; return false; } - private boolean jj_3R_121(){ - if (jj_3R_143()) + private boolean jj_3R_147(){ + if (jj_scan_token(QUANTIFIER)) return true; return false; } - private boolean jj_3R_120(){ - if (jj_3R_142()) + private boolean jj_3R_48(){ + if (jj_scan_token(SELECT)) + return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3R_147()) + jj_scanpos = xsp; + xsp = jj_scanpos; + if (jj_3R_148()) + jj_scanpos = xsp; + if (jj_3R_149()) return true; + while(true){ + xsp = jj_scanpos; + if (jj_3R_150()){ + jj_scanpos = xsp; + break; + } + } return false; } - private boolean jj_3R_119(){ - if (jj_3R_141()) + private boolean jj_3R_144(){ + if (jj_3R_21()) return true; return false; } - private boolean jj_3R_112(){ - if (jj_3R_23()) + private boolean jj_3R_16(){ + if (jj_scan_token(LEFT_PAR)) + return true; + if (jj_3R_31()) + return true; + if (jj_scan_token(RIGHT_PAR)) return true; return false; } - private boolean jj_3R_162(){ - if (jj_3R_49()) + private boolean jj_3R_53(){ + if (jj_3R_74()) return true; return false; } - private boolean jj_3R_64(){ + private boolean jj_3R_122(){ Token xsp; xsp = jj_scanpos; - if (jj_3R_112()){ + if (jj_3R_144()){ jj_scanpos = xsp; - if (jj_3R_113()) + if (jj_3R_145()) return true; } return false; } - private boolean jj_3R_32(){ - if (jj_3R_49()) + private boolean jj_3R_55(){ + if (jj_3R_76()) return true; return false; } - private boolean jj_3_8(){ - if (jj_3R_20()) + private boolean jj_3_11(){ + if (jj_3R_24()) return true; return false; } - private boolean jj_3R_31(){ - if (jj_3R_48()) + private boolean jj_3R_54(){ + if (jj_3R_75()) return true; return false; } - private boolean jj_3R_18(){ + private boolean jj_3R_35(){ Token xsp; xsp = jj_scanpos; - if (jj_3R_31()){ + if (jj_3R_54()){ jj_scanpos = xsp; - if (jj_3_8()){ + if (jj_3_11()){ jj_scanpos = xsp; - if (jj_3R_32()) + if (jj_3R_55()) return true; } } return false; } - private boolean jj_3R_28(){ - if (jj_3R_44()) + private boolean jj_3R_133(){ + if (jj_3R_155()) return true; - if (jj_3R_118()) + return false; + } + + private boolean jj_3R_132(){ + if (jj_3R_154()) return true; - Token xsp; - xsp = jj_scanpos; - if (jj_3R_119()) - jj_scanpos = xsp; - xsp = jj_scanpos; - if (jj_3R_120()) - jj_scanpos = xsp; - xsp = jj_scanpos; - if (jj_3R_121()) - jj_scanpos = xsp; - xsp = jj_scanpos; - if (jj_3R_122()) - jj_scanpos = xsp; return false; } - private boolean jj_3R_65(){ - if (jj_3R_41()) + private boolean jj_3R_131(){ + if (jj_3R_153()) + return true; + return false; + } + + private boolean jj_3R_130(){ + if (jj_3R_152()) + return true; + return false; + } + + private boolean jj_3R_123(){ + if (jj_3R_46()) return true; Token xsp; while(true){ xsp = jj_scanpos; - if (jj_3R_114()){ + if (jj_3R_146()){ jj_scanpos = xsp; break; } @@ -3700,23 +3569,15 @@ public class ADQLParser implements ADQLParserConstants { return false; } - private boolean jj_3R_182(){ - if (jj_scan_token(COMMA)) - return true; - if (jj_3R_191()) - return true; - return false; - } - - private boolean jj_3R_43(){ + private boolean jj_3R_47(){ if (jj_scan_token(CONCAT)) return true; - if (jj_3R_18()) + if (jj_3R_35()) return true; return false; } - private boolean jj_3R_181(){ + private boolean jj_3R_174(){ if (jj_scan_token(COMMA)) return true; if (jj_3R_191()) @@ -3724,25 +3585,42 @@ public class ADQLParser implements ADQLParserConstants { return false; } - private boolean jj_3R_106(){ - if (jj_scan_token(FULL)) + private boolean jj_3R_173(){ + if (jj_scan_token(COMMA)) + return true; + if (jj_3R_191()) return true; return false; } - private boolean jj_3R_170(){ - if (jj_scan_token(MINUS)) + private boolean jj_3R_31(){ + if (jj_3R_48()) return true; + if (jj_3R_129()) + return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3R_130()) + jj_scanpos = xsp; + xsp = jj_scanpos; + if (jj_3R_131()) + jj_scanpos = xsp; + xsp = jj_scanpos; + if (jj_3R_132()) + jj_scanpos = xsp; + xsp = jj_scanpos; + if (jj_3R_133()) + jj_scanpos = xsp; return false; } - private boolean jj_3R_24(){ - if (jj_3R_18()) + private boolean jj_3R_27(){ + if (jj_3R_35()) return true; Token xsp; while(true){ xsp = jj_scanpos; - if (jj_3R_43()){ + if (jj_3R_47()){ jj_scanpos = xsp; break; } @@ -3750,24 +3628,30 @@ public class ADQLParser implements ADQLParserConstants { return false; } - private boolean jj_3_7(){ - if (jj_3R_19()) + private boolean jj_3R_73(){ + if (jj_scan_token(MINUS)) return true; return false; } - private boolean jj_3R_161(){ + private boolean jj_3_10(){ + if (jj_3R_23()) + return true; + return false; + } + + private boolean jj_3R_52(){ Token xsp; xsp = jj_scanpos; if (jj_scan_token(8)){ jj_scanpos = xsp; - if (jj_3R_170()) + if (jj_3R_73()) return true; } return false; } - private boolean jj_3R_160(){ + private boolean jj_3R_168(){ Token xsp; xsp = jj_scanpos; if (jj_scan_token(10)){ @@ -3775,198 +3659,284 @@ public class ADQLParser implements ADQLParserConstants { if (jj_scan_token(11)) return true; } - if (jj_3R_130()) + if (jj_3R_135()) return true; return false; } - private boolean jj_3R_148(){ + private boolean jj_3R_112(){ + if (jj_scan_token(FULL)) + return true; + return false; + } + + private boolean jj_3R_34(){ Token xsp; xsp = jj_scanpos; - if (jj_3R_161()) + if (jj_3R_52()) jj_scanpos = xsp; xsp = jj_scanpos; - if (jj_3_7()){ + if (jj_3_10()){ jj_scanpos = xsp; - if (jj_3R_162()) + if (jj_3R_53()) return true; } return false; } - private boolean jj_3R_20(){ + private boolean jj_3R_24(){ if (jj_scan_token(REGULAR_IDENTIFIER)) return true; if (jj_scan_token(LEFT_PAR)) return true; Token xsp; xsp = jj_scanpos; - if (jj_3R_65()) + if (jj_3R_123()) jj_scanpos = xsp; if (jj_scan_token(RIGHT_PAR)) return true; return false; } - private boolean jj_3R_109(){ - if (jj_scan_token(FULL)) + private boolean jj_3R_156(){ + Token xsp; + xsp = jj_scanpos; + if (jj_scan_token(8)){ + jj_scanpos = xsp; + if (jj_scan_token(9)) + return true; + } + if (jj_3R_108()) return true; return false; } - private boolean jj_3R_180(){ - if (jj_3R_102()) + private boolean jj_3R_19(){ + if (jj_3R_34()) return true; - return false; - } - - private boolean jj_3R_145(){ Token xsp; xsp = jj_scanpos; if (jj_scan_token(8)){ jj_scanpos = xsp; - if (jj_scan_token(9)) - return true; + if (jj_scan_token(9)){ + jj_scanpos = xsp; + if (jj_scan_token(10)){ + jj_scanpos = xsp; + if (jj_scan_token(11)) + return true; + } + } } - if (jj_3R_102()) + return false; + } + + private boolean jj_3R_172(){ + if (jj_3R_108()) return true; return false; } - private boolean jj_3R_93(){ + private boolean jj_3R_20(){ + if (jj_3R_35()) + return true; + if (jj_scan_token(CONCAT)) + return true; + return false; + } + + private boolean jj_3R_135(){ + if (jj_3R_34()) + return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3R_168()) + jj_scanpos = xsp; + return false; + } + + private boolean jj_3R_100(){ if (jj_scan_token(TAN)) return true; if (jj_scan_token(LEFT_PAR)) return true; - if (jj_3R_102()) + if (jj_3R_108()) return true; if (jj_scan_token(RIGHT_PAR)) return true; return false; } - private boolean jj_3R_92(){ + private boolean jj_3_9(){ + if (jj_3R_22()) + return true; + return false; + } + + private boolean jj_3R_99(){ if (jj_scan_token(SIN)) return true; if (jj_scan_token(LEFT_PAR)) return true; - if (jj_3R_102()) + if (jj_3R_108()) return true; if (jj_scan_token(RIGHT_PAR)) return true; return false; } - private boolean jj_3R_130(){ - if (jj_3R_148()) + private boolean jj_3_8(){ + if (jj_3R_21()) return true; - Token xsp; - xsp = jj_scanpos; - if (jj_3R_160()) - jj_scanpos = xsp; return false; } - private boolean jj_3R_91(){ + private boolean jj_3R_98(){ if (jj_scan_token(COT)) return true; if (jj_scan_token(LEFT_PAR)) return true; - if (jj_3R_102()) + if (jj_3R_108()) return true; if (jj_scan_token(RIGHT_PAR)) return true; return false; } - private boolean jj_3R_90(){ + private boolean jj_3R_115(){ + if (jj_scan_token(FULL)) + return true; + return false; + } + + private boolean jj_3R_97(){ if (jj_scan_token(COS)) return true; if (jj_scan_token(LEFT_PAR)) return true; - if (jj_3R_102()) + if (jj_3R_108()) return true; if (jj_scan_token(RIGHT_PAR)) return true; return false; } - private boolean jj_3R_89(){ + private boolean jj_3_7(){ + if (jj_scan_token(REGULAR_IDENTIFIER)) + return true; + if (jj_scan_token(LEFT_PAR)) + return true; + return false; + } + + private boolean jj_3R_96(){ if (jj_scan_token(ATAN2)) return true; if (jj_scan_token(LEFT_PAR)) return true; - if (jj_3R_102()) + if (jj_3R_108()) return true; if (jj_scan_token(COMMA)) return true; - if (jj_3R_102()) + if (jj_3R_108()) return true; if (jj_scan_token(RIGHT_PAR)) return true; return false; } - private boolean jj_3R_88(){ + private boolean jj_3_6(){ + if (jj_scan_token(LEFT_PAR)) + return true; + return false; + } + + private boolean jj_3R_95(){ if (jj_scan_token(ATAN)) return true; if (jj_scan_token(LEFT_PAR)) return true; - if (jj_3R_102()) + if (jj_3R_108()) return true; if (jj_scan_token(RIGHT_PAR)) return true; return false; } - private boolean jj_3R_105(){ - if (jj_scan_token(RIGHT)) - return true; + private boolean jj_3_5(){ + Token xsp; + xsp = jj_scanpos; + if (jj_scan_token(63)){ + jj_scanpos = xsp; + if (jj_3R_20()) + return true; + } return false; } - private boolean jj_3R_87(){ + private boolean jj_3R_94(){ if (jj_scan_token(ASIN)) return true; if (jj_scan_token(LEFT_PAR)) return true; - if (jj_3R_102()) + if (jj_3R_108()) return true; if (jj_scan_token(RIGHT_PAR)) return true; return false; } - private boolean jj_3R_86(){ + private boolean jj_3_4(){ + Token xsp; + xsp = jj_scanpos; + if (jj_3R_18()){ + jj_scanpos = xsp; + if (jj_3R_19()) + return true; + } + return false; + } + + private boolean jj_3R_18(){ + Token xsp; + xsp = jj_scanpos; + if (jj_scan_token(8)){ + jj_scanpos = xsp; + if (jj_scan_token(9)) + return true; + } + return false; + } + + private boolean jj_3R_93(){ if (jj_scan_token(ACOS)) return true; if (jj_scan_token(LEFT_PAR)) return true; - if (jj_3R_102()) + if (jj_3R_108()) return true; if (jj_scan_token(RIGHT_PAR)) return true; return false; } - private boolean jj_3R_51(){ + private boolean jj_3R_58(){ Token xsp; xsp = jj_scanpos; - if (jj_3R_86()){ + if (jj_3R_93()){ jj_scanpos = xsp; - if (jj_3R_87()){ + if (jj_3R_94()){ jj_scanpos = xsp; - if (jj_3R_88()){ + if (jj_3R_95()){ jj_scanpos = xsp; - if (jj_3R_89()){ + if (jj_3R_96()){ jj_scanpos = xsp; - if (jj_3R_90()){ + if (jj_3R_97()){ jj_scanpos = xsp; - if (jj_3R_91()){ + if (jj_3R_98()){ jj_scanpos = xsp; - if (jj_3R_92()){ + if (jj_3R_99()){ jj_scanpos = xsp; - if (jj_3R_93()) + if (jj_3R_100()) return true; } } @@ -3978,128 +3948,155 @@ public class ADQLParser implements ADQLParserConstants { return false; } - private boolean jj_3_6(){ - if (jj_3R_18()) + private boolean jj_3R_69(){ + if (jj_3R_34()) return true; - if (jj_scan_token(CONCAT)) + return false; + } + + private boolean jj_3R_68(){ + if (jj_3R_35()) return true; return false; } - private boolean jj_3_5(){ - if (jj_scan_token(COORDSYS)) + private boolean jj_3R_67(){ + if (jj_3R_21()) return true; return false; } - private boolean jj_3R_85(){ + private boolean jj_3R_108(){ + if (jj_3R_135()) + return true; + Token xsp; + xsp = jj_scanpos; + if (jj_3R_156()) + jj_scanpos = xsp; + return false; + } + + private boolean jj_3R_92(){ if (jj_scan_token(TRUNCATE)) return true; if (jj_scan_token(LEFT_PAR)) return true; - if (jj_3R_102()) + if (jj_3R_108()) return true; Token xsp; xsp = jj_scanpos; - if (jj_3R_182()) + if (jj_3R_174()) jj_scanpos = xsp; if (jj_scan_token(RIGHT_PAR)) return true; return false; } - private boolean jj_3_4(){ - Token xsp; - xsp = jj_scanpos; - if (jj_scan_token(8)){ - jj_scanpos = xsp; - if (jj_scan_token(9)) - return true; - } + private boolean jj_3R_66(){ + if (jj_3R_109()) + return true; return false; } - private boolean jj_3R_84(){ + private boolean jj_3R_91(){ if (jj_scan_token(SQRT)) return true; if (jj_scan_token(LEFT_PAR)) return true; - if (jj_3R_102()) + if (jj_3R_108()) return true; if (jj_scan_token(RIGHT_PAR)) return true; return false; } - private boolean jj_3R_83(){ + private boolean jj_3R_65(){ + if (jj_3R_24()) + return true; + return false; + } + + private boolean jj_3R_90(){ if (jj_scan_token(ROUND)) return true; if (jj_scan_token(LEFT_PAR)) return true; - if (jj_3R_102()) + if (jj_3R_108()) return true; Token xsp; xsp = jj_scanpos; - if (jj_3R_181()) + if (jj_3R_173()) jj_scanpos = xsp; if (jj_scan_token(RIGHT_PAR)) return true; return false; } - private boolean jj_3R_82(){ + private boolean jj_3R_64(){ + if (jj_scan_token(LEFT_PAR)) + return true; + if (jj_3R_46()) + return true; + if (jj_scan_token(RIGHT_PAR)) + return true; + return false; + } + + private boolean jj_3R_89(){ if (jj_scan_token(RAND)) return true; if (jj_scan_token(LEFT_PAR)) return true; Token xsp; xsp = jj_scanpos; - if (jj_3R_180()) + if (jj_3R_172()) jj_scanpos = xsp; if (jj_scan_token(RIGHT_PAR)) return true; return false; } - private boolean jj_3R_81(){ + private boolean jj_3R_63(){ + if (jj_3R_27()) + return true; + return false; + } + + private boolean jj_3R_88(){ if (jj_scan_token(RADIANS)) return true; if (jj_scan_token(LEFT_PAR)) return true; - if (jj_3R_102()) + if (jj_3R_108()) return true; if (jj_scan_token(RIGHT_PAR)) return true; return false; } - private boolean jj_3R_102(){ - if (jj_3R_130()) - return true; - Token xsp; - xsp = jj_scanpos; - if (jj_3R_145()) - jj_scanpos = xsp; - return false; - } - - private boolean jj_3R_80(){ + private boolean jj_3R_87(){ if (jj_scan_token(POWER)) return true; if (jj_scan_token(LEFT_PAR)) return true; - if (jj_3R_102()) + if (jj_3R_108()) return true; if (jj_scan_token(COMMA)) return true; - if (jj_3R_102()) + if (jj_3R_108()) return true; if (jj_scan_token(RIGHT_PAR)) return true; return false; } - private boolean jj_3R_79(){ + private boolean jj_3R_62(){ + if (jj_3R_108()) + return true; + return false; + } + + private boolean jj_3R_86(){ if (jj_scan_token(PI)) return true; if (jj_scan_token(LEFT_PAR)) @@ -4109,153 +4106,150 @@ public class ADQLParser implements ADQLParserConstants { return false; } - private boolean jj_3R_78(){ + private boolean jj_3R_111(){ + if (jj_scan_token(RIGHT)) + return true; + return false; + } + + private boolean jj_3R_85(){ if (jj_scan_token(MOD)) return true; if (jj_scan_token(LEFT_PAR)) return true; - if (jj_3R_102()) + if (jj_3R_108()) return true; if (jj_scan_token(COMMA)) return true; - if (jj_3R_102()) + if (jj_3R_108()) return true; if (jj_scan_token(RIGHT_PAR)) return true; return false; } - private boolean jj_3R_59(){ - if (jj_3R_102()) - return true; - return false; - } - - private boolean jj_3R_77(){ + private boolean jj_3R_84(){ if (jj_scan_token(LOG10)) return true; if (jj_scan_token(LEFT_PAR)) return true; - if (jj_3R_102()) + if (jj_3R_108()) return true; if (jj_scan_token(RIGHT_PAR)) return true; return false; } - private boolean jj_3R_58(){ - if (jj_3R_24()) - return true; - return false; - } - - private boolean jj_3R_76(){ + private boolean jj_3R_83(){ if (jj_scan_token(LOG)) return true; if (jj_scan_token(LEFT_PAR)) return true; - if (jj_3R_102()) + if (jj_3R_108()) return true; if (jj_scan_token(RIGHT_PAR)) return true; return false; } - private boolean jj_3R_57(){ - if (jj_3R_24()) - return true; - return false; - } - - private boolean jj_3R_75(){ + private boolean jj_3R_82(){ if (jj_scan_token(FLOOR)) return true; if (jj_scan_token(LEFT_PAR)) return true; - if (jj_3R_102()) + if (jj_3R_108()) return true; if (jj_scan_token(RIGHT_PAR)) return true; return false; } - private boolean jj_3R_70(){ + private boolean jj_3R_81(){ + if (jj_scan_token(EXP)) + return true; if (jj_scan_token(LEFT_PAR)) return true; - if (jj_3R_41()) + if (jj_3R_108()) return true; if (jj_scan_token(RIGHT_PAR)) return true; return false; } - private boolean jj_3R_56(){ - if (jj_3R_102()) - return true; - return false; - } - - private boolean jj_3R_74(){ - if (jj_scan_token(EXP)) + private boolean jj_3R_80(){ + if (jj_scan_token(DEGREES)) return true; if (jj_scan_token(LEFT_PAR)) return true; - if (jj_3R_102()) + if (jj_3R_108()) return true; if (jj_scan_token(RIGHT_PAR)) return true; return false; } - private boolean jj_3R_73(){ - if (jj_scan_token(DEGREES)) - return true; + private boolean jj_3R_126(){ if (jj_scan_token(LEFT_PAR)) return true; - if (jj_3R_102()) + if (jj_3R_27()) return true; if (jj_scan_token(RIGHT_PAR)) return true; return false; } - private boolean jj_3R_69(){ - if (jj_3R_117()) + private boolean jj_3R_79(){ + if (jj_scan_token(CEILING)) + return true; + if (jj_scan_token(LEFT_PAR)) + return true; + if (jj_3R_108()) + return true; + if (jj_scan_token(RIGHT_PAR)) return true; return false; } - private boolean jj_3R_55(){ - if (jj_3R_101()) + private boolean jj_3R_125(){ + if (jj_3R_21()) return true; return false; } - private boolean jj_3R_72(){ - if (jj_scan_token(CEILING)) + private boolean jj_3R_78(){ + if (jj_scan_token(ABS)) return true; if (jj_scan_token(LEFT_PAR)) return true; - if (jj_3R_102()) + if (jj_3R_108()) return true; if (jj_scan_token(RIGHT_PAR)) return true; return false; } - private boolean jj_3R_41(){ + private boolean jj_3R_46(){ Token xsp; xsp = jj_scanpos; - if (jj_3R_55()){ + if (jj_3R_62()){ jj_scanpos = xsp; - if (jj_3R_56()){ + if (jj_3R_63()){ jj_scanpos = xsp; - if (jj_3R_57()){ + if (jj_3R_64()){ jj_scanpos = xsp; - if (jj_3R_58()){ + if (jj_3R_65()){ jj_scanpos = xsp; - if (jj_3R_59()) - return true; + if (jj_3R_66()){ + jj_scanpos = xsp; + if (jj_3R_67()){ + jj_scanpos = xsp; + if (jj_3R_68()){ + jj_scanpos = xsp; + if (jj_3R_69()) + return true; + } + } + } } } } @@ -4263,74 +4257,44 @@ public class ADQLParser implements ADQLParserConstants { return false; } - private boolean jj_3R_68(){ - if (jj_3R_23()) - return true; - return false; - } - - private boolean jj_3R_71(){ - if (jj_scan_token(ABS)) - return true; - if (jj_scan_token(LEFT_PAR)) - return true; - if (jj_3R_102()) - return true; - if (jj_scan_token(RIGHT_PAR)) - return true; - return false; - } - - private boolean jj_3R_67(){ - if (jj_3R_116()) - return true; - return false; - } - - private boolean jj_3R_108(){ - if (jj_scan_token(RIGHT)) - return true; - return false; - } - - private boolean jj_3R_66(){ - if (jj_3R_115()) + private boolean jj_3R_124(){ + if (jj_3R_22()) return true; return false; } - private boolean jj_3R_50(){ + private boolean jj_3R_57(){ Token xsp; xsp = jj_scanpos; - if (jj_3R_71()){ + if (jj_3R_78()){ jj_scanpos = xsp; - if (jj_3R_72()){ + if (jj_3R_79()){ jj_scanpos = xsp; - if (jj_3R_73()){ + if (jj_3R_80()){ jj_scanpos = xsp; - if (jj_3R_74()){ + if (jj_3R_81()){ jj_scanpos = xsp; - if (jj_3R_75()){ + if (jj_3R_82()){ jj_scanpos = xsp; - if (jj_3R_76()){ + if (jj_3R_83()){ jj_scanpos = xsp; - if (jj_3R_77()){ + if (jj_3R_84()){ jj_scanpos = xsp; - if (jj_3R_78()){ + if (jj_3R_85()){ jj_scanpos = xsp; - if (jj_3R_79()){ + if (jj_3R_86()){ jj_scanpos = xsp; - if (jj_3R_80()){ + if (jj_3R_87()){ jj_scanpos = xsp; - if (jj_3R_81()){ + if (jj_3R_88()){ jj_scanpos = xsp; - if (jj_3R_82()){ + if (jj_3R_89()){ jj_scanpos = xsp; - if (jj_3R_83()){ + if (jj_3R_90()){ jj_scanpos = xsp; - if (jj_3R_84()){ + if (jj_3R_91()){ jj_scanpos = xsp; - if (jj_3R_85()) + if (jj_3R_92()) return true; } } @@ -4349,91 +4313,113 @@ public class ADQLParser implements ADQLParserConstants { return false; } - private boolean jj_3R_179(){ - if (jj_scan_token(COMMA)) + private boolean jj_3R_121(){ + if (jj_scan_token(LEFT_PAR)) return true; - if (jj_3R_14()) + if (jj_3R_108()) return true; - return false; - } - - private boolean jj_3R_36(){ - if (jj_3R_20()) + if (jj_scan_token(RIGHT_PAR)) return true; return false; } - private boolean jj_3R_35(){ - if (jj_3R_52()) + private boolean jj_3R_120(){ + if (jj_3R_143()) return true; return false; } - private boolean jj_3R_34(){ - if (jj_3R_51()) + private boolean jj_3R_41(){ + if (jj_3R_24()) return true; return false; } - private boolean jj_3R_49(){ + private boolean jj_3R_76(){ Token xsp; xsp = jj_scanpos; - if (jj_3R_66()){ + if (jj_3R_124()){ jj_scanpos = xsp; - if (jj_3R_67()){ + if (jj_3R_125()){ jj_scanpos = xsp; - if (jj_3R_68()){ - jj_scanpos = xsp; - if (jj_3R_69()){ - jj_scanpos = xsp; - if (jj_3R_70()) - return true; - } - } + if (jj_3R_126()) + return true; } } return false; } - private boolean jj_3R_104(){ - if (jj_scan_token(LEFT)) + private boolean jj_3R_40(){ + if (jj_3R_59()) return true; return false; } - private boolean jj_3R_33(){ - if (jj_3R_50()) + private boolean jj_3R_114(){ + if (jj_scan_token(RIGHT)) return true; return false; } - private boolean jj_3R_61(){ + private boolean jj_3R_119(){ + if (jj_3R_21()) + return true; + return false; + } + + private boolean jj_3R_39(){ + if (jj_3R_58()) + return true; + return false; + } + + private boolean jj_3R_118(){ + if (jj_3R_142()) + return true; + return false; + } + + private boolean jj_3R_38(){ + if (jj_3R_57()) + return true; + return false; + } + + private boolean jj_3R_23(){ Token xsp; xsp = jj_scanpos; - if (jj_3R_104()){ + if (jj_3R_38()){ jj_scanpos = xsp; - if (jj_3R_105()){ + if (jj_3R_39()){ jj_scanpos = xsp; - if (jj_3R_106()) - return true; + if (jj_3R_40()){ + jj_scanpos = xsp; + if (jj_3R_41()) + return true; + } } } - xsp = jj_scanpos; - if (jj_scan_token(25)) - jj_scanpos = xsp; return false; } - private boolean jj_3R_19(){ + private boolean jj_3R_201(){ + if (jj_scan_token(COMMA)) + return true; + if (jj_3R_14()) + return true; + return false; + } + + private boolean jj_3R_74(){ Token xsp; xsp = jj_scanpos; - if (jj_3R_33()){ + if (jj_3R_118()){ jj_scanpos = xsp; - if (jj_3R_34()){ + if (jj_3R_119()){ jj_scanpos = xsp; - if (jj_3R_35()){ + if (jj_3R_120()){ jj_scanpos = xsp; - if (jj_3R_36()) + if (jj_3R_121()) return true; } } @@ -4441,7 +4427,62 @@ public class ADQLParser implements ADQLParserConstants { return false; } - private boolean jj_3R_192(){ + private boolean jj_3R_110(){ + if (jj_scan_token(LEFT)) + return true; + return false; + } + + private boolean jj_3R_70(){ + Token xsp; + xsp = jj_scanpos; + if (jj_3R_110()){ + jj_scanpos = xsp; + if (jj_3R_111()){ + jj_scanpos = xsp; + if (jj_3R_112()) + return true; + } + } + xsp = jj_scanpos; + if (jj_scan_token(25)) + jj_scanpos = xsp; + return false; + } + + private boolean jj_3R_75(){ + if (jj_scan_token(COORDSYS)) + return true; + if (jj_scan_token(LEFT_PAR)) + return true; + if (jj_3R_122()) + return true; + if (jj_scan_token(RIGHT_PAR)) + return true; + return false; + } + + private boolean jj_3R_178(){ + if (jj_3R_21()) + return true; + return false; + } + + private boolean jj_3R_171(){ + if (jj_scan_token(COMMA)) + return true; + if (jj_3R_170()) + return true; + return false; + } + + private boolean jj_3R_176(){ + if (jj_3R_21()) + return true; + return false; + } + + private boolean jj_3R_197(){ Token xsp; xsp = jj_scanpos; if (jj_scan_token(8)){ @@ -4455,45 +4496,53 @@ public class ADQLParser implements ADQLParserConstants { private boolean jj_3R_191(){ Token xsp; xsp = jj_scanpos; - if (jj_3R_192()) + if (jj_3R_197()) jj_scanpos = xsp; if (jj_scan_token(UNSIGNED_INTEGER)) return true; return false; } - private boolean jj_3R_45(){ + private boolean jj_3R_49(){ Token xsp; xsp = jj_scanpos; if (jj_scan_token(24)){ jj_scanpos = xsp; - if (jj_3R_61()) + if (jj_3R_70()) return true; } return false; } - private boolean jj_3R_48(){ - if (jj_scan_token(COORDSYS)) + private boolean jj_3R_141(){ + if (jj_scan_token(REGION)) return true; if (jj_scan_token(LEFT_PAR)) return true; - if (jj_3R_64()) + if (jj_3R_27()) return true; if (jj_scan_token(RIGHT_PAR)) return true; return false; } - private boolean jj_3R_159(){ + private boolean jj_3R_158(){ + if (jj_scan_token(POINT)) + return true; + if (jj_scan_token(LEFT_PAR)) + return true; + if (jj_3R_169()) + return true; if (jj_scan_token(COMMA)) return true; - if (jj_3R_158()) + if (jj_3R_170()) + return true; + if (jj_scan_token(RIGHT_PAR)) return true; return false; } - private boolean jj_3R_115(){ + private boolean jj_3R_142(){ Token xsp; xsp = jj_scanpos; if (jj_scan_token(99)){ @@ -4507,13 +4556,7 @@ public class ADQLParser implements ADQLParserConstants { return false; } - private boolean jj_3R_186(){ - if (jj_3R_23()) - return true; - return false; - } - - private boolean jj_3R_178(){ + private boolean jj_3R_200(){ if (jj_scan_token(USING)) return true; if (jj_scan_token(LEFT_PAR)) @@ -4523,7 +4566,7 @@ public class ADQLParser implements ADQLParserConstants { Token xsp; while(true){ xsp = jj_scanpos; - if (jj_3R_179()){ + if (jj_3R_201()){ jj_scanpos = xsp; break; } @@ -4533,26 +4576,52 @@ public class ADQLParser implements ADQLParserConstants { return false; } - private boolean jj_3R_107(){ + private boolean jj_3R_113(){ if (jj_scan_token(LEFT)) return true; return false; } - private boolean jj_3R_184(){ - if (jj_3R_23()) + private boolean jj_3R_140(){ + if (jj_scan_token(POLYGON)) + return true; + if (jj_scan_token(LEFT_PAR)) + return true; + if (jj_3R_169()) + return true; + if (jj_scan_token(COMMA)) + return true; + if (jj_3R_170()) + return true; + if (jj_scan_token(COMMA)) + return true; + if (jj_3R_170()) + return true; + if (jj_scan_token(COMMA)) + return true; + if (jj_3R_170()) + return true; + Token xsp; + while(true){ + xsp = jj_scanpos; + if (jj_3R_171()){ + jj_scanpos = xsp; + break; + } + } + if (jj_scan_token(RIGHT_PAR)) return true; return false; } - private boolean jj_3R_62(){ + private boolean jj_3R_71(){ Token xsp; xsp = jj_scanpos; - if (jj_3R_107()){ + if (jj_3R_113()){ jj_scanpos = xsp; - if (jj_3R_108()){ + if (jj_3R_114()){ jj_scanpos = xsp; - if (jj_3R_109()) + if (jj_3R_115()) return true; } } @@ -4562,55 +4631,33 @@ public class ADQLParser implements ADQLParserConstants { return false; } - private boolean jj_3R_177(){ + private boolean jj_3R_199(){ if (jj_scan_token(ON)) return true; - if (jj_3R_152()) - return true; - return false; - } - - private boolean jj_3R_129(){ - if (jj_scan_token(REGION)) - return true; - if (jj_scan_token(LEFT_PAR)) - return true; - if (jj_3R_24()) - return true; - if (jj_scan_token(RIGHT_PAR)) + if (jj_3R_163()) return true; return false; } - private boolean jj_3R_147(){ - if (jj_scan_token(POINT)) - return true; - if (jj_scan_token(LEFT_PAR)) - return true; - if (jj_3R_157()) - return true; - if (jj_scan_token(COMMA)) - return true; + private boolean jj_3R_139(){ if (jj_3R_158()) return true; - if (jj_scan_token(RIGHT_PAR)) - return true; return false; } - private boolean jj_3R_133(){ + private boolean jj_3R_37(){ if (jj_scan_token(STRING_LITERAL)) return true; return false; } - private boolean jj_3R_116(){ + private boolean jj_3R_22(){ Token xsp; - if (jj_3R_133()) + if (jj_3R_37()) return true; while(true){ xsp = jj_scanpos; - if (jj_3R_133()){ + if (jj_3R_37()){ jj_scanpos = xsp; break; } @@ -4618,130 +4665,122 @@ public class ADQLParser implements ADQLParserConstants { return false; } - private boolean jj_3R_46(){ + private boolean jj_3R_138(){ + if (jj_scan_token(CIRCLE)) + return true; + if (jj_scan_token(LEFT_PAR)) + return true; + if (jj_3R_169()) + return true; + if (jj_scan_token(COMMA)) + return true; + if (jj_3R_170()) + return true; + if (jj_scan_token(COMMA)) + return true; + if (jj_3R_108()) + return true; + if (jj_scan_token(RIGHT_PAR)) + return true; + return false; + } + + private boolean jj_3R_50(){ Token xsp; xsp = jj_scanpos; if (jj_scan_token(24)){ jj_scanpos = xsp; - if (jj_3R_62()) + if (jj_3R_71()) return true; } return false; } - private boolean jj_3R_30(){ + private boolean jj_3R_33(){ Token xsp; xsp = jj_scanpos; - if (jj_3R_46()) + if (jj_3R_50()) jj_scanpos = xsp; if (jj_scan_token(JOIN)) return true; - if (jj_3R_47()) + if (jj_3R_51()) return true; xsp = jj_scanpos; - if (jj_3R_177()){ + if (jj_3R_199()){ jj_scanpos = xsp; - if (jj_3R_178()) + if (jj_3R_200()) return true; } return false; } - private boolean jj_3R_128(){ - if (jj_scan_token(POLYGON)) + private boolean jj_3R_137(){ + if (jj_scan_token(CENTROID)) return true; if (jj_scan_token(LEFT_PAR)) return true; - if (jj_3R_157()) - return true; - if (jj_scan_token(COMMA)) - return true; - if (jj_3R_158()) - return true; - if (jj_scan_token(COMMA)) - return true; - if (jj_3R_158()) - return true; - if (jj_scan_token(COMMA)) - return true; - if (jj_3R_158()) + if (jj_3R_122()) return true; - Token xsp; - while(true){ - xsp = jj_scanpos; - if (jj_3R_159()){ - jj_scanpos = xsp; - break; - } - } if (jj_scan_token(RIGHT_PAR)) return true; return false; } - private boolean jj_3R_29(){ + private boolean jj_3R_32(){ if (jj_scan_token(NATURAL)) return true; Token xsp; xsp = jj_scanpos; - if (jj_3R_45()) + if (jj_3R_49()) jj_scanpos = xsp; if (jj_scan_token(JOIN)) return true; - if (jj_3R_47()) + if (jj_3R_51()) return true; return false; } - private boolean jj_3R_127(){ - if (jj_3R_147()) + private boolean jj_3R_136(){ + if (jj_scan_token(BOX)) return true; - return false; - } - - private boolean jj_3R_171(){ - Token xsp; - xsp = jj_scanpos; - if (jj_scan_token(22)) - jj_scanpos = xsp; - if (jj_3R_14()) + if (jj_scan_token(LEFT_PAR)) return true; - return false; - } - - private boolean jj_3R_126(){ - if (jj_scan_token(CIRCLE)) + if (jj_3R_169()) return true; - if (jj_scan_token(LEFT_PAR)) + if (jj_scan_token(COMMA)) return true; - if (jj_3R_157()) + if (jj_3R_170()) return true; if (jj_scan_token(COMMA)) return true; - if (jj_3R_158()) + if (jj_3R_108()) return true; if (jj_scan_token(COMMA)) return true; - if (jj_3R_102()) + if (jj_3R_108()) return true; if (jj_scan_token(RIGHT_PAR)) return true; return false; } - private boolean jj_3R_125(){ - if (jj_scan_token(CENTROID)) - return true; - if (jj_scan_token(LEFT_PAR)) - return true; - if (jj_3R_64()) + private boolean jj_3R_192(){ + Token xsp; + xsp = jj_scanpos; + if (jj_scan_token(22)) + jj_scanpos = xsp; + if (jj_3R_14()) return true; - if (jj_scan_token(RIGHT_PAR)) + return false; + } + + private boolean jj_3R_182(){ + if (jj_3R_21()) return true; return false; } - private boolean jj_3R_169(){ + private boolean jj_3R_190(){ Token xsp; xsp = jj_scanpos; if (jj_scan_token(45)){ @@ -4752,26 +4791,55 @@ public class ADQLParser implements ADQLParserConstants { return false; } - private boolean jj_3R_124(){ - if (jj_scan_token(BOX)) - return true; - if (jj_scan_token(LEFT_PAR)) - return true; - if (jj_3R_157()) + private boolean jj_3R_183(){ + if (jj_3R_46()) return true; - if (jj_scan_token(COMMA)) + return false; + } + + private boolean jj_3R_180(){ + if (jj_3R_21()) return true; + return false; + } + + private boolean jj_3R_109(){ + Token xsp; + xsp = jj_scanpos; + if (jj_3R_136()){ + jj_scanpos = xsp; + if (jj_3R_137()){ + jj_scanpos = xsp; + if (jj_3R_138()){ + jj_scanpos = xsp; + if (jj_3R_139()){ + jj_scanpos = xsp; + if (jj_3R_140()){ + jj_scanpos = xsp; + if (jj_3R_141()) + return true; + } + } + } + } + } + return false; + } + + private boolean jj_3R_181(){ if (jj_3R_158()) return true; - if (jj_scan_token(COMMA)) - return true; - if (jj_3R_102()) - return true; - if (jj_scan_token(COMMA)) - return true; - if (jj_3R_102()) + return false; + } + + private boolean jj_3R_177(){ + if (jj_3R_158()) return true; - if (jj_scan_token(RIGHT_PAR)) + return false; + } + + private boolean jj_3R_175(){ + if (jj_3R_158()) return true; return false; } @@ -4779,39 +4847,45 @@ public class ADQLParser implements ADQLParserConstants { private boolean jj_3R_17(){ Token xsp; xsp = jj_scanpos; - if (jj_3R_29()){ + if (jj_3R_32()){ jj_scanpos = xsp; - if (jj_3R_30()) + if (jj_3R_33()) return true; } return false; } - private boolean jj_3R_176(){ + private boolean jj_3R_169(){ + if (jj_3R_27()) + return true; + return false; + } + + private boolean jj_3R_198(){ if (jj_3R_17()) return true; return false; } - private boolean jj_3R_111(){ + private boolean jj_3R_117(){ if (jj_scan_token(LEFT_PAR)) return true; - if (jj_3R_172()) + if (jj_3R_193()) return true; if (jj_scan_token(RIGHT_PAR)) return true; return false; } - private boolean jj_3R_172(){ - if (jj_3R_63()) + private boolean jj_3R_193(){ + if (jj_3R_72()) return true; Token xsp; - if (jj_3R_176()) + if (jj_3R_198()) return true; while(true){ xsp = jj_scanpos; - if (jj_3R_176()){ + if (jj_3R_198()){ jj_scanpos = xsp; break; } @@ -4819,59 +4893,30 @@ public class ADQLParser implements ADQLParserConstants { return false; } - private boolean jj_3R_190(){ - if (jj_3R_23()) + private boolean jj_3R_179(){ + if (jj_3R_158()) return true; return false; } private boolean jj_3_3(){ - if (jj_3R_17()) - return true; - return false; - } - - private boolean jj_3R_101(){ - Token xsp; - xsp = jj_scanpos; - if (jj_3R_124()){ - jj_scanpos = xsp; - if (jj_3R_125()){ - jj_scanpos = xsp; - if (jj_3R_126()){ - jj_scanpos = xsp; - if (jj_3R_127()){ - jj_scanpos = xsp; - if (jj_3R_128()){ - jj_scanpos = xsp; - if (jj_3R_129()) - return true; - } - } - } - } - } - return false; - } - - private boolean jj_3R_149(){ - if (jj_3R_41()) + if (jj_3R_17()) return true; return false; } - private boolean jj_3R_110(){ - if (jj_3R_103()) + private boolean jj_3R_116(){ + if (jj_3R_77()) return true; Token xsp; xsp = jj_scanpos; - if (jj_3R_171()) + if (jj_3R_192()) jj_scanpos = xsp; return false; } - private boolean jj_3R_47(){ - if (jj_3R_63()) + private boolean jj_3R_51(){ + if (jj_3R_72()) return true; Token xsp; while(true){ @@ -4884,18 +4929,6 @@ public class ADQLParser implements ADQLParserConstants { return false; } - private boolean jj_3R_188(){ - if (jj_3R_23()) - return true; - return false; - } - - private boolean jj_3R_185(){ - if (jj_3R_147()) - return true; - return false; - } - private boolean jj_3_2(){ if (jj_3R_16()) return true; @@ -4908,62 +4941,24 @@ public class ADQLParser implements ADQLParserConstants { return false; } - private boolean jj_3R_183(){ - if (jj_3R_147()) - return true; - return false; - } - - private boolean jj_3R_189(){ - if (jj_3R_147()) - return true; - return false; - } - - private boolean jj_3R_157(){ - if (jj_3R_24()) - return true; - return false; - } - - private boolean jj_3R_187(){ - if (jj_3R_147()) - return true; - return false; - } - - private boolean jj_3R_63(){ - Token xsp; - xsp = jj_scanpos; - if (jj_3R_110()){ - jj_scanpos = xsp; - if (jj_3_2()){ - jj_scanpos = xsp; - if (jj_3R_111()) - return true; - } - } - return false; - } - - private boolean jj_3R_98(){ + private boolean jj_3R_105(){ if (jj_scan_token(DISTANCE)) return true; if (jj_scan_token(LEFT_PAR)) return true; Token xsp; xsp = jj_scanpos; - if (jj_3R_187()){ + if (jj_3R_179()){ jj_scanpos = xsp; - if (jj_3R_188()) + if (jj_3R_180()) return true; } if (jj_scan_token(COMMA)) return true; xsp = jj_scanpos; - if (jj_3R_189()){ + if (jj_3R_181()){ jj_scanpos = xsp; - if (jj_3R_190()) + if (jj_3R_182()) return true; } if (jj_scan_token(RIGHT_PAR)) @@ -4971,16 +4966,16 @@ public class ADQLParser implements ADQLParserConstants { return false; } - private boolean jj_3R_97(){ + private boolean jj_3R_104(){ if (jj_scan_token(COORD2)) return true; if (jj_scan_token(LEFT_PAR)) return true; Token xsp; xsp = jj_scanpos; - if (jj_3R_185()){ + if (jj_3R_177()){ jj_scanpos = xsp; - if (jj_3R_186()) + if (jj_3R_178()) return true; } if (jj_scan_token(RIGHT_PAR)) @@ -4988,16 +4983,16 @@ public class ADQLParser implements ADQLParserConstants { return false; } - private boolean jj_3R_96(){ + private boolean jj_3R_103(){ if (jj_scan_token(COORD1)) return true; if (jj_scan_token(LEFT_PAR)) return true; Token xsp; xsp = jj_scanpos; - if (jj_3R_183()){ + if (jj_3R_175()){ jj_scanpos = xsp; - if (jj_3R_184()) + if (jj_3R_176()) return true; } if (jj_scan_token(RIGHT_PAR)) @@ -5005,39 +5000,33 @@ public class ADQLParser implements ADQLParserConstants { return false; } - private boolean jj_3R_95(){ + private boolean jj_3R_102(){ if (jj_scan_token(AREA)) return true; if (jj_scan_token(LEFT_PAR)) return true; - if (jj_3R_64()) + if (jj_3R_122()) return true; if (jj_scan_token(RIGHT_PAR)) return true; return false; } - private boolean jj_3R_168(){ - if (jj_3R_42()) - return true; - return false; - } - - private boolean jj_3R_155(){ + private boolean jj_3R_72(){ Token xsp; xsp = jj_scanpos; - if (jj_3R_168()){ + if (jj_3R_116()){ jj_scanpos = xsp; - if (jj_scan_token(101)) - return true; + if (jj_3_2()){ + jj_scanpos = xsp; + if (jj_3R_117()) + return true; + } } - xsp = jj_scanpos; - if (jj_3R_169()) - jj_scanpos = xsp; return false; } - private boolean jj_3R_94(){ + private boolean jj_3R_101(){ Token xsp; xsp = jj_scanpos; if (jj_scan_token(58)){ @@ -5047,62 +5036,57 @@ public class ADQLParser implements ADQLParserConstants { } if (jj_scan_token(LEFT_PAR)) return true; - if (jj_3R_64()) + if (jj_3R_122()) return true; if (jj_scan_token(COMMA)) return true; - if (jj_3R_64()) + if (jj_3R_122()) return true; if (jj_scan_token(RIGHT_PAR)) return true; return false; } - private boolean jj_3R_146(){ + private boolean jj_3R_157(){ if (jj_scan_token(COMMA)) return true; - if (jj_3R_41()) + if (jj_3R_46()) return true; return false; } - private boolean jj_3R_167(){ - if (jj_3R_42()) + private boolean jj_3R_189(){ + if (jj_3R_36()) return true; return false; } - private boolean jj_3R_153(){ + private boolean jj_3R_166(){ Token xsp; xsp = jj_scanpos; - if (jj_3R_167()){ + if (jj_3R_189()){ jj_scanpos = xsp; if (jj_scan_token(101)) return true; } + xsp = jj_scanpos; + if (jj_3R_190()) + jj_scanpos = xsp; return false; } - private boolean jj_3R_60(){ - if (jj_scan_token(DOT)) - return true; - if (jj_3R_103()) - return true; - return false; - } - - private boolean jj_3R_52(){ + private boolean jj_3R_59(){ Token xsp; xsp = jj_scanpos; - if (jj_3R_94()){ + if (jj_3R_101()){ jj_scanpos = xsp; - if (jj_3R_95()){ + if (jj_3R_102()){ jj_scanpos = xsp; - if (jj_3R_96()){ + if (jj_3R_103()){ jj_scanpos = xsp; - if (jj_3R_97()){ + if (jj_3R_104()){ jj_scanpos = xsp; - if (jj_3R_98()) + if (jj_3R_105()) return true; } } @@ -5111,7 +5095,7 @@ public class ADQLParser implements ADQLParserConstants { return false; } - private boolean jj_3R_135(){ + private boolean jj_3R_160(){ Token xsp; xsp = jj_scanpos; if (jj_scan_token(47)){ @@ -5130,30 +5114,24 @@ public class ADQLParser implements ADQLParserConstants { xsp = jj_scanpos; if (jj_scan_token(19)) jj_scanpos = xsp; - if (jj_3R_41()) + if (jj_3R_46()) return true; if (jj_scan_token(RIGHT_PAR)) return true; return false; } - private boolean jj_3R_158(){ - if (jj_3R_102()) + private boolean jj_3R_170(){ + if (jj_3R_108()) return true; if (jj_scan_token(COMMA)) return true; - if (jj_3R_102()) - return true; - return false; - } - - private boolean jj_3R_23(){ - if (jj_3R_42()) + if (jj_3R_108()) return true; return false; } - private boolean jj_3R_134(){ + private boolean jj_3R_159(){ if (jj_scan_token(COUNT)) return true; if (jj_scan_token(LEFT_PAR)) @@ -5165,7 +5143,7 @@ public class ADQLParser implements ADQLParserConstants { xsp = jj_scanpos; if (jj_scan_token(10)){ jj_scanpos = xsp; - if (jj_3R_149()) + if (jj_3R_183()) return true; } if (jj_scan_token(RIGHT_PAR)) @@ -5173,77 +5151,83 @@ public class ADQLParser implements ADQLParserConstants { return false; } - private boolean jj_3R_42(){ - if (jj_3R_14()) + private boolean jj_3R_188(){ + if (jj_3R_36()) return true; - Token xsp; - xsp = jj_scanpos; - if (jj_3R_60()) - jj_scanpos = xsp; return false; } - private boolean jj_3R_132(){ - if (jj_scan_token(DOT)) - return true; - if (jj_3R_14()) - return true; + private boolean jj_3R_164(){ + Token xsp; + xsp = jj_scanpos; + if (jj_3R_188()){ + jj_scanpos = xsp; + if (jj_scan_token(101)) + return true; + } return false; } - private boolean jj_3R_131(){ + private boolean jj_3R_56(){ if (jj_scan_token(DOT)) return true; - if (jj_3R_14()) + if (jj_3R_77()) return true; return false; } - private boolean jj_3R_117(){ + private boolean jj_3R_143(){ Token xsp; xsp = jj_scanpos; - if (jj_3R_134()){ + if (jj_3R_159()){ jj_scanpos = xsp; - if (jj_3R_135()) + if (jj_3R_160()) return true; } return false; } - private boolean jj_3R_103(){ + private boolean jj_3R_21(){ + if (jj_3R_36()) + return true; + return false; + } + + private boolean jj_3R_36(){ if (jj_3R_14()) return true; Token xsp; xsp = jj_scanpos; - if (jj_3R_131()) - jj_scanpos = xsp; - xsp = jj_scanpos; - if (jj_3R_132()) + if (jj_3R_56()) jj_scanpos = xsp; return false; } - private boolean jj_3R_26(){ - if (jj_scan_token(DELIMITED_IDENTIFIER)) + private boolean jj_3R_128(){ + if (jj_scan_token(DOT)) + return true; + if (jj_3R_14()) return true; return false; } - private boolean jj_3R_25(){ - if (jj_scan_token(REGULAR_IDENTIFIER)) + private boolean jj_3R_127(){ + if (jj_scan_token(DOT)) + return true; + if (jj_3R_14()) return true; return false; } - private boolean jj_3R_123(){ + private boolean jj_3R_134(){ if (jj_scan_token(LEFT_PAR)) return true; - if (jj_3R_41()) + if (jj_3R_46()) return true; Token xsp; while(true){ xsp = jj_scanpos; - if (jj_3R_146()){ + if (jj_3R_157()){ jj_scanpos = xsp; break; } @@ -5253,24 +5237,13 @@ public class ADQLParser implements ADQLParserConstants { return false; } - private boolean jj_3R_14(){ - Token xsp; - xsp = jj_scanpos; - if (jj_3R_25()){ - jj_scanpos = xsp; - if (jj_3R_26()) - return true; - } - return false; - } - - private boolean jj_3_13(){ + private boolean jj_3_16(){ if (jj_3R_16()) return true; return false; } - private boolean jj_3R_100(){ + private boolean jj_3R_107(){ Token xsp; xsp = jj_scanpos; if (jj_scan_token(35)) @@ -5278,124 +5251,80 @@ public class ADQLParser implements ADQLParserConstants { if (jj_scan_token(IN)) return true; xsp = jj_scanpos; - if (jj_3_13()){ + if (jj_3_16()){ jj_scanpos = xsp; - if (jj_3R_123()) + if (jj_3R_134()) return true; } return false; } - private boolean jj_3R_156(){ - if (jj_scan_token(COMMA)) - return true; - if (jj_3R_155()) - return true; - return false; - } - - private boolean jj_3R_144(){ - if (jj_scan_token(ORDER_BY)) - return true; - if (jj_3R_155()) + private boolean jj_3R_77(){ + if (jj_3R_14()) return true; Token xsp; - while(true){ - xsp = jj_scanpos; - if (jj_3R_156()){ - jj_scanpos = xsp; - break; - } - } + xsp = jj_scanpos; + if (jj_3R_127()) + jj_scanpos = xsp; + xsp = jj_scanpos; + if (jj_3R_128()) + jj_scanpos = xsp; return false; } - private boolean jj_3R_143(){ - if (jj_scan_token(HAVING)) - return true; - if (jj_3R_152()) + private boolean jj_3R_29(){ + if (jj_scan_token(DELIMITED_IDENTIFIER)) return true; return false; } - private boolean jj_3R_154(){ - if (jj_scan_token(COMMA)) - return true; - if (jj_3R_153()) + private boolean jj_3R_28(){ + if (jj_scan_token(REGULAR_IDENTIFIER)) return true; return false; } - private boolean jj_3R_22(){ + private boolean jj_3R_26(){ Token xsp; xsp = jj_scanpos; if (jj_scan_token(35)) jj_scanpos = xsp; if (jj_scan_token(BETWEEN)) return true; - if (jj_3R_41()) + if (jj_3R_46()) return true; if (jj_scan_token(AND)) return true; - if (jj_3R_41()) + if (jj_3R_46()) return true; return false; } - private boolean jj_3R_163(){ - if (jj_scan_token(AS)) - return true; - if (jj_3R_14()) + private boolean jj_3R_61(){ + if (jj_3R_107()) return true; return false; } - private boolean jj_3R_142(){ - if (jj_scan_token(GROUP_BY)) - return true; - if (jj_3R_153()) - return true; + private boolean jj_3R_14(){ Token xsp; - while(true){ - xsp = jj_scanpos; - if (jj_3R_154()){ - jj_scanpos = xsp; - break; - } - } - return false; - } - - private boolean jj_3R_54(){ - if (jj_3R_100()) - return true; - return false; - } - - private boolean jj_3_10(){ - if (jj_3R_22()) - return true; - return false; - } - - private boolean jj_3R_140(){ - if (jj_scan_token(COMMA)) - return true; - if (jj_3R_47()) - return true; + xsp = jj_scanpos; + if (jj_3R_28()){ + jj_scanpos = xsp; + if (jj_3R_29()) + return true; + } return false; } - private boolean jj_3R_141(){ - if (jj_scan_token(WHERE)) - return true; - if (jj_3R_152()) + private boolean jj_3_13(){ + if (jj_3R_26()) return true; return false; } - private boolean jj_3_12(){ - if (jj_3R_24()) + private boolean jj_3_15(){ + if (jj_3R_27()) return true; Token xsp; xsp = jj_scanpos; @@ -5406,21 +5335,29 @@ public class ADQLParser implements ADQLParserConstants { return false; } - private boolean jj_3R_53(){ - if (jj_3R_99()) + private boolean jj_3R_60(){ + if (jj_3R_106()) return true; return false; } - private boolean jj_3_11(){ - if (jj_3R_23()) + private boolean jj_3R_167(){ + if (jj_scan_token(COMMA)) + return true; + if (jj_3R_166()) + return true; + return false; + } + + private boolean jj_3_14(){ + if (jj_3R_21()) return true; if (jj_scan_token(IS)) return true; return false; } - private boolean jj_3R_99(){ + private boolean jj_3R_106(){ Token xsp; xsp = jj_scanpos; if (jj_scan_token(12)){ @@ -5440,28 +5377,20 @@ public class ADQLParser implements ADQLParserConstants { } } } - if (jj_3R_41()) - return true; - return false; - } - - private boolean jj_3R_27(){ - if (jj_3R_14()) - return true; - if (jj_scan_token(DOT)) + if (jj_3R_46()) return true; return false; } - private boolean jj_3R_118(){ - if (jj_scan_token(FROM)) + private boolean jj_3R_155(){ + if (jj_scan_token(ORDER_BY)) return true; - if (jj_3R_47()) + if (jj_3R_166()) return true; Token xsp; while(true){ xsp = jj_scanpos; - if (jj_3R_140()){ + if (jj_3R_167()){ jj_scanpos = xsp; break; } @@ -5469,24 +5398,32 @@ public class ADQLParser implements ADQLParserConstants { return false; } - private boolean jj_3R_40(){ - if (jj_3R_41()) + private boolean jj_3R_154(){ + if (jj_scan_token(HAVING)) + return true; + if (jj_3R_163()) + return true; + return false; + } + + private boolean jj_3R_45(){ + if (jj_3R_46()) return true; Token xsp; xsp = jj_scanpos; - if (jj_3R_53()){ + if (jj_3R_60()){ jj_scanpos = xsp; - if (jj_3_10()){ + if (jj_3_13()){ jj_scanpos = xsp; - if (jj_3R_54()) + if (jj_3R_61()) return true; } } return false; } - private boolean jj_3R_39(){ - if (jj_3R_24()) + private boolean jj_3R_44(){ + if (jj_3R_27()) return true; Token xsp; xsp = jj_scanpos; @@ -5494,13 +5431,21 @@ public class ADQLParser implements ADQLParserConstants { jj_scanpos = xsp; if (jj_scan_token(LIKE)) return true; - if (jj_3R_24()) + if (jj_3R_27()) return true; return false; } - private boolean jj_3R_38(){ - if (jj_3R_23()) + private boolean jj_3R_165(){ + if (jj_scan_token(COMMA)) + return true; + if (jj_3R_164()) + return true; + return false; + } + + private boolean jj_3R_43(){ + if (jj_3R_21()) return true; if (jj_scan_token(IS)) return true; @@ -5513,7 +5458,31 @@ public class ADQLParser implements ADQLParserConstants { return false; } - private boolean jj_3R_37(){ + private boolean jj_3R_184(){ + if (jj_scan_token(AS)) + return true; + if (jj_3R_14()) + return true; + return false; + } + + private boolean jj_3R_153(){ + if (jj_scan_token(GROUP_BY)) + return true; + if (jj_3R_164()) + return true; + Token xsp; + while(true){ + xsp = jj_scanpos; + if (jj_3R_165()){ + jj_scanpos = xsp; + break; + } + } + return false; + } + + private boolean jj_3R_42(){ if (jj_scan_token(EXISTS)) return true; if (jj_3R_16()) @@ -5522,37 +5491,39 @@ public class ADQLParser implements ADQLParserConstants { } private boolean jj_3R_151(){ - if (jj_3R_41()) + if (jj_scan_token(COMMA)) + return true; + if (jj_3R_51()) + return true; + return false; + } + + private boolean jj_3R_152(){ + if (jj_scan_token(WHERE)) return true; - Token xsp; - xsp = jj_scanpos; if (jj_3R_163()) - jj_scanpos = xsp; + return true; return false; } - private boolean jj_3R_15(){ + private boolean jj_3R_30(){ if (jj_3R_14()) return true; if (jj_scan_token(DOT)) return true; - Token xsp; - xsp = jj_scanpos; - if (jj_3R_27()) - jj_scanpos = xsp; return false; } - private boolean jj_3R_21(){ + private boolean jj_3R_25(){ Token xsp; xsp = jj_scanpos; - if (jj_3R_37()){ + if (jj_3R_42()){ jj_scanpos = xsp; - if (jj_3R_38()){ + if (jj_3R_43()){ jj_scanpos = xsp; - if (jj_3R_39()){ + if (jj_3R_44()){ jj_scanpos = xsp; - if (jj_3R_40()) + if (jj_3R_45()) return true; } } @@ -5560,150 +5531,116 @@ public class ADQLParser implements ADQLParserConstants { return false; } - private boolean jj_3_9(){ - if (jj_3R_21()) + private boolean jj_3R_129(){ + if (jj_scan_token(FROM)) return true; - return false; - } - - private boolean jj_3R_150(){ - if (jj_scan_token(ASTERISK)) + if (jj_3R_51()) return true; + Token xsp; + while(true){ + xsp = jj_scanpos; + if (jj_3R_151()){ + jj_scanpos = xsp; + break; + } + } return false; } - private boolean jj_3R_174(){ - if (jj_scan_token(LEFT_PAR)) - return true; - if (jj_3R_152()) - return true; - if (jj_scan_token(RIGHT_PAR)) + private boolean jj_3_12(){ + if (jj_3R_25()) return true; return false; } - private boolean jj_3R_173(){ - if (jj_3R_21()) + private boolean jj_3R_162(){ + if (jj_3R_46()) return true; - return false; - } - - private boolean jj_3R_165(){ Token xsp; xsp = jj_scanpos; - if (jj_3R_173()){ + if (jj_3R_184()) jj_scanpos = xsp; - if (jj_3R_174()) - return true; - } - return false; - } - - private boolean jj_3R_175(){ - if (jj_scan_token(NOT)) - return true; return false; } - private boolean jj_3_1(){ + private boolean jj_3R_15(){ if (jj_3R_14()) return true; if (jj_scan_token(DOT)) return true; Token xsp; xsp = jj_scanpos; - if (jj_3R_15()) + if (jj_3R_30()) jj_scanpos = xsp; - if (jj_scan_token(ASTERISK)) + return false; + } + + private boolean jj_3R_195(){ + if (jj_scan_token(LEFT_PAR)) + return true; + if (jj_3R_163()) + return true; + if (jj_scan_token(RIGHT_PAR)) return true; return false; } - private boolean jj_3R_166(){ - Token xsp; - xsp = jj_scanpos; - if (jj_scan_token(33)){ - jj_scanpos = xsp; - if (jj_scan_token(34)) - return true; - } - xsp = jj_scanpos; - if (jj_3R_175()) - jj_scanpos = xsp; - if (jj_3R_165()) + private boolean jj_3R_194(){ + if (jj_3R_25()) return true; return false; } - private boolean jj_3R_138(){ + private boolean jj_3R_186(){ Token xsp; xsp = jj_scanpos; - if (jj_3R_150()){ + if (jj_3R_194()){ jj_scanpos = xsp; - if (jj_3_1()){ - jj_scanpos = xsp; - if (jj_3R_151()) - return true; - } + if (jj_3R_195()) + return true; } return false; } - private boolean jj_3R_139(){ - if (jj_scan_token(COMMA)) - return true; - if (jj_3R_138()) - return true; - return false; - } - - private boolean jj_3R_114(){ - if (jj_scan_token(COMMA)) - return true; - if (jj_3R_41()) + private boolean jj_3R_196(){ + if (jj_scan_token(NOT)) return true; return false; } - private boolean jj_3R_137(){ - if (jj_scan_token(TOP)) - return true; - if (jj_scan_token(UNSIGNED_INTEGER)) + private boolean jj_3R_187(){ + Token xsp; + xsp = jj_scanpos; + if (jj_scan_token(33)){ + jj_scanpos = xsp; + if (jj_scan_token(34)) + return true; + } + xsp = jj_scanpos; + if (jj_3R_196()) + jj_scanpos = xsp; + if (jj_3R_186()) return true; return false; } - private boolean jj_3R_136(){ - if (jj_scan_token(QUANTIFIER)) + private boolean jj_3R_161(){ + if (jj_scan_token(ASTERISK)) return true; return false; } - private boolean jj_3R_164(){ - if (jj_scan_token(NOT)) + private boolean jj_3_1(){ + if (jj_3R_14()) return true; - return false; - } - - private boolean jj_3R_44(){ - if (jj_scan_token(SELECT)) + if (jj_scan_token(DOT)) return true; Token xsp; xsp = jj_scanpos; - if (jj_3R_136()) - jj_scanpos = xsp; - xsp = jj_scanpos; - if (jj_3R_137()) + if (jj_3R_15()) jj_scanpos = xsp; - if (jj_3R_138()) + if (jj_scan_token(ASTERISK)) return true; - while(true){ - xsp = jj_scanpos; - if (jj_3R_139()){ - jj_scanpos = xsp; - break; - } - } return false; } @@ -5718,7 +5655,7 @@ public class ADQLParser implements ADQLParserConstants { private Token jj_scanpos, jj_lastpos; private int jj_la; private int jj_gen; - final private int[] jj_la1 = new int[97]; + final private int[] jj_la1 = new int[98]; static private int[] jj_la1_0; static private int[] jj_la1_1; static private int[] jj_la1_2; @@ -5731,22 +5668,22 @@ public class ADQLParser implements ADQLParserConstants { } private static void jj_la1_init_0(){ - jj_la1_0 = new int[]{0x41,0x0,0x0,0x0,0x0,0x80000,0x100000,0x20,0x0,0x0,0x400000,0x400,0x304,0x20,0x20,0x20,0x0,0x10,0x10,0x10,0x0,0x0,0x0,0x0,0x400000,0x400000,0x400000,0x0,0x4,0x3d800000,0x1c000000,0x2000000,0x1d000000,0x1d000000,0x1c000000,0x2000000,0x1d000000,0x1d000000,0x20,0xc0000000,0x3d800000,0x0,0x0,0x0,0x300,0x300,0x4,0x0,0x304,0x300,0x300,0xc00,0xc00,0x300,0x300,0x4,0x80,0x0,0x4,0x0,0x0,0x0,0x0,0x0,0x4,0x0,0x0,0x3f000,0x0,0x0,0x304,0x3f000,0x0,0x0,0x20,0x4,0x80000,0x704,0x0,0x80000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x0,0x304,0x20,0x20,0x0,0x0,0x20,0x304,}; + jj_la1_0 = new int[]{0x41,0x0,0x0,0x0,0x0,0x80000,0x100000,0x20,0x0,0x0,0x400000,0x400,0x304,0x20,0x20,0x20,0x0,0x10,0x10,0x10,0x0,0x0,0x0,0x0,0x400000,0x400000,0x400000,0x0,0x4,0x3d800000,0x1c000000,0x2000000,0x1d000000,0x1d000000,0x1c000000,0x2000000,0x1d000000,0x1d000000,0x20,0xc0000000,0x3d800000,0x0,0x0,0x0,0x300,0x300,0x4,0x4,0x0,0x304,0x300,0x300,0xc00,0xc00,0x300,0x300,0x4,0x80,0x0,0x4,0x0,0x0,0x0,0x0,0x0,0x4,0x0,0x0,0x3f000,0x0,0x0,0x304,0x3f000,0x0,0x0,0x20,0x4,0x80000,0x704,0x0,0x80000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x0,0x304,0x20,0x20,0x0,0x0,0x20,0x304,}; } private static void jj_la1_init_1(){ - jj_la1_1 = new int[]{0x0,0x1,0x400,0x800,0x1000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x6000,0x6000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf8000,0x3f00000,0x7c0f8000,0x0,0x0,0x0,0x0,0x0,0x0,0xf8000,0x0,0x80000000,0xf8000,0x3f00000,0x8,0x6,0x6,0x8,0x0,0x8,0x8,0x0,0x108,0x200,0xffff8000,0x0,0x8,0x8,0x0,0x0,0x0,0xffff8000,0x78000,0x0,0xf8000,0xc000000,0x800000,0x800000,0x800000,0x800000,0x7c000000,0x0,0x3f00000,0x7c000000,0x7c0f8000,0x0,0x0,0x0,0x0,0x0,0xffff8000,}; + jj_la1_1 = new int[]{0x0,0x1,0x400,0x800,0x1000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffff8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x6000,0x6000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf8000,0x0,0x3f00000,0x7c0f8000,0x0,0x0,0x0,0x0,0x0,0x0,0xf8000,0x0,0x80000000,0x0,0x3f00000,0x8,0x6,0x6,0x8,0x0,0x8,0x8,0x0,0x108,0x200,0xffff8000,0x0,0x8,0x8,0x0,0x0,0x0,0xffff8000,0x78000,0x0,0xf8000,0xc000000,0x800000,0x800000,0x800000,0x800000,0x7c000000,0x0,0x3f00000,0x7c000000,0x7c0f8000,0x0,0x0,0x0,0x0,0x0,0xffff8000,}; } private static void jj_la1_init_2(){ - jj_la1_2 = new int[]{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20ffffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20000000,0x0,0x0,0x0,0x0,0x20000000,0x0,0x20ffffff,0x0,0x0,0x0,0x0,0x0,0x0,0x20000000,0x0,0x0,0x20000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20ffffff,0x0,0x0,0x0,0x0,0x0,0x0,0x20ffffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0xffffff,0x20ffffff,0x0,0x0,0xfffe,0xff0000,0x0,0x20ffffff,}; + jj_la1_2 = new int[]{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20ffffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20000000,0x0,0x0,0x0,0x0,0x0,0x20000000,0x0,0xffffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20ffffff,0x0,0x0,0x0,0x0,0x0,0x0,0x20ffffff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0xffffff,0xffffff,0x0,0x0,0xfffe,0xff0000,0x0,0x20ffffff,}; } private static void jj_la1_init_3(){ - jj_la1_3 = new int[]{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3,0x3,0x0,0x0,0x3b,0x0,0x0,0x0,0x3,0x0,0x0,0x0,0x23,0x23,0x0,0x0,0x0,0x3,0x0,0x3,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x38,0x30,0x0,0x0,0x3b,0x0,0x3b,0x0,0x0,0x0,0x0,0x0,0x0,0x3b,0x0,0x0,0x3b,0x3,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3b,0x0,0x0,0x0,0x0,0x0,0x0,0x3b,0x0,0x0,0x0,0x0,0x3,0x3,0x3,0x3,0x0,0x0,0x0,0x2,0x3b,0x0,0x0,0x0,0x0,0x0,0x3b,}; + jj_la1_3 = new int[]{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3,0x3,0x0,0x0,0x3b,0x0,0x0,0x0,0x3,0x0,0x0,0x0,0x23,0x23,0x0,0x0,0x0,0x3,0x0,0x3,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x38,0x30,0x0,0x0,0x3b,0x3,0x0,0x3b,0x0,0x0,0x0,0x0,0x0,0x0,0x3b,0x0,0x0,0x3,0x3,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3b,0x0,0x0,0x0,0x0,0x0,0x0,0x3b,0x0,0x0,0x0,0x0,0x3,0x3,0x3,0x3,0x0,0x0,0x0,0x2,0x3b,0x0,0x0,0x0,0x0,0x0,0x3b,}; } - final private JJCalls[] jj_2_rtns = new JJCalls[13]; + final private JJCalls[] jj_2_rtns = new JJCalls[16]; private boolean jj_rescan = false; private int jj_gc = 0; @@ -5766,7 +5703,7 @@ public class ADQLParser implements ADQLParserConstants { token = new Token(); jj_ntk = -1; jj_gen = 0; - for(int i = 0; i < 97; i++) + for(int i = 0; i < 98; i++) jj_la1[i] = -1; for(int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); @@ -5788,7 +5725,7 @@ public class ADQLParser implements ADQLParserConstants { token = new Token(); jj_ntk = -1; jj_gen = 0; - for(int i = 0; i < 97; i++) + for(int i = 0; i < 98; i++) jj_la1[i] = -1; for(int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); @@ -5801,7 +5738,7 @@ public class ADQLParser implements ADQLParserConstants { token = new Token(); jj_ntk = -1; jj_gen = 0; - for(int i = 0; i < 97; i++) + for(int i = 0; i < 98; i++) jj_la1[i] = -1; for(int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); @@ -5814,7 +5751,7 @@ public class ADQLParser implements ADQLParserConstants { token = new Token(); jj_ntk = -1; jj_gen = 0; - for(int i = 0; i < 97; i++) + for(int i = 0; i < 98; i++) jj_la1[i] = -1; for(int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); @@ -5826,7 +5763,7 @@ public class ADQLParser implements ADQLParserConstants { token = new Token(); jj_ntk = -1; jj_gen = 0; - for(int i = 0; i < 97; i++) + for(int i = 0; i < 98; i++) jj_la1[i] = -1; for(int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); @@ -5838,7 +5775,7 @@ public class ADQLParser implements ADQLParserConstants { token = new Token(); jj_ntk = -1; jj_gen = 0; - for(int i = 0; i < 97; i++) + for(int i = 0; i < 98; i++) jj_la1[i] = -1; for(int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); @@ -5864,7 +5801,6 @@ public class ADQLParser implements ADQLParserConstants { } } } - trace_token(token, ""); return token; } token = oldToken; @@ -5912,7 +5848,6 @@ public class ADQLParser implements ADQLParserConstants { token = token.next = token_source.getNextToken(); jj_ntk = -1; jj_gen++; - trace_token(token, " (in getNextToken)"); return token; } @@ -5976,7 +5911,7 @@ public class ADQLParser implements ADQLParserConstants { la1tokens[jj_kind] = true; jj_kind = -1; } - for(int i = 0; i < 97; i++){ + for(int i = 0; i < 98; i++){ if (jj_la1[i] == jj_gen){ for(int j = 0; j < 32; j++){ if ((jj_la1_0[i] & (1 << j)) != 0){ @@ -6011,68 +5946,15 @@ public class ADQLParser implements ADQLParserConstants { return new ParseException(token, exptokseq, tokenImage); } - private int trace_indent = 0; - private boolean trace_enabled = true; - /** Enable tracing. */ - final public void enable_tracing(){ - trace_enabled = true; - } + final public void enable_tracing(){} /** Disable tracing. */ - final public void disable_tracing(){ - trace_enabled = false; - } - - private void trace_call(String s){ - if (trace_enabled){ - for(int i = 0; i < trace_indent; i++){ - System.out.print(" "); - } - System.out.println("Call: " + s); - } - trace_indent = trace_indent + 2; - } - - private void trace_return(String s){ - trace_indent = trace_indent - 2; - if (trace_enabled){ - for(int i = 0; i < trace_indent; i++){ - System.out.print(" "); - } - System.out.println("Return: " + s); - } - } - - private void trace_token(Token t, String where){ - if (trace_enabled){ - for(int i = 0; i < trace_indent; i++){ - System.out.print(" "); - } - System.out.print("Consumed token: <" + tokenImage[t.kind]); - if (t.kind != 0 && !tokenImage[t.kind].equals("\"" + t.image + "\"")){ - System.out.print(": \"" + t.image + "\""); - } - System.out.println(" at line " + t.beginLine + " column " + t.beginColumn + ">" + where); - } - } - - private void trace_scan(Token t1, int t2){ - if (trace_enabled){ - for(int i = 0; i < trace_indent; i++){ - System.out.print(" "); - } - System.out.print("Visited token: <" + tokenImage[t1.kind]); - if (t1.kind != 0 && !tokenImage[t1.kind].equals("\"" + t1.image + "\"")){ - System.out.print(": \"" + t1.image + "\""); - } - System.out.println(" at line " + t1.beginLine + " column " + t1.beginColumn + ">; Expected token: <" + tokenImage[t2] + ">"); - } - } + final public void disable_tracing(){} private void jj_rescan_token(){ jj_rescan = true; - for(int i = 0; i < 13; i++){ + for(int i = 0; i < 16; i++){ try{ JJCalls p = jj_2_rtns[i]; do{ @@ -6119,6 +6001,15 @@ public class ADQLParser implements ADQLParserConstants { case 12: jj_3_13(); break; + case 13: + jj_3_14(); + break; + case 14: + jj_3_15(); + break; + case 15: + jj_3_16(); + break; } } p = p.next; diff --git a/src/adql/parser/ADQLParserConstants.java b/src/adql/parser/ADQLParserConstants.java index cf75565a791da7dda1c52e7a91f37ac6498c5a89..e69af55581bc59a5c723daf82e5f639616ced299 100644 --- a/src/adql/parser/ADQLParserConstants.java +++ b/src/adql/parser/ADQLParserConstants.java @@ -1,213 +1,318 @@ /* Generated By:JavaCC: Do not edit this line. ADQLParserConstants.java */ package adql.parser; + /** * Token literal values and constants. * Generated by org.javacc.parser.OtherFilesGen#start() */ public interface ADQLParserConstants { - /** End of File. */ - int EOF = 0; - /** RegularExpression Id. */ - int LEFT_PAR = 2; - /** RegularExpression Id. */ - int RIGHT_PAR = 3; - /** RegularExpression Id. */ - int DOT = 4; - /** RegularExpression Id. */ - int COMMA = 5; - /** RegularExpression Id. */ - int EOQ = 6; - /** RegularExpression Id. */ - int CONCAT = 7; - /** RegularExpression Id. */ - int PLUS = 8; - /** RegularExpression Id. */ - int MINUS = 9; - /** RegularExpression Id. */ - int ASTERISK = 10; - /** RegularExpression Id. */ - int DIVIDE = 11; - /** RegularExpression Id. */ - int EQUAL = 12; - /** RegularExpression Id. */ - int NOT_EQUAL = 13; - /** RegularExpression Id. */ - int LESS_THAN = 14; - /** RegularExpression Id. */ - int LESS_EQUAL_THAN = 15; - /** RegularExpression Id. */ - int GREATER_THAN = 16; - /** RegularExpression Id. */ - int GREATER_EQUAL_THAN = 17; - /** RegularExpression Id. */ - int SELECT = 18; - /** RegularExpression Id. */ - int QUANTIFIER = 19; - /** RegularExpression Id. */ - int TOP = 20; - /** RegularExpression Id. */ - int FROM = 21; - /** RegularExpression Id. */ - int AS = 22; - /** RegularExpression Id. */ - int NATURAL = 23; - /** RegularExpression Id. */ - int INNER = 24; - /** RegularExpression Id. */ - int OUTER = 25; - /** RegularExpression Id. */ - int RIGHT = 26; - /** RegularExpression Id. */ - int LEFT = 27; - /** RegularExpression Id. */ - int FULL = 28; - /** RegularExpression Id. */ - int JOIN = 29; - /** RegularExpression Id. */ - int ON = 30; - /** RegularExpression Id. */ - int USING = 31; - /** RegularExpression Id. */ - int WHERE = 32; - /** RegularExpression Id. */ - int AND = 33; - /** RegularExpression Id. */ - int OR = 34; - /** RegularExpression Id. */ - int NOT = 35; - /** RegularExpression Id. */ - int IS = 36; - /** RegularExpression Id. */ - int NULL = 37; - /** RegularExpression Id. */ - int BETWEEN = 38; - /** RegularExpression Id. */ - int LIKE = 39; - /** RegularExpression Id. */ - int IN = 40; - /** RegularExpression Id. */ - int EXISTS = 41; - /** RegularExpression Id. */ - int GROUP_BY = 42; - /** RegularExpression Id. */ - int HAVING = 43; - /** RegularExpression Id. */ - int ORDER_BY = 44; - /** RegularExpression Id. */ - int ASC = 45; - /** RegularExpression Id. */ - int DESC = 46; - /** RegularExpression Id. */ - int AVG = 47; - /** RegularExpression Id. */ - int MAX = 48; - /** RegularExpression Id. */ - int MIN = 49; - /** RegularExpression Id. */ - int SUM = 50; - /** RegularExpression Id. */ - int COUNT = 51; - /** RegularExpression Id. */ - int BOX = 52; - /** RegularExpression Id. */ - int CENTROID = 53; - /** RegularExpression Id. */ - int CIRCLE = 54; - /** RegularExpression Id. */ - int POINT = 55; - /** RegularExpression Id. */ - int POLYGON = 56; - /** RegularExpression Id. */ - int REGION = 57; - /** RegularExpression Id. */ - int CONTAINS = 58; - /** RegularExpression Id. */ - int INTERSECTS = 59; - /** RegularExpression Id. */ - int AREA = 60; - /** RegularExpression Id. */ - int COORD1 = 61; - /** RegularExpression Id. */ - int COORD2 = 62; - /** RegularExpression Id. */ - int COORDSYS = 63; - /** RegularExpression Id. */ - int DISTANCE = 64; - /** RegularExpression Id. */ - int ABS = 65; - /** RegularExpression Id. */ - int CEILING = 66; - /** RegularExpression Id. */ - int DEGREES = 67; - /** RegularExpression Id. */ - int EXP = 68; - /** RegularExpression Id. */ - int FLOOR = 69; - /** RegularExpression Id. */ - int LOG = 70; - /** RegularExpression Id. */ - int LOG10 = 71; - /** RegularExpression Id. */ - int MOD = 72; - /** RegularExpression Id. */ - int PI = 73; - /** RegularExpression Id. */ - int POWER = 74; - /** RegularExpression Id. */ - int RADIANS = 75; - /** RegularExpression Id. */ - int RAND = 76; - /** RegularExpression Id. */ - int ROUND = 77; - /** RegularExpression Id. */ - int SQRT = 78; - /** RegularExpression Id. */ - int TRUNCATE = 79; - /** RegularExpression Id. */ - int ACOS = 80; - /** RegularExpression Id. */ - int ASIN = 81; - /** RegularExpression Id. */ - int ATAN = 82; - /** RegularExpression Id. */ - int ATAN2 = 83; - /** RegularExpression Id. */ - int COS = 84; - /** RegularExpression Id. */ - int COT = 85; - /** RegularExpression Id. */ - int SIN = 86; - /** RegularExpression Id. */ - int TAN = 87; - /** RegularExpression Id. */ - int STRING_LITERAL = 93; - /** RegularExpression Id. */ - int DELIMITED_IDENTIFIER = 96; - /** RegularExpression Id. */ - int REGULAR_IDENTIFIER = 97; - /** RegularExpression Id. */ - int Letter = 98; - /** RegularExpression Id. */ - int SCIENTIFIC_NUMBER = 99; - /** RegularExpression Id. */ - int UNSIGNED_FLOAT = 100; - /** RegularExpression Id. */ - int UNSIGNED_INTEGER = 101; - /** RegularExpression Id. */ - int DIGIT = 102; + /** End of File. */ + int EOF = 0; + /** RegularExpression Id. */ + int LEFT_PAR = 2; + /** RegularExpression Id. */ + int RIGHT_PAR = 3; + /** RegularExpression Id. */ + int DOT = 4; + /** RegularExpression Id. */ + int COMMA = 5; + /** RegularExpression Id. */ + int EOQ = 6; + /** RegularExpression Id. */ + int CONCAT = 7; + /** RegularExpression Id. */ + int PLUS = 8; + /** RegularExpression Id. */ + int MINUS = 9; + /** RegularExpression Id. */ + int ASTERISK = 10; + /** RegularExpression Id. */ + int DIVIDE = 11; + /** RegularExpression Id. */ + int EQUAL = 12; + /** RegularExpression Id. */ + int NOT_EQUAL = 13; + /** RegularExpression Id. */ + int LESS_THAN = 14; + /** RegularExpression Id. */ + int LESS_EQUAL_THAN = 15; + /** RegularExpression Id. */ + int GREATER_THAN = 16; + /** RegularExpression Id. */ + int GREATER_EQUAL_THAN = 17; + /** RegularExpression Id. */ + int SELECT = 18; + /** RegularExpression Id. */ + int QUANTIFIER = 19; + /** RegularExpression Id. */ + int TOP = 20; + /** RegularExpression Id. */ + int FROM = 21; + /** RegularExpression Id. */ + int AS = 22; + /** RegularExpression Id. */ + int NATURAL = 23; + /** RegularExpression Id. */ + int INNER = 24; + /** RegularExpression Id. */ + int OUTER = 25; + /** RegularExpression Id. */ + int RIGHT = 26; + /** RegularExpression Id. */ + int LEFT = 27; + /** RegularExpression Id. */ + int FULL = 28; + /** RegularExpression Id. */ + int JOIN = 29; + /** RegularExpression Id. */ + int ON = 30; + /** RegularExpression Id. */ + int USING = 31; + /** RegularExpression Id. */ + int WHERE = 32; + /** RegularExpression Id. */ + int AND = 33; + /** RegularExpression Id. */ + int OR = 34; + /** RegularExpression Id. */ + int NOT = 35; + /** RegularExpression Id. */ + int IS = 36; + /** RegularExpression Id. */ + int NULL = 37; + /** RegularExpression Id. */ + int BETWEEN = 38; + /** RegularExpression Id. */ + int LIKE = 39; + /** RegularExpression Id. */ + int IN = 40; + /** RegularExpression Id. */ + int EXISTS = 41; + /** RegularExpression Id. */ + int GROUP_BY = 42; + /** RegularExpression Id. */ + int HAVING = 43; + /** RegularExpression Id. */ + int ORDER_BY = 44; + /** RegularExpression Id. */ + int ASC = 45; + /** RegularExpression Id. */ + int DESC = 46; + /** RegularExpression Id. */ + int AVG = 47; + /** RegularExpression Id. */ + int MAX = 48; + /** RegularExpression Id. */ + int MIN = 49; + /** RegularExpression Id. */ + int SUM = 50; + /** RegularExpression Id. */ + int COUNT = 51; + /** RegularExpression Id. */ + int BOX = 52; + /** RegularExpression Id. */ + int CENTROID = 53; + /** RegularExpression Id. */ + int CIRCLE = 54; + /** RegularExpression Id. */ + int POINT = 55; + /** RegularExpression Id. */ + int POLYGON = 56; + /** RegularExpression Id. */ + int REGION = 57; + /** RegularExpression Id. */ + int CONTAINS = 58; + /** RegularExpression Id. */ + int INTERSECTS = 59; + /** RegularExpression Id. */ + int AREA = 60; + /** RegularExpression Id. */ + int COORD1 = 61; + /** RegularExpression Id. */ + int COORD2 = 62; + /** RegularExpression Id. */ + int COORDSYS = 63; + /** RegularExpression Id. */ + int DISTANCE = 64; + /** RegularExpression Id. */ + int ABS = 65; + /** RegularExpression Id. */ + int CEILING = 66; + /** RegularExpression Id. */ + int DEGREES = 67; + /** RegularExpression Id. */ + int EXP = 68; + /** RegularExpression Id. */ + int FLOOR = 69; + /** RegularExpression Id. */ + int LOG = 70; + /** RegularExpression Id. */ + int LOG10 = 71; + /** RegularExpression Id. */ + int MOD = 72; + /** RegularExpression Id. */ + int PI = 73; + /** RegularExpression Id. */ + int POWER = 74; + /** RegularExpression Id. */ + int RADIANS = 75; + /** RegularExpression Id. */ + int RAND = 76; + /** RegularExpression Id. */ + int ROUND = 77; + /** RegularExpression Id. */ + int SQRT = 78; + /** RegularExpression Id. */ + int TRUNCATE = 79; + /** RegularExpression Id. */ + int ACOS = 80; + /** RegularExpression Id. */ + int ASIN = 81; + /** RegularExpression Id. */ + int ATAN = 82; + /** RegularExpression Id. */ + int ATAN2 = 83; + /** RegularExpression Id. */ + int COS = 84; + /** RegularExpression Id. */ + int COT = 85; + /** RegularExpression Id. */ + int SIN = 86; + /** RegularExpression Id. */ + int TAN = 87; + /** RegularExpression Id. */ + int STRING_LITERAL = 93; + /** RegularExpression Id. */ + int DELIMITED_IDENTIFIER = 96; + /** RegularExpression Id. */ + int REGULAR_IDENTIFIER = 97; + /** RegularExpression Id. */ + int Letter = 98; + /** RegularExpression Id. */ + int SCIENTIFIC_NUMBER = 99; + /** RegularExpression Id. */ + int UNSIGNED_FLOAT = 100; + /** RegularExpression Id. */ + int UNSIGNED_INTEGER = 101; + /** RegularExpression Id. */ + int DIGIT = 102; - /** Lexical state. */ - int DEFAULT = 0; - /** Lexical state. */ - int WithinComment = 1; - /** Lexical state. */ - int WithinString = 2; - /** Lexical state. */ - int WithinDelimitedId = 3; + /** Lexical state. */ + int DEFAULT = 0; + /** Lexical state. */ + int WithinComment = 1; + /** Lexical state. */ + int WithinString = 2; + /** Lexical state. */ + int WithinDelimitedId = 3; - /** Literal token values. */ - String[] tokenImage = {"<EOF>","<token of kind 1>","\"(\"","\")\"","\".\"","\",\"","\";\"","\"||\"","\"+\"","\"-\"","\"*\"","\"/\"","\"=\"","<NOT_EQUAL>","\"<\"","\"<=\"","\">\"","\">=\"","\"SELECT\"","<QUANTIFIER>","\"TOP\"","\"FROM\"","\"AS\"","\"NATURAL\"","\"INNER\"","\"OUTER\"","\"RIGHT\"","\"LEFT\"","\"FULL\"","\"JOIN\"","\"ON\"","\"USING\"","\"WHERE\"","\"AND\"","\"OR\"","\"NOT\"","\"IS\"","\"NULL\"","\"BETWEEN\"","\"LIKE\"","\"IN\"","\"EXISTS\"","\"GROUP BY\"","\"HAVING\"","\"ORDER BY\"","\"ASC\"","\"DESC\"","\"AVG\"","\"MAX\"","\"MIN\"","\"SUM\"","\"COUNT\"","\"BOX\"","\"CENTROID\"","\"CIRCLE\"","\"POINT\"","\"POLYGON\"","\"REGION\"","\"CONTAINS\"","\"INTERSECTS\"","\"AREA\"","\"COORD1\"","\"COORD2\"","\"COORDSYS\"","\"DISTANCE\"","\"ABS\"","\"CEILING\"","\"DEGREES\"","\"EXP\"","\"FLOOR\"","\"LOG\"","\"LOG10\"","\"MOD\"","\"PI\"","\"POWER\"","\"RADIANS\"","\"RAND\"","\"ROUND\"","\"SQRT\"","\"TRUNCATE\"","\"ACOS\"","\"ASIN\"","\"ATAN\"","\"ATAN2\"","\"COS\"","\"COT\"","\"SIN\"","\"TAN\"","<token of kind 88>","<token of kind 89>","<token of kind 90>","\"\\\'\"","<token of kind 92>","\"\\\'\"","\"\\\"\"","<token of kind 95>","\"\\\"\"","<REGULAR_IDENTIFIER>","<Letter>","<SCIENTIFIC_NUMBER>","<UNSIGNED_FLOAT>","<UNSIGNED_INTEGER>","<DIGIT>",}; + /** Literal token values. */ + String[] tokenImage = { + "<EOF>", + "<token of kind 1>", + "\"(\"", + "\")\"", + "\".\"", + "\",\"", + "\";\"", + "\"||\"", + "\"+\"", + "\"-\"", + "\"*\"", + "\"/\"", + "\"=\"", + "<NOT_EQUAL>", + "\"<\"", + "\"<=\"", + "\">\"", + "\">=\"", + "\"SELECT\"", + "<QUANTIFIER>", + "\"TOP\"", + "\"FROM\"", + "\"AS\"", + "\"NATURAL\"", + "\"INNER\"", + "\"OUTER\"", + "\"RIGHT\"", + "\"LEFT\"", + "\"FULL\"", + "\"JOIN\"", + "\"ON\"", + "\"USING\"", + "\"WHERE\"", + "\"AND\"", + "\"OR\"", + "\"NOT\"", + "\"IS\"", + "\"NULL\"", + "\"BETWEEN\"", + "\"LIKE\"", + "\"IN\"", + "\"EXISTS\"", + "\"GROUP BY\"", + "\"HAVING\"", + "\"ORDER BY\"", + "\"ASC\"", + "\"DESC\"", + "\"AVG\"", + "\"MAX\"", + "\"MIN\"", + "\"SUM\"", + "\"COUNT\"", + "\"BOX\"", + "\"CENTROID\"", + "\"CIRCLE\"", + "\"POINT\"", + "\"POLYGON\"", + "\"REGION\"", + "\"CONTAINS\"", + "\"INTERSECTS\"", + "\"AREA\"", + "\"COORD1\"", + "\"COORD2\"", + "\"COORDSYS\"", + "\"DISTANCE\"", + "\"ABS\"", + "\"CEILING\"", + "\"DEGREES\"", + "\"EXP\"", + "\"FLOOR\"", + "\"LOG\"", + "\"LOG10\"", + "\"MOD\"", + "\"PI\"", + "\"POWER\"", + "\"RADIANS\"", + "\"RAND\"", + "\"ROUND\"", + "\"SQRT\"", + "\"TRUNCATE\"", + "\"ACOS\"", + "\"ASIN\"", + "\"ATAN\"", + "\"ATAN2\"", + "\"COS\"", + "\"COT\"", + "\"SIN\"", + "\"TAN\"", + "<token of kind 88>", + "<token of kind 89>", + "<token of kind 90>", + "\"\\\'\"", + "<token of kind 92>", + "\"\\\'\"", + "\"\\\"\"", + "<token of kind 95>", + "\"\\\"\"", + "<REGULAR_IDENTIFIER>", + "<Letter>", + "<SCIENTIFIC_NUMBER>", + "<UNSIGNED_FLOAT>", + "<UNSIGNED_INTEGER>", + "<DIGIT>", + }; } diff --git a/src/adql/parser/ADQLParserTokenManager.java b/src/adql/parser/ADQLParserTokenManager.java index 4e4d9ccacac9e6978b879eca02d022d91348d0e9..15441617d4a598b379a86b537a7081e68d30579b 100644 --- a/src/adql/parser/ADQLParserTokenManager.java +++ b/src/adql/parser/ADQLParserTokenManager.java @@ -1,6 +1,5 @@ /* Generated By:JavaCC: Do not edit this line. ADQLParserTokenManager.java */ package adql.parser; - import java.util.Stack; import java.util.Vector; import java.util.ArrayList; @@ -21,1716 +20,1842 @@ import adql.translator.PostgreSQLTranslator; import adql.translator.TranslationException; /** Token Manager. */ -public class ADQLParserTokenManager implements ADQLParserConstants { - - /** Debug output. */ - public java.io.PrintStream debugStream = System.out; - - /** Set debug output. */ - public void setDebugStream(java.io.PrintStream ds){ - debugStream = ds; - } - - private final int jjStopStringLiteralDfa_3(int pos, long active0, long active1){ - switch(pos){ - default: - return -1; - } - } - - private final int jjStartNfa_3(int pos, long active0, long active1){ - return jjMoveNfa_3(jjStopStringLiteralDfa_3(pos, active0, active1), pos + 1); - } - - private int jjStopAtPos(int pos, int kind){ - jjmatchedKind = kind; - jjmatchedPos = pos; - return pos + 1; - } - - private int jjMoveStringLiteralDfa0_3(){ - switch(curChar){ - case 34: - return jjStartNfaWithStates_3(0, 96, 1); - default: - return jjMoveNfa_3(0, 0); - } - } - - private int jjStartNfaWithStates_3(int pos, int kind, int state){ - jjmatchedKind = kind; - jjmatchedPos = pos; - try{ - curChar = input_stream.readChar(); - }catch(java.io.IOException e){ - return pos + 1; - } - return jjMoveNfa_3(state, pos + 1); - } - - static final long[] jjbitVec0 = {0x0L,0x0L,0xffffffffffffffffL,0xffffffffffffffffL}; - - private int jjMoveNfa_3(int startState, int curPos){ - int startsAt = 0; - jjnewStateCnt = 3; - int i = 1; - jjstateSet[0] = startState; - int kind = 0x7fffffff; - for(;;){ - if (++jjround == 0x7fffffff) - ReInitRounds(); - if (curChar < 64){ - long l = 1L << curChar; - do{ - switch(jjstateSet[--i]){ - case 0: - if ((0xfffffffbffffffffL & l) != 0L){ - if (kind > 95) - kind = 95; - }else if (curChar == 34) - jjstateSet[jjnewStateCnt++] = 1; - break; - case 1: - if (curChar == 34 && kind > 95) - kind = 95; - break; - case 2: - if (curChar == 34) - jjstateSet[jjnewStateCnt++] = 1; - break; - default: - break; - } - }while(i != startsAt); - }else if (curChar < 128){ - long l = 1L << (curChar & 077); - do{ - switch(jjstateSet[--i]){ - case 0: - kind = 95; - break; - default: - break; - } - }while(i != startsAt); - }else{ - int i2 = (curChar & 0xff) >> 6; - long l2 = 1L << (curChar & 077); - do{ - switch(jjstateSet[--i]){ - case 0: - if ((jjbitVec0[i2] & l2) != 0L && kind > 95) - kind = 95; - break; - default: - break; - } - }while(i != startsAt); - } - if (kind != 0x7fffffff){ - jjmatchedKind = kind; - jjmatchedPos = curPos; - kind = 0x7fffffff; - } - ++curPos; - if ((i = jjnewStateCnt) == (startsAt = 3 - (jjnewStateCnt = startsAt))) - return curPos; - try{ - curChar = input_stream.readChar(); - }catch(java.io.IOException e){ - return curPos; - } - } - } - - private final int jjStopStringLiteralDfa_0(int pos, long active0, long active1){ - switch(pos){ - case 0: - if ((active0 & 0xefff1ffdffb40000L) != 0L || (active1 & 0xf0fff4L) != 0L){ - jjmatchedKind = 97; - return 37; - } - if ((active0 & 0x1000a00200400000L) != 0L || (active1 & 0xf0002L) != 0L){ - jjmatchedKind = 97; - return 16; - } - if ((active0 & 0x10L) != 0L) - return 38; - if ((active0 & 0x400000000000L) != 0L || (active1 & 0x9L) != 0L){ - jjmatchedKind = 97; - return 13; - } - if ((active0 & 0xc000L) != 0L) - return 3; - if ((active0 & 0x200L) != 0L) - return 19; - return -1; - case 1: - if ((active0 & 0xf7ffceebbeb40000L) != 0L || (active1 & 0xfdfdfeL) != 0L){ - if (jjmatchedPos != 1){ - jjmatchedKind = 97; - jjmatchedPos = 1; - } - return 37; - } - if ((active0 & 0x800311441400000L) != 0L || (active1 & 0x20200L) != 0L) - return 37; - if ((active1 & 0x1L) != 0L){ - if (jjmatchedPos != 1){ - jjmatchedKind = 97; - jjmatchedPos = 1; - } - return 12; - } - return -1; - case 2: - if ((active1 & 0x1L) != 0L){ - if (jjmatchedPos != 2){ - jjmatchedKind = 97; - jjmatchedPos = 2; - } - return 11; - } - if ((active0 & 0x17a00a00100000L) != 0L || (active1 & 0xf001d2L) != 0L) - return 37; - if ((active0 & 0xffe85ee1bfa40000L) != 0L || (active1 & 0xffc2cL) != 0L){ - if (jjmatchedPos != 2){ - jjmatchedKind = 97; - jjmatchedPos = 2; - } - return 37; - } - return -1; - case 3: - if ((active0 & 0xefe81e4187840000L) != 0L || (active1 & 0xac2cL) != 0L){ - if (jjmatchedPos != 3){ - jjmatchedKind = 97; - jjmatchedPos = 3; - } - return 37; - } - if ((active0 & 0x100040a038200000L) != 0L || (active1 & 0xf5000L) != 0L) - return 37; - if ((active1 & 0x80L) != 0L){ - if (jjmatchedPos != 3){ - jjmatchedKind = 97; - jjmatchedPos = 3; - } - return 21; - } - if ((active1 & 0x1L) != 0L){ - if (jjmatchedPos != 3){ - jjmatchedKind = 97; - jjmatchedPos = 3; - } - return 10; - } - return -1; - case 4: - if ((active0 & 0xef601e4000840000L) != 0L || (active1 & 0x880dL) != 0L){ - jjmatchedKind = 97; - jjmatchedPos = 4; - return 37; - } - if ((active0 & 0x88000187000000L) != 0L || (active1 & 0x2420L) != 0L) - return 37; - if ((active1 & 0x80080L) != 0L) - return 21; - return -1; - case 5: - if ((active0 & 0x2400a0000040000L) != 0L) - return 37; - if ((active0 & 0x6000000000000000L) != 0L) - return 21; - if ((active0 & 0x8d20004000800000L) != 0L || (active1 & 0x880dL) != 0L){ - jjmatchedKind = 97; - jjmatchedPos = 5; - return 37; - } - if ((active0 & 0x140000000000L) != 0L){ - if (jjmatchedPos < 4){ - jjmatchedKind = 97; - jjmatchedPos = 4; - } - return -1; - } - return -1; - case 6: - if ((active0 & 0x8c20000000000000L) != 0L || (active1 & 0x8001L) != 0L){ - jjmatchedKind = 97; - jjmatchedPos = 6; - return 37; - } - if ((active0 & 0x100004000800000L) != 0L || (active1 & 0x80cL) != 0L) - return 37; - if ((active0 & 0x140000000000L) != 0L){ - if (jjmatchedPos < 4){ - jjmatchedKind = 97; - jjmatchedPos = 4; - } - return -1; - } - return -1; - case 7: - if ((active0 & 0x800000000000000L) != 0L){ - jjmatchedKind = 97; - jjmatchedPos = 7; - return 37; - } - if ((active0 & 0x8420000000000000L) != 0L || (active1 & 0x8001L) != 0L) - return 37; - if ((active0 & 0x140000000000L) != 0L){ - if (jjmatchedPos < 4){ - jjmatchedKind = 97; - jjmatchedPos = 4; - } - return -1; - } - return -1; - case 8: - if ((active0 & 0x800000000000000L) != 0L){ - jjmatchedKind = 97; - jjmatchedPos = 8; - return 37; - } - return -1; - default: - return -1; - } - } - - private final int jjStartNfa_0(int pos, long active0, long active1){ - return jjMoveNfa_0(jjStopStringLiteralDfa_0(pos, active0, active1), pos + 1); - } - - private int jjMoveStringLiteralDfa0_0(){ - switch(curChar){ - case 34: - return jjStopAtPos(0, 94); - case 39: - return jjStopAtPos(0, 91); - case 40: - return jjStopAtPos(0, 2); - case 41: - return jjStopAtPos(0, 3); - case 42: - return jjStopAtPos(0, 10); - case 43: - return jjStopAtPos(0, 8); - case 44: - return jjStopAtPos(0, 5); - case 45: - return jjStartNfaWithStates_0(0, 9, 19); - case 46: - return jjStartNfaWithStates_0(0, 4, 38); - case 47: - return jjStopAtPos(0, 11); - case 59: - return jjStopAtPos(0, 6); - case 60: - jjmatchedKind = 14; - return jjMoveStringLiteralDfa1_0(0x8000L, 0x0L); - case 61: - return jjStopAtPos(0, 12); - case 62: - jjmatchedKind = 16; - return jjMoveStringLiteralDfa1_0(0x20000L, 0x0L); - case 65: - case 97: - return jjMoveStringLiteralDfa1_0(0x1000a00200400000L, 0xf0002L); - case 66: - case 98: - return jjMoveStringLiteralDfa1_0(0x10004000000000L, 0x0L); - case 67: - case 99: - return jjMoveStringLiteralDfa1_0(0xe468000000000000L, 0x300004L); - case 68: - case 100: - return jjMoveStringLiteralDfa1_0(0x400000000000L, 0x9L); - case 69: - case 101: - return jjMoveStringLiteralDfa1_0(0x20000000000L, 0x10L); - case 70: - case 102: - return jjMoveStringLiteralDfa1_0(0x10200000L, 0x20L); - case 71: - case 103: - return jjMoveStringLiteralDfa1_0(0x40000000000L, 0x0L); - case 72: - case 104: - return jjMoveStringLiteralDfa1_0(0x80000000000L, 0x0L); - case 73: - case 105: - return jjMoveStringLiteralDfa1_0(0x800011001000000L, 0x0L); - case 74: - case 106: - return jjMoveStringLiteralDfa1_0(0x20000000L, 0x0L); - case 76: - case 108: - return jjMoveStringLiteralDfa1_0(0x8008000000L, 0xc0L); - case 77: - case 109: - return jjMoveStringLiteralDfa1_0(0x3000000000000L, 0x100L); - case 78: - case 110: - return jjMoveStringLiteralDfa1_0(0x2800800000L, 0x0L); - case 79: - case 111: - return jjMoveStringLiteralDfa1_0(0x100442000000L, 0x0L); - case 80: - case 112: - return jjMoveStringLiteralDfa1_0(0x180000000000000L, 0x600L); - case 82: - case 114: - return jjMoveStringLiteralDfa1_0(0x200000004000000L, 0x3800L); - case 83: - case 115: - return jjMoveStringLiteralDfa1_0(0x4000000040000L, 0x404000L); - case 84: - case 116: - return jjMoveStringLiteralDfa1_0(0x100000L, 0x808000L); - case 85: - case 117: - return jjMoveStringLiteralDfa1_0(0x80000000L, 0x0L); - case 87: - case 119: - return jjMoveStringLiteralDfa1_0(0x100000000L, 0x0L); - case 124: - return jjMoveStringLiteralDfa1_0(0x80L, 0x0L); - default: - return jjMoveNfa_0(0, 0); - } - } - - private int jjMoveStringLiteralDfa1_0(long active0, long active1){ - try{ - curChar = input_stream.readChar(); - }catch(java.io.IOException e){ - jjStopStringLiteralDfa_0(0, active0, active1); - return 1; - } - switch(curChar){ - case 61: - if ((active0 & 0x8000L) != 0L) - return jjStopAtPos(1, 15); - else if ((active0 & 0x20000L) != 0L) - return jjStopAtPos(1, 17); - break; - case 65: - case 97: - return jjMoveStringLiteralDfa2_0(active0, 0x1080000800000L, active1, 0x801800L); - case 66: - case 98: - return jjMoveStringLiteralDfa2_0(active0, 0L, active1, 0x2L); - case 67: - case 99: - return jjMoveStringLiteralDfa2_0(active0, 0L, active1, 0x10000L); - case 69: - case 101: - return jjMoveStringLiteralDfa2_0(active0, 0x220404008040000L, active1, 0xcL); - case 72: - case 104: - return jjMoveStringLiteralDfa2_0(active0, 0x100000000L, active1, 0L); - case 73: - case 105: - if ((active1 & 0x200L) != 0L) - return jjStartNfaWithStates_0(1, 73, 37); - return jjMoveStringLiteralDfa2_0(active0, 0x42008004000000L, active1, 0x400001L); - case 76: - case 108: - return jjMoveStringLiteralDfa2_0(active0, 0L, active1, 0x20L); - case 78: - case 110: - if ((active0 & 0x40000000L) != 0L) - return jjStartNfaWithStates_0(1, 30, 37); - else if ((active0 & 0x10000000000L) != 0L){ - jjmatchedKind = 40; - jjmatchedPos = 1; - } - return jjMoveStringLiteralDfa2_0(active0, 0x800000201000000L, active1, 0L); - case 79: - case 111: - return jjMoveStringLiteralDfa2_0(active0, 0xe598000820100000L, active1, 0x3025c0L); - case 81: - case 113: - return jjMoveStringLiteralDfa2_0(active0, 0L, active1, 0x4000L); - case 82: - case 114: - if ((active0 & 0x400000000L) != 0L){ - jjmatchedKind = 34; - jjmatchedPos = 1; - } - return jjMoveStringLiteralDfa2_0(active0, 0x1000140000200000L, active1, 0x8000L); - case 83: - case 115: - if ((active0 & 0x400000L) != 0L){ - jjmatchedKind = 22; - jjmatchedPos = 1; - }else if ((active0 & 0x1000000000L) != 0L) - return jjStartNfaWithStates_0(1, 36, 37); - return jjMoveStringLiteralDfa2_0(active0, 0x200080000000L, active1, 0x20000L); - case 84: - case 116: - return jjMoveStringLiteralDfa2_0(active0, 0L, active1, 0xc0000L); - case 85: - case 117: - return jjMoveStringLiteralDfa2_0(active0, 0x4002012000000L, active1, 0L); - case 86: - case 118: - return jjMoveStringLiteralDfa2_0(active0, 0x800000000000L, active1, 0L); - case 88: - case 120: - return jjMoveStringLiteralDfa2_0(active0, 0x20000000000L, active1, 0x10L); - case 124: - if ((active0 & 0x80L) != 0L) - return jjStopAtPos(1, 7); - break; - default: - break; - } - return jjStartNfa_0(0, active0, active1); - } - - private int jjMoveStringLiteralDfa2_0(long old0, long active0, long old1, long active1){ - if (((active0 &= old0) | (active1 &= old1)) == 0L) - return jjStartNfa_0(0, old0, old1); - try{ - curChar = input_stream.readChar(); - }catch(java.io.IOException e){ - jjStopStringLiteralDfa_0(1, active0, active1); - return 2; - } - switch(curChar){ - case 65: - case 97: - return jjMoveStringLiteralDfa3_0(active0, 0L, active1, 0xc0000L); - case 67: - case 99: - if ((active0 & 0x200000000000L) != 0L) - return jjStartNfaWithStates_0(2, 45, 37); - break; - case 68: - case 100: - if ((active0 & 0x200000000L) != 0L) - return jjStartNfaWithStates_0(2, 33, 37); - else if ((active1 & 0x100L) != 0L) - return jjStartNfaWithStates_0(2, 72, 37); - return jjMoveStringLiteralDfa3_0(active0, 0x100000000000L, active1, 0x800L); - case 69: - case 101: - return jjMoveStringLiteralDfa3_0(active0, 0x1000000100000000L, active1, 0L); - case 70: - case 102: - return jjMoveStringLiteralDfa3_0(active0, 0x8000000L, active1, 0L); - case 71: - case 103: - if ((active0 & 0x800000000000L) != 0L) - return jjStartNfaWithStates_0(2, 47, 37); - else if ((active1 & 0x40L) != 0L){ - jjmatchedKind = 70; - jjmatchedPos = 2; - } - return jjMoveStringLiteralDfa3_0(active0, 0x200000004000000L, active1, 0x88L); - case 73: - case 105: - return jjMoveStringLiteralDfa3_0(active0, 0x800200a0000000L, active1, 0x20004L); - case 75: - case 107: - return jjMoveStringLiteralDfa3_0(active0, 0x8000000000L, active1, 0L); - case 76: - case 108: - return jjMoveStringLiteralDfa3_0(active0, 0x100002010040000L, active1, 0L); - case 77: - case 109: - if ((active0 & 0x4000000000000L) != 0L) - return jjStartNfaWithStates_0(2, 50, 37); - break; - case 78: - case 110: - if ((active0 & 0x2000000000000L) != 0L) - return jjStartNfaWithStates_0(2, 49, 37); - else if ((active1 & 0x400000L) != 0L) - return jjStartNfaWithStates_0(2, 86, 37); - else if ((active1 & 0x800000L) != 0L) - return jjStartNfaWithStates_0(2, 87, 37); - return jjMoveStringLiteralDfa3_0(active0, 0x420000001000000L, active1, 0x1000L); - case 79: - case 111: - return jjMoveStringLiteralDfa3_0(active0, 0xe000040000200000L, active1, 0x10020L); - case 80: - case 112: - if ((active0 & 0x100000L) != 0L) - return jjStartNfaWithStates_0(2, 20, 37); - else if ((active1 & 0x10L) != 0L) - return jjStartNfaWithStates_0(2, 68, 37); - break; - case 82: - case 114: - return jjMoveStringLiteralDfa3_0(active0, 0x40000000000000L, active1, 0x4000L); - case 83: - case 115: - if ((active1 & 0x2L) != 0L) - return jjStartNfaWithStates_0(2, 65, 37); - else if ((active1 & 0x100000L) != 0L) - return jjStartNfaWithStates_0(2, 84, 37); - return jjMoveStringLiteralDfa3_0(active0, 0x400000000000L, active1, 0x1L); - case 84: - case 116: - if ((active0 & 0x800000000L) != 0L) - return jjStartNfaWithStates_0(2, 35, 37); - else if ((active1 & 0x200000L) != 0L) - return jjStartNfaWithStates_0(2, 85, 37); - return jjMoveStringLiteralDfa3_0(active0, 0x800004002800000L, active1, 0L); - case 85: - case 117: - return jjMoveStringLiteralDfa3_0(active0, 0x8000000000000L, active1, 0xa000L); - case 86: - case 118: - return jjMoveStringLiteralDfa3_0(active0, 0x80000000000L, active1, 0L); - case 87: - case 119: - return jjMoveStringLiteralDfa3_0(active0, 0L, active1, 0x400L); - case 88: - case 120: - if ((active0 & 0x1000000000000L) != 0L) - return jjStartNfaWithStates_0(2, 48, 37); - else if ((active0 & 0x10000000000000L) != 0L) - return jjStartNfaWithStates_0(2, 52, 37); - break; - default: - break; - } - return jjStartNfa_0(1, active0, active1); - } - - private int jjMoveStringLiteralDfa3_0(long old0, long active0, long old1, long active1){ - if (((active0 &= old0) | (active1 &= old1)) == 0L) - return jjStartNfa_0(1, old0, old1); - try{ - curChar = input_stream.readChar(); - }catch(java.io.IOException e){ - jjStopStringLiteralDfa_0(2, active0, active1); - return 3; - } - switch(curChar){ - case 49: - return jjMoveStringLiteralDfa4_0(active0, 0L, active1, 0x80L); - case 65: - case 97: - if ((active0 & 0x1000000000000000L) != 0L) - return jjStartNfaWithStates_0(3, 60, 37); - break; - case 67: - case 99: - if ((active0 & 0x400000000000L) != 0L) - return jjStartNfaWithStates_0(3, 46, 37); - return jjMoveStringLiteralDfa4_0(active0, 0x40000000000000L, active1, 0L); - case 68: - case 100: - if ((active1 & 0x1000L) != 0L) - return jjStartNfaWithStates_0(3, 76, 37); - break; - case 69: - case 101: - if ((active0 & 0x8000000000L) != 0L) - return jjStartNfaWithStates_0(3, 39, 37); - return jjMoveStringLiteralDfa4_0(active0, 0x800100003040000L, active1, 0x400L); - case 72: - case 104: - return jjMoveStringLiteralDfa4_0(active0, 0x4000000L, active1, 0L); - case 73: - case 105: - return jjMoveStringLiteralDfa4_0(active0, 0x200080000000000L, active1, 0x800L); - case 76: - case 108: - if ((active0 & 0x10000000L) != 0L) - return jjStartNfaWithStates_0(3, 28, 37); - else if ((active0 & 0x2000000000L) != 0L) - return jjStartNfaWithStates_0(3, 37, 37); - return jjMoveStringLiteralDfa4_0(active0, 0L, active1, 0x4L); - case 77: - case 109: - if ((active0 & 0x200000L) != 0L) - return jjStartNfaWithStates_0(3, 21, 37); - break; - case 78: - case 110: - if ((active0 & 0x20000000L) != 0L) - return jjStartNfaWithStates_0(3, 29, 37); - else if ((active1 & 0x20000L) != 0L) - return jjStartNfaWithStates_0(3, 81, 37); - else if ((active1 & 0x40000L) != 0L){ - jjmatchedKind = 82; - jjmatchedPos = 3; - } - return jjMoveStringLiteralDfa4_0(active0, 0x88000080000000L, active1, 0x8a000L); - case 79: - case 111: - return jjMoveStringLiteralDfa4_0(active0, 0L, active1, 0x20L); - case 82: - case 114: - return jjMoveStringLiteralDfa4_0(active0, 0xe000000100000000L, active1, 0x8L); - case 83: - case 115: - if ((active1 & 0x10000L) != 0L) - return jjStartNfaWithStates_0(3, 80, 37); - return jjMoveStringLiteralDfa4_0(active0, 0x20000000000L, active1, 0L); - case 84: - case 116: - if ((active0 & 0x8000000L) != 0L) - return jjStartNfaWithStates_0(3, 27, 37); - else if ((active1 & 0x4000L) != 0L) - return jjStartNfaWithStates_0(3, 78, 37); - return jjMoveStringLiteralDfa4_0(active0, 0x420000000000000L, active1, 0x1L); - case 85: - case 117: - return jjMoveStringLiteralDfa4_0(active0, 0x40000800000L, active1, 0L); - case 87: - case 119: - return jjMoveStringLiteralDfa4_0(active0, 0x4000000000L, active1, 0L); - case 89: - case 121: - return jjMoveStringLiteralDfa4_0(active0, 0x100000000000000L, active1, 0L); - default: - break; - } - return jjStartNfa_0(2, active0, active1); - } - - private int jjMoveStringLiteralDfa4_0(long old0, long active0, long old1, long active1){ - if (((active0 &= old0) | (active1 &= old1)) == 0L) - return jjStartNfa_0(2, old0, old1); - try{ - curChar = input_stream.readChar(); - }catch(java.io.IOException e){ - jjStopStringLiteralDfa_0(3, active0, active1); - return 4; - } - switch(curChar){ - case 48: - if ((active1 & 0x80L) != 0L) - return jjStartNfaWithStates_0(4, 71, 21); - break; - case 50: - if ((active1 & 0x80000L) != 0L) - return jjStartNfaWithStates_0(4, 83, 21); - break; - case 65: - case 97: - return jjMoveStringLiteralDfa5_0(active0, 0x400000000000000L, active1, 0x801L); - case 67: - case 99: - return jjMoveStringLiteralDfa5_0(active0, 0x40000L, active1, 0x8000L); - case 68: - case 100: - if ((active1 & 0x2000L) != 0L) - return jjStartNfaWithStates_0(4, 77, 37); - return jjMoveStringLiteralDfa5_0(active0, 0xe000000000000000L, active1, 0L); - case 69: - case 101: - if ((active0 & 0x100000000L) != 0L) - return jjStartNfaWithStates_0(4, 32, 37); - return jjMoveStringLiteralDfa5_0(active0, 0x4000000000L, active1, 0x8L); - case 71: - case 103: - if ((active0 & 0x80000000L) != 0L) - return jjStartNfaWithStates_0(4, 31, 37); - return jjMoveStringLiteralDfa5_0(active0, 0x100000000000000L, active1, 0L); - case 73: - case 105: - return jjMoveStringLiteralDfa5_0(active0, 0L, active1, 0x4L); - case 76: - case 108: - return jjMoveStringLiteralDfa5_0(active0, 0x40000000000000L, active1, 0L); - case 78: - case 110: - return jjMoveStringLiteralDfa5_0(active0, 0x80000000000L, active1, 0L); - case 79: - case 111: - return jjMoveStringLiteralDfa5_0(active0, 0x200000000000000L, active1, 0L); - case 80: - case 112: - return jjMoveStringLiteralDfa5_0(active0, 0x40000000000L, active1, 0L); - case 82: - case 114: - if ((active0 & 0x1000000L) != 0L) - return jjStartNfaWithStates_0(4, 24, 37); - else if ((active0 & 0x2000000L) != 0L) - return jjStartNfaWithStates_0(4, 25, 37); - else if ((active1 & 0x20L) != 0L) - return jjStartNfaWithStates_0(4, 69, 37); - else if ((active1 & 0x400L) != 0L) - return jjStartNfaWithStates_0(4, 74, 37); - return jjMoveStringLiteralDfa5_0(active0, 0x820100000800000L, active1, 0L); - case 84: - case 116: - if ((active0 & 0x4000000L) != 0L) - return jjStartNfaWithStates_0(4, 26, 37); - else if ((active0 & 0x8000000000000L) != 0L) - return jjStartNfaWithStates_0(4, 51, 37); - else if ((active0 & 0x80000000000000L) != 0L) - return jjStartNfaWithStates_0(4, 55, 37); - return jjMoveStringLiteralDfa5_0(active0, 0x20000000000L, active1, 0L); - default: - break; - } - return jjStartNfa_0(3, active0, active1); - } - - private int jjMoveStringLiteralDfa5_0(long old0, long active0, long old1, long active1){ - if (((active0 &= old0) | (active1 &= old1)) == 0L) - return jjStartNfa_0(3, old0, old1); - try{ - curChar = input_stream.readChar(); - }catch(java.io.IOException e){ - jjStopStringLiteralDfa_0(4, active0, active1); - return 5; - } - switch(curChar){ - case 32: - return jjMoveStringLiteralDfa6_0(active0, 0x140000000000L, active1, 0L); - case 49: - if ((active0 & 0x2000000000000000L) != 0L) - return jjStartNfaWithStates_0(5, 61, 21); - break; - case 50: - if ((active0 & 0x4000000000000000L) != 0L) - return jjStartNfaWithStates_0(5, 62, 21); - break; - case 65: - case 97: - return jjMoveStringLiteralDfa6_0(active0, 0x800000L, active1, 0x8000L); - case 69: - case 101: - if ((active0 & 0x40000000000000L) != 0L) - return jjStartNfaWithStates_0(5, 54, 37); - return jjMoveStringLiteralDfa6_0(active0, 0x4000000000L, active1, 0x8L); - case 71: - case 103: - if ((active0 & 0x80000000000L) != 0L) - return jjStartNfaWithStates_0(5, 43, 37); - break; - case 73: - case 105: - return jjMoveStringLiteralDfa6_0(active0, 0x400000000000000L, active1, 0L); - case 78: - case 110: - if ((active0 & 0x200000000000000L) != 0L) - return jjStartNfaWithStates_0(5, 57, 37); - return jjMoveStringLiteralDfa6_0(active0, 0L, active1, 0x805L); - case 79: - case 111: - return jjMoveStringLiteralDfa6_0(active0, 0x120000000000000L, active1, 0L); - case 83: - case 115: - if ((active0 & 0x20000000000L) != 0L) - return jjStartNfaWithStates_0(5, 41, 37); - return jjMoveStringLiteralDfa6_0(active0, 0x8800000000000000L, active1, 0L); - case 84: - case 116: - if ((active0 & 0x40000L) != 0L) - return jjStartNfaWithStates_0(5, 18, 37); - break; - default: - break; - } - return jjStartNfa_0(4, active0, active1); - } - - private int jjMoveStringLiteralDfa6_0(long old0, long active0, long old1, long active1){ - if (((active0 &= old0) | (active1 &= old1)) == 0L) - return jjStartNfa_0(4, old0, old1); - try{ - curChar = input_stream.readChar(); - }catch(java.io.IOException e){ - jjStopStringLiteralDfa_0(5, active0, active1); - return 6; - } - switch(curChar){ - case 66: - case 98: - return jjMoveStringLiteralDfa7_0(active0, 0x140000000000L, active1, 0L); - case 67: - case 99: - return jjMoveStringLiteralDfa7_0(active0, 0L, active1, 0x1L); - case 69: - case 101: - return jjMoveStringLiteralDfa7_0(active0, 0x800000000000000L, active1, 0L); - case 71: - case 103: - if ((active1 & 0x4L) != 0L) - return jjStartNfaWithStates_0(6, 66, 37); - break; - case 73: - case 105: - return jjMoveStringLiteralDfa7_0(active0, 0x20000000000000L, active1, 0L); - case 76: - case 108: - if ((active0 & 0x800000L) != 0L) - return jjStartNfaWithStates_0(6, 23, 37); - break; - case 78: - case 110: - if ((active0 & 0x4000000000L) != 0L) - return jjStartNfaWithStates_0(6, 38, 37); - else if ((active0 & 0x100000000000000L) != 0L) - return jjStartNfaWithStates_0(6, 56, 37); - return jjMoveStringLiteralDfa7_0(active0, 0x400000000000000L, active1, 0L); - case 83: - case 115: - if ((active1 & 0x8L) != 0L) - return jjStartNfaWithStates_0(6, 67, 37); - else if ((active1 & 0x800L) != 0L) - return jjStartNfaWithStates_0(6, 75, 37); - break; - case 84: - case 116: - return jjMoveStringLiteralDfa7_0(active0, 0L, active1, 0x8000L); - case 89: - case 121: - return jjMoveStringLiteralDfa7_0(active0, 0x8000000000000000L, active1, 0L); - default: - break; - } - return jjStartNfa_0(5, active0, active1); - } +public class ADQLParserTokenManager implements ADQLParserConstants +{ - private int jjMoveStringLiteralDfa7_0(long old0, long active0, long old1, long active1){ - if (((active0 &= old0) | (active1 &= old1)) == 0L) - return jjStartNfa_0(5, old0, old1); - try{ - curChar = input_stream.readChar(); - }catch(java.io.IOException e){ - jjStopStringLiteralDfa_0(6, active0, active1); - return 7; - } - switch(curChar){ - case 67: - case 99: - return jjMoveStringLiteralDfa8_0(active0, 0x800000000000000L, active1, 0L); - case 68: - case 100: - if ((active0 & 0x20000000000000L) != 0L) - return jjStartNfaWithStates_0(7, 53, 37); - break; - case 69: - case 101: - if ((active1 & 0x1L) != 0L) - return jjStartNfaWithStates_0(7, 64, 37); - else if ((active1 & 0x8000L) != 0L) - return jjStartNfaWithStates_0(7, 79, 37); - break; - case 83: - case 115: - if ((active0 & 0x400000000000000L) != 0L) - return jjStartNfaWithStates_0(7, 58, 37); - else if ((active0 & 0x8000000000000000L) != 0L) - return jjStartNfaWithStates_0(7, 63, 37); - break; - case 89: - case 121: - if ((active0 & 0x40000000000L) != 0L) - return jjStopAtPos(7, 42); - else if ((active0 & 0x100000000000L) != 0L) - return jjStopAtPos(7, 44); - break; - default: - break; - } - return jjStartNfa_0(6, active0, active1); - } - - private int jjMoveStringLiteralDfa8_0(long old0, long active0, long old1, long active1){ - if (((active0 &= old0) | (active1 &= old1)) == 0L) - return jjStartNfa_0(6, old0, old1); - try{ - curChar = input_stream.readChar(); - }catch(java.io.IOException e){ - jjStopStringLiteralDfa_0(7, active0, 0L); - return 8; - } - switch(curChar){ - case 84: - case 116: - return jjMoveStringLiteralDfa9_0(active0, 0x800000000000000L); - default: - break; - } - return jjStartNfa_0(7, active0, 0L); - } - - private int jjMoveStringLiteralDfa9_0(long old0, long active0){ - if (((active0 &= old0)) == 0L) - return jjStartNfa_0(7, old0, 0L); - try{ - curChar = input_stream.readChar(); - }catch(java.io.IOException e){ - jjStopStringLiteralDfa_0(8, active0, 0L); - return 9; - } - switch(curChar){ - case 83: - case 115: - if ((active0 & 0x800000000000000L) != 0L) - return jjStartNfaWithStates_0(9, 59, 37); - break; - default: - break; - } - return jjStartNfa_0(8, active0, 0L); - } - - private int jjStartNfaWithStates_0(int pos, int kind, int state){ - jjmatchedKind = kind; - jjmatchedPos = pos; - try{ - curChar = input_stream.readChar(); - }catch(java.io.IOException e){ - return pos + 1; - } - return jjMoveNfa_0(state, pos + 1); - } - - private int jjMoveNfa_0(int startState, int curPos){ - int startsAt = 0; - jjnewStateCnt = 37; - int i = 1; - jjstateSet[0] = startState; - int kind = 0x7fffffff; - for(;;){ - if (++jjround == 0x7fffffff) - ReInitRounds(); - if (curChar < 64){ - long l = 1L << curChar; - do{ - switch(jjstateSet[--i]){ - case 12: - case 21: - if ((0x3ff000000000000L & l) == 0L) - break; - if (kind > 97) - kind = 97; - jjCheckNAdd(21); - break; - case 38: - if ((0x3ff000000000000L & l) != 0L){ - if (kind > 100) - kind = 100; - jjCheckNAdd(27); - } - if ((0x3ff000000000000L & l) != 0L) - jjCheckNAddTwoStates(23, 24); - break; - case 37: - if ((0x3ff000000000000L & l) == 0L) - break; - if (kind > 97) - kind = 97; - jjCheckNAdd(21); - break; - case 0: - if ((0x3ff000000000000L & l) != 0L){ - if (kind > 101) - kind = 101; - jjCheckNAddStates(0, 6); - }else if ((0x100002600L & l) != 0L){ - if (kind > 1) - kind = 1; - }else if (curChar == 46) - jjCheckNAddTwoStates(23, 27); - else if (curChar == 45) - jjCheckNAdd(19); - else if (curChar == 33) - jjstateSet[jjnewStateCnt++] = 5; - else if (curChar == 60) - jjstateSet[jjnewStateCnt++] = 3; - if (curChar == 13) - jjstateSet[jjnewStateCnt++] = 1; - break; - case 11: - if ((0x3ff000000000000L & l) == 0L) - break; - if (kind > 97) - kind = 97; - jjCheckNAdd(21); - break; - case 16: - if ((0x3ff000000000000L & l) == 0L) - break; - if (kind > 97) - kind = 97; - jjCheckNAdd(21); - break; - case 13: - if ((0x3ff000000000000L & l) == 0L) - break; - if (kind > 97) - kind = 97; - jjCheckNAdd(21); - break; - case 10: - if ((0x3ff000000000000L & l) == 0L) - break; - if (kind > 97) - kind = 97; - jjCheckNAdd(21); - break; - case 1: - if (curChar == 10 && kind > 1) - kind = 1; - break; - case 2: - if (curChar == 13) - jjstateSet[jjnewStateCnt++] = 1; - break; - case 3: - if (curChar == 62) - kind = 13; - break; - case 4: - if (curChar == 60) - jjstateSet[jjnewStateCnt++] = 3; - break; - case 5: - if (curChar == 61) - kind = 13; - break; - case 6: - if (curChar == 33) - jjstateSet[jjnewStateCnt++] = 5; - break; - case 18: - if (curChar == 45) - jjCheckNAdd(19); - break; - case 19: - if (curChar != 45) - break; - if (kind > 88) - kind = 88; - jjCheckNAdd(19); - break; - case 22: - if (curChar == 46) - jjCheckNAddTwoStates(23, 27); - break; - case 23: - if ((0x3ff000000000000L & l) != 0L) - jjCheckNAddTwoStates(23, 24); - break; - case 25: - if ((0x280000000000L & l) != 0L) - jjCheckNAdd(26); - break; - case 26: - if ((0x3ff000000000000L & l) == 0L) - break; - if (kind > 99) - kind = 99; - jjCheckNAdd(26); - break; - case 27: - if ((0x3ff000000000000L & l) == 0L) - break; - if (kind > 100) - kind = 100; - jjCheckNAdd(27); - break; - case 28: - if ((0x3ff000000000000L & l) == 0L) - break; - if (kind > 101) - kind = 101; - jjCheckNAddStates(0, 6); - break; - case 29: - if ((0x3ff000000000000L & l) != 0L) - jjCheckNAddTwoStates(29, 24); - break; - case 30: - if ((0x3ff000000000000L & l) != 0L) - jjCheckNAddTwoStates(30, 31); - break; - case 31: - if (curChar == 46) - jjCheckNAddTwoStates(32, 24); - break; - case 32: - if ((0x3ff000000000000L & l) != 0L) - jjCheckNAddTwoStates(32, 24); - break; - case 33: - if ((0x3ff000000000000L & l) != 0L) - jjCheckNAddTwoStates(33, 34); - break; - case 34: - if (curChar != 46) - break; - if (kind > 100) - kind = 100; - jjCheckNAdd(35); - break; - case 35: - if ((0x3ff000000000000L & l) == 0L) - break; - if (kind > 100) - kind = 100; - jjCheckNAdd(35); - break; - case 36: - if ((0x3ff000000000000L & l) == 0L) - break; - if (kind > 101) - kind = 101; - jjCheckNAdd(36); - break; - default: - break; - } - }while(i != startsAt); - }else if (curChar < 128){ - long l = 1L << (curChar & 077); - do{ - switch(jjstateSet[--i]){ - case 12: - if ((0x7fffffe87fffffeL & l) != 0L){ - if (kind > 97) - kind = 97; - jjCheckNAdd(21); - } - if ((0x7fffffe07fffffeL & l) != 0L){ - if (kind > 97) - kind = 97; - jjCheckNAddTwoStates(20, 21); - } - if ((0x8000000080000L & l) != 0L) - jjstateSet[jjnewStateCnt++] = 11; - break; - case 37: - if ((0x7fffffe87fffffeL & l) != 0L){ - if (kind > 97) - kind = 97; - jjCheckNAdd(21); - } - if ((0x7fffffe07fffffeL & l) != 0L){ - if (kind > 97) - kind = 97; - jjCheckNAddTwoStates(20, 21); - } - break; - case 0: - if ((0x7fffffe07fffffeL & l) != 0L){ - if (kind > 97) - kind = 97; - jjCheckNAddTwoStates(20, 21); - } - if ((0x200000002L & l) != 0L) - jjstateSet[jjnewStateCnt++] = 16; - else if ((0x1000000010L & l) != 0L) - jjstateSet[jjnewStateCnt++] = 13; - break; - case 11: - if ((0x7fffffe87fffffeL & l) != 0L){ - if (kind > 97) - kind = 97; - jjCheckNAdd(21); - } - if ((0x7fffffe07fffffeL & l) != 0L){ - if (kind > 97) - kind = 97; - jjCheckNAddTwoStates(20, 21); - } - if ((0x10000000100000L & l) != 0L) - jjstateSet[jjnewStateCnt++] = 10; - break; - case 16: - if ((0x7fffffe87fffffeL & l) != 0L){ - if (kind > 97) - kind = 97; - jjCheckNAdd(21); - } - if ((0x7fffffe07fffffeL & l) != 0L){ - if (kind > 97) - kind = 97; - jjCheckNAddTwoStates(20, 21); - } - if ((0x100000001000L & l) != 0L) - jjstateSet[jjnewStateCnt++] = 15; - break; - case 13: - if ((0x7fffffe87fffffeL & l) != 0L){ - if (kind > 97) - kind = 97; - jjCheckNAdd(21); - } - if ((0x7fffffe07fffffeL & l) != 0L){ - if (kind > 97) - kind = 97; - jjCheckNAddTwoStates(20, 21); - } - if ((0x20000000200L & l) != 0L) - jjstateSet[jjnewStateCnt++] = 12; - break; - case 10: - if ((0x7fffffe87fffffeL & l) != 0L){ - if (kind > 97) - kind = 97; - jjCheckNAdd(21); - } - if ((0x7fffffe07fffffeL & l) != 0L){ - if (kind > 97) - kind = 97; - jjCheckNAddTwoStates(20, 21); - } - if ((0x20000000200L & l) != 0L) - jjstateSet[jjnewStateCnt++] = 9; - break; - case 7: - if ((0x10000000100000L & l) != 0L && kind > 19) - kind = 19; - break; - case 8: - if ((0x800000008L & l) != 0L) - jjstateSet[jjnewStateCnt++] = 7; - break; - case 9: - if ((0x400000004000L & l) != 0L) - jjstateSet[jjnewStateCnt++] = 8; - break; - case 14: - if ((0x1000000010L & l) != 0L) - jjstateSet[jjnewStateCnt++] = 13; - break; - case 15: - if ((0x100000001000L & l) != 0L && kind > 19) - kind = 19; - break; - case 17: - if ((0x200000002L & l) != 0L) - jjstateSet[jjnewStateCnt++] = 16; - break; - case 20: - if ((0x7fffffe07fffffeL & l) == 0L) - break; - if (kind > 97) - kind = 97; - jjCheckNAddTwoStates(20, 21); - break; - case 21: - if ((0x7fffffe87fffffeL & l) == 0L) - break; - if (kind > 97) - kind = 97; - jjCheckNAdd(21); - break; - case 24: - if ((0x2000000020L & l) != 0L) - jjAddStates(7, 8); - break; - default: - break; - } - }while(i != startsAt); - }else{ - int i2 = (curChar & 0xff) >> 6; - long l2 = 1L << (curChar & 077); - do{ - switch(jjstateSet[--i]){ - default: - break; - } - }while(i != startsAt); - } - if (kind != 0x7fffffff){ - jjmatchedKind = kind; - jjmatchedPos = curPos; - kind = 0x7fffffff; - } - ++curPos; - if ((i = jjnewStateCnt) == (startsAt = 37 - (jjnewStateCnt = startsAt))) - return curPos; - try{ - curChar = input_stream.readChar(); - }catch(java.io.IOException e){ - return curPos; - } - } - } - - private final int jjStopStringLiteralDfa_2(int pos, long active0, long active1){ - switch(pos){ - default: - return -1; - } - } - - private final int jjStartNfa_2(int pos, long active0, long active1){ - return jjMoveNfa_2(jjStopStringLiteralDfa_2(pos, active0, active1), pos + 1); - } - - private int jjMoveStringLiteralDfa0_2(){ - switch(curChar){ - case 39: - return jjStartNfaWithStates_2(0, 93, 1); - default: - return jjMoveNfa_2(0, 0); - } - } - - private int jjStartNfaWithStates_2(int pos, int kind, int state){ - jjmatchedKind = kind; - jjmatchedPos = pos; - try{ - curChar = input_stream.readChar(); - }catch(java.io.IOException e){ - return pos + 1; - } - return jjMoveNfa_2(state, pos + 1); - } - - private int jjMoveNfa_2(int startState, int curPos){ - int startsAt = 0; - jjnewStateCnt = 3; - int i = 1; - jjstateSet[0] = startState; - int kind = 0x7fffffff; - for(;;){ - if (++jjround == 0x7fffffff) - ReInitRounds(); - if (curChar < 64){ - long l = 1L << curChar; - do{ - switch(jjstateSet[--i]){ - case 0: - if ((0xffffff7fffffffffL & l) != 0L){ - if (kind > 92) - kind = 92; - }else if (curChar == 39) - jjstateSet[jjnewStateCnt++] = 1; - break; - case 1: - if (curChar == 39 && kind > 92) - kind = 92; - break; - case 2: - if (curChar == 39) - jjstateSet[jjnewStateCnt++] = 1; - break; - default: - break; - } - }while(i != startsAt); - }else if (curChar < 128){ - long l = 1L << (curChar & 077); - do{ - switch(jjstateSet[--i]){ - case 0: - kind = 92; - break; - default: - break; - } - }while(i != startsAt); - }else{ - int i2 = (curChar & 0xff) >> 6; - long l2 = 1L << (curChar & 077); - do{ - switch(jjstateSet[--i]){ - case 0: - if ((jjbitVec0[i2] & l2) != 0L && kind > 92) - kind = 92; - break; - default: - break; - } - }while(i != startsAt); - } - if (kind != 0x7fffffff){ - jjmatchedKind = kind; - jjmatchedPos = curPos; - kind = 0x7fffffff; - } - ++curPos; - if ((i = jjnewStateCnt) == (startsAt = 3 - (jjnewStateCnt = startsAt))) - return curPos; - try{ - curChar = input_stream.readChar(); - }catch(java.io.IOException e){ - return curPos; - } - } - } - - private int jjMoveStringLiteralDfa0_1(){ - return jjMoveNfa_1(0, 0); - } - - private int jjMoveNfa_1(int startState, int curPos){ - int startsAt = 0; - jjnewStateCnt = 3; - int i = 1; - jjstateSet[0] = startState; - int kind = 0x7fffffff; - for(;;){ - if (++jjround == 0x7fffffff) - ReInitRounds(); - if (curChar < 64){ - long l = 1L << curChar; - do{ - switch(jjstateSet[--i]){ - case 0: - if ((0x2400L & l) != 0L){ - if (kind > 89) - kind = 89; - } - if (curChar == 13) - jjstateSet[jjnewStateCnt++] = 1; - break; - case 1: - if (curChar == 10 && kind > 89) - kind = 89; - break; - case 2: - if (curChar == 13) - jjstateSet[jjnewStateCnt++] = 1; - break; - default: - break; - } - }while(i != startsAt); - }else if (curChar < 128){ - long l = 1L << (curChar & 077); - do{ - switch(jjstateSet[--i]){ - default: - break; - } - }while(i != startsAt); - }else{ - int i2 = (curChar & 0xff) >> 6; - long l2 = 1L << (curChar & 077); - do{ - switch(jjstateSet[--i]){ - default: - break; - } - }while(i != startsAt); - } - if (kind != 0x7fffffff){ - jjmatchedKind = kind; - jjmatchedPos = curPos; - kind = 0x7fffffff; - } - ++curPos; - if ((i = jjnewStateCnt) == (startsAt = 3 - (jjnewStateCnt = startsAt))) - return curPos; - try{ - curChar = input_stream.readChar(); - }catch(java.io.IOException e){ - return curPos; - } - } - } - - static final int[] jjnextStates = {29,30,31,24,33,34,36,25,26,}; - - /** Token literal values. */ - public static final String[] jjstrLiteralImages = {"",null,"\50","\51","\56","\54","\73","\174\174","\53","\55","\52","\57","\75",null,"\74","\74\75","\76","\76\75",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,}; - - /** Lexer state names. */ - public static final String[] lexStateNames = {"DEFAULT","WithinComment","WithinString","WithinDelimitedId",}; - - /** Lex State array. */ - public static final int[] jjnewLexState = {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,0,-1,2,-1,0,3,-1,0,-1,-1,-1,-1,-1,-1,}; - static final long[] jjtoToken = {0xfffffffffffffffdL,0x3b20ffffffL,}; - static final long[] jjtoSkip = {0x2L,0x2000000L,}; - static final long[] jjtoMore = {0x0L,0xdd000000L,}; - protected SimpleCharStream input_stream; - private final int[] jjrounds = new int[37]; - private final int[] jjstateSet = new int[74]; - protected char curChar; - - /** Constructor. */ - public ADQLParserTokenManager(SimpleCharStream stream){ - if (SimpleCharStream.staticFlag) - throw new Error("ERROR: Cannot use a static CharStream class with a non-static lexical analyzer."); - input_stream = stream; - } + /** Debug output. */ + public java.io.PrintStream debugStream = System.out; + /** Set debug output. */ + public void setDebugStream(java.io.PrintStream ds) { debugStream = ds; } +private final int jjStopStringLiteralDfa_3(int pos, long active0, long active1) +{ + switch (pos) + { + default : + return -1; + } +} +private final int jjStartNfa_3(int pos, long active0, long active1) +{ + return jjMoveNfa_3(jjStopStringLiteralDfa_3(pos, active0, active1), pos + 1); +} +private int jjStopAtPos(int pos, int kind) +{ + jjmatchedKind = kind; + jjmatchedPos = pos; + return pos + 1; +} +private int jjMoveStringLiteralDfa0_3() +{ + switch(curChar) + { + case 34: + return jjStartNfaWithStates_3(0, 96, 1); + default : + return jjMoveNfa_3(0, 0); + } +} +private int jjStartNfaWithStates_3(int pos, int kind, int state) +{ + jjmatchedKind = kind; + jjmatchedPos = pos; + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { return pos + 1; } + return jjMoveNfa_3(state, pos + 1); +} +static final long[] jjbitVec0 = { + 0x0L, 0x0L, 0xffffffffffffffffL, 0xffffffffffffffffL +}; +private int jjMoveNfa_3(int startState, int curPos) +{ + int startsAt = 0; + jjnewStateCnt = 3; + int i = 1; + jjstateSet[0] = startState; + int kind = 0x7fffffff; + for (;;) + { + if (++jjround == 0x7fffffff) + ReInitRounds(); + if (curChar < 64) + { + long l = 1L << curChar; + do + { + switch(jjstateSet[--i]) + { + case 0: + if ((0xfffffffbffffffffL & l) != 0L) + { + if (kind > 95) + kind = 95; + } + else if (curChar == 34) + jjstateSet[jjnewStateCnt++] = 1; + break; + case 1: + if (curChar == 34 && kind > 95) + kind = 95; + break; + case 2: + if (curChar == 34) + jjstateSet[jjnewStateCnt++] = 1; + break; + default : break; + } + } while(i != startsAt); + } + else if (curChar < 128) + { + long l = 1L << (curChar & 077); + do + { + switch(jjstateSet[--i]) + { + case 0: + kind = 95; + break; + default : break; + } + } while(i != startsAt); + } + else + { + int i2 = (curChar & 0xff) >> 6; + long l2 = 1L << (curChar & 077); + do + { + switch(jjstateSet[--i]) + { + case 0: + if ((jjbitVec0[i2] & l2) != 0L && kind > 95) + kind = 95; + break; + default : break; + } + } while(i != startsAt); + } + if (kind != 0x7fffffff) + { + jjmatchedKind = kind; + jjmatchedPos = curPos; + kind = 0x7fffffff; + } + ++curPos; + if ((i = jjnewStateCnt) == (startsAt = 3 - (jjnewStateCnt = startsAt))) + return curPos; + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { return curPos; } + } +} +private final int jjStopStringLiteralDfa_0(int pos, long active0, long active1) +{ + switch (pos) + { + case 0: + if ((active0 & 0xefff1ffdffb40000L) != 0L || (active1 & 0xf0fff4L) != 0L) + { + jjmatchedKind = 97; + return 37; + } + if ((active0 & 0x1000a00200400000L) != 0L || (active1 & 0xf0002L) != 0L) + { + jjmatchedKind = 97; + return 16; + } + if ((active0 & 0x10L) != 0L) + return 38; + if ((active0 & 0x400000000000L) != 0L || (active1 & 0x9L) != 0L) + { + jjmatchedKind = 97; + return 13; + } + if ((active0 & 0xc000L) != 0L) + return 3; + if ((active0 & 0x200L) != 0L) + return 19; + return -1; + case 1: + if ((active0 & 0xf7ffceebbeb40000L) != 0L || (active1 & 0xfdfdfeL) != 0L) + { + if (jjmatchedPos != 1) + { + jjmatchedKind = 97; + jjmatchedPos = 1; + } + return 37; + } + if ((active0 & 0x800311441400000L) != 0L || (active1 & 0x20200L) != 0L) + return 37; + if ((active1 & 0x1L) != 0L) + { + if (jjmatchedPos != 1) + { + jjmatchedKind = 97; + jjmatchedPos = 1; + } + return 12; + } + return -1; + case 2: + if ((active1 & 0x1L) != 0L) + { + if (jjmatchedPos != 2) + { + jjmatchedKind = 97; + jjmatchedPos = 2; + } + return 11; + } + if ((active0 & 0x17a00a00100000L) != 0L || (active1 & 0xf001d2L) != 0L) + return 37; + if ((active0 & 0xffe85ee1bfa40000L) != 0L || (active1 & 0xffc2cL) != 0L) + { + if (jjmatchedPos != 2) + { + jjmatchedKind = 97; + jjmatchedPos = 2; + } + return 37; + } + return -1; + case 3: + if ((active0 & 0xefe81e4187840000L) != 0L || (active1 & 0xac2cL) != 0L) + { + if (jjmatchedPos != 3) + { + jjmatchedKind = 97; + jjmatchedPos = 3; + } + return 37; + } + if ((active0 & 0x100040a038200000L) != 0L || (active1 & 0xf5000L) != 0L) + return 37; + if ((active1 & 0x80L) != 0L) + { + if (jjmatchedPos != 3) + { + jjmatchedKind = 97; + jjmatchedPos = 3; + } + return 21; + } + if ((active1 & 0x1L) != 0L) + { + if (jjmatchedPos != 3) + { + jjmatchedKind = 97; + jjmatchedPos = 3; + } + return 10; + } + return -1; + case 4: + if ((active0 & 0xef601e4000840000L) != 0L || (active1 & 0x880dL) != 0L) + { + jjmatchedKind = 97; + jjmatchedPos = 4; + return 37; + } + if ((active0 & 0x88000187000000L) != 0L || (active1 & 0x2420L) != 0L) + return 37; + if ((active1 & 0x80080L) != 0L) + return 21; + return -1; + case 5: + if ((active0 & 0x2400a0000040000L) != 0L) + return 37; + if ((active0 & 0x6000000000000000L) != 0L) + return 21; + if ((active0 & 0x8d20004000800000L) != 0L || (active1 & 0x880dL) != 0L) + { + jjmatchedKind = 97; + jjmatchedPos = 5; + return 37; + } + if ((active0 & 0x140000000000L) != 0L) + { + if (jjmatchedPos < 4) + { + jjmatchedKind = 97; + jjmatchedPos = 4; + } + return -1; + } + return -1; + case 6: + if ((active0 & 0x8c20000000000000L) != 0L || (active1 & 0x8001L) != 0L) + { + jjmatchedKind = 97; + jjmatchedPos = 6; + return 37; + } + if ((active0 & 0x100004000800000L) != 0L || (active1 & 0x80cL) != 0L) + return 37; + if ((active0 & 0x140000000000L) != 0L) + { + if (jjmatchedPos < 4) + { + jjmatchedKind = 97; + jjmatchedPos = 4; + } + return -1; + } + return -1; + case 7: + if ((active0 & 0x800000000000000L) != 0L) + { + jjmatchedKind = 97; + jjmatchedPos = 7; + return 37; + } + if ((active0 & 0x8420000000000000L) != 0L || (active1 & 0x8001L) != 0L) + return 37; + if ((active0 & 0x140000000000L) != 0L) + { + if (jjmatchedPos < 4) + { + jjmatchedKind = 97; + jjmatchedPos = 4; + } + return -1; + } + return -1; + case 8: + if ((active0 & 0x800000000000000L) != 0L) + { + jjmatchedKind = 97; + jjmatchedPos = 8; + return 37; + } + return -1; + default : + return -1; + } +} +private final int jjStartNfa_0(int pos, long active0, long active1) +{ + return jjMoveNfa_0(jjStopStringLiteralDfa_0(pos, active0, active1), pos + 1); +} +private int jjMoveStringLiteralDfa0_0() +{ + switch(curChar) + { + case 34: + return jjStopAtPos(0, 94); + case 39: + return jjStopAtPos(0, 91); + case 40: + return jjStopAtPos(0, 2); + case 41: + return jjStopAtPos(0, 3); + case 42: + return jjStopAtPos(0, 10); + case 43: + return jjStopAtPos(0, 8); + case 44: + return jjStopAtPos(0, 5); + case 45: + return jjStartNfaWithStates_0(0, 9, 19); + case 46: + return jjStartNfaWithStates_0(0, 4, 38); + case 47: + return jjStopAtPos(0, 11); + case 59: + return jjStopAtPos(0, 6); + case 60: + jjmatchedKind = 14; + return jjMoveStringLiteralDfa1_0(0x8000L, 0x0L); + case 61: + return jjStopAtPos(0, 12); + case 62: + jjmatchedKind = 16; + return jjMoveStringLiteralDfa1_0(0x20000L, 0x0L); + case 65: + case 97: + return jjMoveStringLiteralDfa1_0(0x1000a00200400000L, 0xf0002L); + case 66: + case 98: + return jjMoveStringLiteralDfa1_0(0x10004000000000L, 0x0L); + case 67: + case 99: + return jjMoveStringLiteralDfa1_0(0xe468000000000000L, 0x300004L); + case 68: + case 100: + return jjMoveStringLiteralDfa1_0(0x400000000000L, 0x9L); + case 69: + case 101: + return jjMoveStringLiteralDfa1_0(0x20000000000L, 0x10L); + case 70: + case 102: + return jjMoveStringLiteralDfa1_0(0x10200000L, 0x20L); + case 71: + case 103: + return jjMoveStringLiteralDfa1_0(0x40000000000L, 0x0L); + case 72: + case 104: + return jjMoveStringLiteralDfa1_0(0x80000000000L, 0x0L); + case 73: + case 105: + return jjMoveStringLiteralDfa1_0(0x800011001000000L, 0x0L); + case 74: + case 106: + return jjMoveStringLiteralDfa1_0(0x20000000L, 0x0L); + case 76: + case 108: + return jjMoveStringLiteralDfa1_0(0x8008000000L, 0xc0L); + case 77: + case 109: + return jjMoveStringLiteralDfa1_0(0x3000000000000L, 0x100L); + case 78: + case 110: + return jjMoveStringLiteralDfa1_0(0x2800800000L, 0x0L); + case 79: + case 111: + return jjMoveStringLiteralDfa1_0(0x100442000000L, 0x0L); + case 80: + case 112: + return jjMoveStringLiteralDfa1_0(0x180000000000000L, 0x600L); + case 82: + case 114: + return jjMoveStringLiteralDfa1_0(0x200000004000000L, 0x3800L); + case 83: + case 115: + return jjMoveStringLiteralDfa1_0(0x4000000040000L, 0x404000L); + case 84: + case 116: + return jjMoveStringLiteralDfa1_0(0x100000L, 0x808000L); + case 85: + case 117: + return jjMoveStringLiteralDfa1_0(0x80000000L, 0x0L); + case 87: + case 119: + return jjMoveStringLiteralDfa1_0(0x100000000L, 0x0L); + case 124: + return jjMoveStringLiteralDfa1_0(0x80L, 0x0L); + default : + return jjMoveNfa_0(0, 0); + } +} +private int jjMoveStringLiteralDfa1_0(long active0, long active1) +{ + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + jjStopStringLiteralDfa_0(0, active0, active1); + return 1; + } + switch(curChar) + { + case 61: + if ((active0 & 0x8000L) != 0L) + return jjStopAtPos(1, 15); + else if ((active0 & 0x20000L) != 0L) + return jjStopAtPos(1, 17); + break; + case 65: + case 97: + return jjMoveStringLiteralDfa2_0(active0, 0x1080000800000L, active1, 0x801800L); + case 66: + case 98: + return jjMoveStringLiteralDfa2_0(active0, 0L, active1, 0x2L); + case 67: + case 99: + return jjMoveStringLiteralDfa2_0(active0, 0L, active1, 0x10000L); + case 69: + case 101: + return jjMoveStringLiteralDfa2_0(active0, 0x220404008040000L, active1, 0xcL); + case 72: + case 104: + return jjMoveStringLiteralDfa2_0(active0, 0x100000000L, active1, 0L); + case 73: + case 105: + if ((active1 & 0x200L) != 0L) + return jjStartNfaWithStates_0(1, 73, 37); + return jjMoveStringLiteralDfa2_0(active0, 0x42008004000000L, active1, 0x400001L); + case 76: + case 108: + return jjMoveStringLiteralDfa2_0(active0, 0L, active1, 0x20L); + case 78: + case 110: + if ((active0 & 0x40000000L) != 0L) + return jjStartNfaWithStates_0(1, 30, 37); + else if ((active0 & 0x10000000000L) != 0L) + { + jjmatchedKind = 40; + jjmatchedPos = 1; + } + return jjMoveStringLiteralDfa2_0(active0, 0x800000201000000L, active1, 0L); + case 79: + case 111: + return jjMoveStringLiteralDfa2_0(active0, 0xe598000820100000L, active1, 0x3025c0L); + case 81: + case 113: + return jjMoveStringLiteralDfa2_0(active0, 0L, active1, 0x4000L); + case 82: + case 114: + if ((active0 & 0x400000000L) != 0L) + { + jjmatchedKind = 34; + jjmatchedPos = 1; + } + return jjMoveStringLiteralDfa2_0(active0, 0x1000140000200000L, active1, 0x8000L); + case 83: + case 115: + if ((active0 & 0x400000L) != 0L) + { + jjmatchedKind = 22; + jjmatchedPos = 1; + } + else if ((active0 & 0x1000000000L) != 0L) + return jjStartNfaWithStates_0(1, 36, 37); + return jjMoveStringLiteralDfa2_0(active0, 0x200080000000L, active1, 0x20000L); + case 84: + case 116: + return jjMoveStringLiteralDfa2_0(active0, 0L, active1, 0xc0000L); + case 85: + case 117: + return jjMoveStringLiteralDfa2_0(active0, 0x4002012000000L, active1, 0L); + case 86: + case 118: + return jjMoveStringLiteralDfa2_0(active0, 0x800000000000L, active1, 0L); + case 88: + case 120: + return jjMoveStringLiteralDfa2_0(active0, 0x20000000000L, active1, 0x10L); + case 124: + if ((active0 & 0x80L) != 0L) + return jjStopAtPos(1, 7); + break; + default : + break; + } + return jjStartNfa_0(0, active0, active1); +} +private int jjMoveStringLiteralDfa2_0(long old0, long active0, long old1, long active1) +{ + if (((active0 &= old0) | (active1 &= old1)) == 0L) + return jjStartNfa_0(0, old0, old1); + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + jjStopStringLiteralDfa_0(1, active0, active1); + return 2; + } + switch(curChar) + { + case 65: + case 97: + return jjMoveStringLiteralDfa3_0(active0, 0L, active1, 0xc0000L); + case 67: + case 99: + if ((active0 & 0x200000000000L) != 0L) + return jjStartNfaWithStates_0(2, 45, 37); + break; + case 68: + case 100: + if ((active0 & 0x200000000L) != 0L) + return jjStartNfaWithStates_0(2, 33, 37); + else if ((active1 & 0x100L) != 0L) + return jjStartNfaWithStates_0(2, 72, 37); + return jjMoveStringLiteralDfa3_0(active0, 0x100000000000L, active1, 0x800L); + case 69: + case 101: + return jjMoveStringLiteralDfa3_0(active0, 0x1000000100000000L, active1, 0L); + case 70: + case 102: + return jjMoveStringLiteralDfa3_0(active0, 0x8000000L, active1, 0L); + case 71: + case 103: + if ((active0 & 0x800000000000L) != 0L) + return jjStartNfaWithStates_0(2, 47, 37); + else if ((active1 & 0x40L) != 0L) + { + jjmatchedKind = 70; + jjmatchedPos = 2; + } + return jjMoveStringLiteralDfa3_0(active0, 0x200000004000000L, active1, 0x88L); + case 73: + case 105: + return jjMoveStringLiteralDfa3_0(active0, 0x800200a0000000L, active1, 0x20004L); + case 75: + case 107: + return jjMoveStringLiteralDfa3_0(active0, 0x8000000000L, active1, 0L); + case 76: + case 108: + return jjMoveStringLiteralDfa3_0(active0, 0x100002010040000L, active1, 0L); + case 77: + case 109: + if ((active0 & 0x4000000000000L) != 0L) + return jjStartNfaWithStates_0(2, 50, 37); + break; + case 78: + case 110: + if ((active0 & 0x2000000000000L) != 0L) + return jjStartNfaWithStates_0(2, 49, 37); + else if ((active1 & 0x400000L) != 0L) + return jjStartNfaWithStates_0(2, 86, 37); + else if ((active1 & 0x800000L) != 0L) + return jjStartNfaWithStates_0(2, 87, 37); + return jjMoveStringLiteralDfa3_0(active0, 0x420000001000000L, active1, 0x1000L); + case 79: + case 111: + return jjMoveStringLiteralDfa3_0(active0, 0xe000040000200000L, active1, 0x10020L); + case 80: + case 112: + if ((active0 & 0x100000L) != 0L) + return jjStartNfaWithStates_0(2, 20, 37); + else if ((active1 & 0x10L) != 0L) + return jjStartNfaWithStates_0(2, 68, 37); + break; + case 82: + case 114: + return jjMoveStringLiteralDfa3_0(active0, 0x40000000000000L, active1, 0x4000L); + case 83: + case 115: + if ((active1 & 0x2L) != 0L) + return jjStartNfaWithStates_0(2, 65, 37); + else if ((active1 & 0x100000L) != 0L) + return jjStartNfaWithStates_0(2, 84, 37); + return jjMoveStringLiteralDfa3_0(active0, 0x400000000000L, active1, 0x1L); + case 84: + case 116: + if ((active0 & 0x800000000L) != 0L) + return jjStartNfaWithStates_0(2, 35, 37); + else if ((active1 & 0x200000L) != 0L) + return jjStartNfaWithStates_0(2, 85, 37); + return jjMoveStringLiteralDfa3_0(active0, 0x800004002800000L, active1, 0L); + case 85: + case 117: + return jjMoveStringLiteralDfa3_0(active0, 0x8000000000000L, active1, 0xa000L); + case 86: + case 118: + return jjMoveStringLiteralDfa3_0(active0, 0x80000000000L, active1, 0L); + case 87: + case 119: + return jjMoveStringLiteralDfa3_0(active0, 0L, active1, 0x400L); + case 88: + case 120: + if ((active0 & 0x1000000000000L) != 0L) + return jjStartNfaWithStates_0(2, 48, 37); + else if ((active0 & 0x10000000000000L) != 0L) + return jjStartNfaWithStates_0(2, 52, 37); + break; + default : + break; + } + return jjStartNfa_0(1, active0, active1); +} +private int jjMoveStringLiteralDfa3_0(long old0, long active0, long old1, long active1) +{ + if (((active0 &= old0) | (active1 &= old1)) == 0L) + return jjStartNfa_0(1, old0, old1); + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + jjStopStringLiteralDfa_0(2, active0, active1); + return 3; + } + switch(curChar) + { + case 49: + return jjMoveStringLiteralDfa4_0(active0, 0L, active1, 0x80L); + case 65: + case 97: + if ((active0 & 0x1000000000000000L) != 0L) + return jjStartNfaWithStates_0(3, 60, 37); + break; + case 67: + case 99: + if ((active0 & 0x400000000000L) != 0L) + return jjStartNfaWithStates_0(3, 46, 37); + return jjMoveStringLiteralDfa4_0(active0, 0x40000000000000L, active1, 0L); + case 68: + case 100: + if ((active1 & 0x1000L) != 0L) + return jjStartNfaWithStates_0(3, 76, 37); + break; + case 69: + case 101: + if ((active0 & 0x8000000000L) != 0L) + return jjStartNfaWithStates_0(3, 39, 37); + return jjMoveStringLiteralDfa4_0(active0, 0x800100003040000L, active1, 0x400L); + case 72: + case 104: + return jjMoveStringLiteralDfa4_0(active0, 0x4000000L, active1, 0L); + case 73: + case 105: + return jjMoveStringLiteralDfa4_0(active0, 0x200080000000000L, active1, 0x800L); + case 76: + case 108: + if ((active0 & 0x10000000L) != 0L) + return jjStartNfaWithStates_0(3, 28, 37); + else if ((active0 & 0x2000000000L) != 0L) + return jjStartNfaWithStates_0(3, 37, 37); + return jjMoveStringLiteralDfa4_0(active0, 0L, active1, 0x4L); + case 77: + case 109: + if ((active0 & 0x200000L) != 0L) + return jjStartNfaWithStates_0(3, 21, 37); + break; + case 78: + case 110: + if ((active0 & 0x20000000L) != 0L) + return jjStartNfaWithStates_0(3, 29, 37); + else if ((active1 & 0x20000L) != 0L) + return jjStartNfaWithStates_0(3, 81, 37); + else if ((active1 & 0x40000L) != 0L) + { + jjmatchedKind = 82; + jjmatchedPos = 3; + } + return jjMoveStringLiteralDfa4_0(active0, 0x88000080000000L, active1, 0x8a000L); + case 79: + case 111: + return jjMoveStringLiteralDfa4_0(active0, 0L, active1, 0x20L); + case 82: + case 114: + return jjMoveStringLiteralDfa4_0(active0, 0xe000000100000000L, active1, 0x8L); + case 83: + case 115: + if ((active1 & 0x10000L) != 0L) + return jjStartNfaWithStates_0(3, 80, 37); + return jjMoveStringLiteralDfa4_0(active0, 0x20000000000L, active1, 0L); + case 84: + case 116: + if ((active0 & 0x8000000L) != 0L) + return jjStartNfaWithStates_0(3, 27, 37); + else if ((active1 & 0x4000L) != 0L) + return jjStartNfaWithStates_0(3, 78, 37); + return jjMoveStringLiteralDfa4_0(active0, 0x420000000000000L, active1, 0x1L); + case 85: + case 117: + return jjMoveStringLiteralDfa4_0(active0, 0x40000800000L, active1, 0L); + case 87: + case 119: + return jjMoveStringLiteralDfa4_0(active0, 0x4000000000L, active1, 0L); + case 89: + case 121: + return jjMoveStringLiteralDfa4_0(active0, 0x100000000000000L, active1, 0L); + default : + break; + } + return jjStartNfa_0(2, active0, active1); +} +private int jjMoveStringLiteralDfa4_0(long old0, long active0, long old1, long active1) +{ + if (((active0 &= old0) | (active1 &= old1)) == 0L) + return jjStartNfa_0(2, old0, old1); + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + jjStopStringLiteralDfa_0(3, active0, active1); + return 4; + } + switch(curChar) + { + case 48: + if ((active1 & 0x80L) != 0L) + return jjStartNfaWithStates_0(4, 71, 21); + break; + case 50: + if ((active1 & 0x80000L) != 0L) + return jjStartNfaWithStates_0(4, 83, 21); + break; + case 65: + case 97: + return jjMoveStringLiteralDfa5_0(active0, 0x400000000000000L, active1, 0x801L); + case 67: + case 99: + return jjMoveStringLiteralDfa5_0(active0, 0x40000L, active1, 0x8000L); + case 68: + case 100: + if ((active1 & 0x2000L) != 0L) + return jjStartNfaWithStates_0(4, 77, 37); + return jjMoveStringLiteralDfa5_0(active0, 0xe000000000000000L, active1, 0L); + case 69: + case 101: + if ((active0 & 0x100000000L) != 0L) + return jjStartNfaWithStates_0(4, 32, 37); + return jjMoveStringLiteralDfa5_0(active0, 0x4000000000L, active1, 0x8L); + case 71: + case 103: + if ((active0 & 0x80000000L) != 0L) + return jjStartNfaWithStates_0(4, 31, 37); + return jjMoveStringLiteralDfa5_0(active0, 0x100000000000000L, active1, 0L); + case 73: + case 105: + return jjMoveStringLiteralDfa5_0(active0, 0L, active1, 0x4L); + case 76: + case 108: + return jjMoveStringLiteralDfa5_0(active0, 0x40000000000000L, active1, 0L); + case 78: + case 110: + return jjMoveStringLiteralDfa5_0(active0, 0x80000000000L, active1, 0L); + case 79: + case 111: + return jjMoveStringLiteralDfa5_0(active0, 0x200000000000000L, active1, 0L); + case 80: + case 112: + return jjMoveStringLiteralDfa5_0(active0, 0x40000000000L, active1, 0L); + case 82: + case 114: + if ((active0 & 0x1000000L) != 0L) + return jjStartNfaWithStates_0(4, 24, 37); + else if ((active0 & 0x2000000L) != 0L) + return jjStartNfaWithStates_0(4, 25, 37); + else if ((active1 & 0x20L) != 0L) + return jjStartNfaWithStates_0(4, 69, 37); + else if ((active1 & 0x400L) != 0L) + return jjStartNfaWithStates_0(4, 74, 37); + return jjMoveStringLiteralDfa5_0(active0, 0x820100000800000L, active1, 0L); + case 84: + case 116: + if ((active0 & 0x4000000L) != 0L) + return jjStartNfaWithStates_0(4, 26, 37); + else if ((active0 & 0x8000000000000L) != 0L) + return jjStartNfaWithStates_0(4, 51, 37); + else if ((active0 & 0x80000000000000L) != 0L) + return jjStartNfaWithStates_0(4, 55, 37); + return jjMoveStringLiteralDfa5_0(active0, 0x20000000000L, active1, 0L); + default : + break; + } + return jjStartNfa_0(3, active0, active1); +} +private int jjMoveStringLiteralDfa5_0(long old0, long active0, long old1, long active1) +{ + if (((active0 &= old0) | (active1 &= old1)) == 0L) + return jjStartNfa_0(3, old0, old1); + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + jjStopStringLiteralDfa_0(4, active0, active1); + return 5; + } + switch(curChar) + { + case 32: + return jjMoveStringLiteralDfa6_0(active0, 0x140000000000L, active1, 0L); + case 49: + if ((active0 & 0x2000000000000000L) != 0L) + return jjStartNfaWithStates_0(5, 61, 21); + break; + case 50: + if ((active0 & 0x4000000000000000L) != 0L) + return jjStartNfaWithStates_0(5, 62, 21); + break; + case 65: + case 97: + return jjMoveStringLiteralDfa6_0(active0, 0x800000L, active1, 0x8000L); + case 69: + case 101: + if ((active0 & 0x40000000000000L) != 0L) + return jjStartNfaWithStates_0(5, 54, 37); + return jjMoveStringLiteralDfa6_0(active0, 0x4000000000L, active1, 0x8L); + case 71: + case 103: + if ((active0 & 0x80000000000L) != 0L) + return jjStartNfaWithStates_0(5, 43, 37); + break; + case 73: + case 105: + return jjMoveStringLiteralDfa6_0(active0, 0x400000000000000L, active1, 0L); + case 78: + case 110: + if ((active0 & 0x200000000000000L) != 0L) + return jjStartNfaWithStates_0(5, 57, 37); + return jjMoveStringLiteralDfa6_0(active0, 0L, active1, 0x805L); + case 79: + case 111: + return jjMoveStringLiteralDfa6_0(active0, 0x120000000000000L, active1, 0L); + case 83: + case 115: + if ((active0 & 0x20000000000L) != 0L) + return jjStartNfaWithStates_0(5, 41, 37); + return jjMoveStringLiteralDfa6_0(active0, 0x8800000000000000L, active1, 0L); + case 84: + case 116: + if ((active0 & 0x40000L) != 0L) + return jjStartNfaWithStates_0(5, 18, 37); + break; + default : + break; + } + return jjStartNfa_0(4, active0, active1); +} +private int jjMoveStringLiteralDfa6_0(long old0, long active0, long old1, long active1) +{ + if (((active0 &= old0) | (active1 &= old1)) == 0L) + return jjStartNfa_0(4, old0, old1); + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + jjStopStringLiteralDfa_0(5, active0, active1); + return 6; + } + switch(curChar) + { + case 66: + case 98: + return jjMoveStringLiteralDfa7_0(active0, 0x140000000000L, active1, 0L); + case 67: + case 99: + return jjMoveStringLiteralDfa7_0(active0, 0L, active1, 0x1L); + case 69: + case 101: + return jjMoveStringLiteralDfa7_0(active0, 0x800000000000000L, active1, 0L); + case 71: + case 103: + if ((active1 & 0x4L) != 0L) + return jjStartNfaWithStates_0(6, 66, 37); + break; + case 73: + case 105: + return jjMoveStringLiteralDfa7_0(active0, 0x20000000000000L, active1, 0L); + case 76: + case 108: + if ((active0 & 0x800000L) != 0L) + return jjStartNfaWithStates_0(6, 23, 37); + break; + case 78: + case 110: + if ((active0 & 0x4000000000L) != 0L) + return jjStartNfaWithStates_0(6, 38, 37); + else if ((active0 & 0x100000000000000L) != 0L) + return jjStartNfaWithStates_0(6, 56, 37); + return jjMoveStringLiteralDfa7_0(active0, 0x400000000000000L, active1, 0L); + case 83: + case 115: + if ((active1 & 0x8L) != 0L) + return jjStartNfaWithStates_0(6, 67, 37); + else if ((active1 & 0x800L) != 0L) + return jjStartNfaWithStates_0(6, 75, 37); + break; + case 84: + case 116: + return jjMoveStringLiteralDfa7_0(active0, 0L, active1, 0x8000L); + case 89: + case 121: + return jjMoveStringLiteralDfa7_0(active0, 0x8000000000000000L, active1, 0L); + default : + break; + } + return jjStartNfa_0(5, active0, active1); +} +private int jjMoveStringLiteralDfa7_0(long old0, long active0, long old1, long active1) +{ + if (((active0 &= old0) | (active1 &= old1)) == 0L) + return jjStartNfa_0(5, old0, old1); + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + jjStopStringLiteralDfa_0(6, active0, active1); + return 7; + } + switch(curChar) + { + case 67: + case 99: + return jjMoveStringLiteralDfa8_0(active0, 0x800000000000000L, active1, 0L); + case 68: + case 100: + if ((active0 & 0x20000000000000L) != 0L) + return jjStartNfaWithStates_0(7, 53, 37); + break; + case 69: + case 101: + if ((active1 & 0x1L) != 0L) + return jjStartNfaWithStates_0(7, 64, 37); + else if ((active1 & 0x8000L) != 0L) + return jjStartNfaWithStates_0(7, 79, 37); + break; + case 83: + case 115: + if ((active0 & 0x400000000000000L) != 0L) + return jjStartNfaWithStates_0(7, 58, 37); + else if ((active0 & 0x8000000000000000L) != 0L) + return jjStartNfaWithStates_0(7, 63, 37); + break; + case 89: + case 121: + if ((active0 & 0x40000000000L) != 0L) + return jjStopAtPos(7, 42); + else if ((active0 & 0x100000000000L) != 0L) + return jjStopAtPos(7, 44); + break; + default : + break; + } + return jjStartNfa_0(6, active0, active1); +} +private int jjMoveStringLiteralDfa8_0(long old0, long active0, long old1, long active1) +{ + if (((active0 &= old0) | (active1 &= old1)) == 0L) + return jjStartNfa_0(6, old0, old1); + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + jjStopStringLiteralDfa_0(7, active0, 0L); + return 8; + } + switch(curChar) + { + case 84: + case 116: + return jjMoveStringLiteralDfa9_0(active0, 0x800000000000000L); + default : + break; + } + return jjStartNfa_0(7, active0, 0L); +} +private int jjMoveStringLiteralDfa9_0(long old0, long active0) +{ + if (((active0 &= old0)) == 0L) + return jjStartNfa_0(7, old0, 0L); + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + jjStopStringLiteralDfa_0(8, active0, 0L); + return 9; + } + switch(curChar) + { + case 83: + case 115: + if ((active0 & 0x800000000000000L) != 0L) + return jjStartNfaWithStates_0(9, 59, 37); + break; + default : + break; + } + return jjStartNfa_0(8, active0, 0L); +} +private int jjStartNfaWithStates_0(int pos, int kind, int state) +{ + jjmatchedKind = kind; + jjmatchedPos = pos; + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { return pos + 1; } + return jjMoveNfa_0(state, pos + 1); +} +private int jjMoveNfa_0(int startState, int curPos) +{ + int startsAt = 0; + jjnewStateCnt = 37; + int i = 1; + jjstateSet[0] = startState; + int kind = 0x7fffffff; + for (;;) + { + if (++jjround == 0x7fffffff) + ReInitRounds(); + if (curChar < 64) + { + long l = 1L << curChar; + do + { + switch(jjstateSet[--i]) + { + case 12: + case 21: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 97) + kind = 97; + jjCheckNAdd(21); + break; + case 38: + if ((0x3ff000000000000L & l) != 0L) + { + if (kind > 100) + kind = 100; + jjCheckNAdd(27); + } + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddTwoStates(23, 24); + break; + case 37: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 97) + kind = 97; + jjCheckNAdd(21); + break; + case 0: + if ((0x3ff000000000000L & l) != 0L) + { + if (kind > 101) + kind = 101; + jjCheckNAddStates(0, 6); + } + else if ((0x100002600L & l) != 0L) + { + if (kind > 1) + kind = 1; + } + else if (curChar == 46) + jjCheckNAddTwoStates(23, 27); + else if (curChar == 45) + jjCheckNAdd(19); + else if (curChar == 33) + jjstateSet[jjnewStateCnt++] = 5; + else if (curChar == 60) + jjstateSet[jjnewStateCnt++] = 3; + if (curChar == 13) + jjstateSet[jjnewStateCnt++] = 1; + break; + case 11: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 97) + kind = 97; + jjCheckNAdd(21); + break; + case 16: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 97) + kind = 97; + jjCheckNAdd(21); + break; + case 13: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 97) + kind = 97; + jjCheckNAdd(21); + break; + case 10: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 97) + kind = 97; + jjCheckNAdd(21); + break; + case 1: + if (curChar == 10 && kind > 1) + kind = 1; + break; + case 2: + if (curChar == 13) + jjstateSet[jjnewStateCnt++] = 1; + break; + case 3: + if (curChar == 62) + kind = 13; + break; + case 4: + if (curChar == 60) + jjstateSet[jjnewStateCnt++] = 3; + break; + case 5: + if (curChar == 61) + kind = 13; + break; + case 6: + if (curChar == 33) + jjstateSet[jjnewStateCnt++] = 5; + break; + case 18: + if (curChar == 45) + jjCheckNAdd(19); + break; + case 19: + if (curChar != 45) + break; + if (kind > 88) + kind = 88; + jjCheckNAdd(19); + break; + case 22: + if (curChar == 46) + jjCheckNAddTwoStates(23, 27); + break; + case 23: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddTwoStates(23, 24); + break; + case 25: + if ((0x280000000000L & l) != 0L) + jjCheckNAdd(26); + break; + case 26: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 99) + kind = 99; + jjCheckNAdd(26); + break; + case 27: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 100) + kind = 100; + jjCheckNAdd(27); + break; + case 28: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 101) + kind = 101; + jjCheckNAddStates(0, 6); + break; + case 29: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddTwoStates(29, 24); + break; + case 30: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddTwoStates(30, 31); + break; + case 31: + if (curChar == 46) + jjCheckNAddTwoStates(32, 24); + break; + case 32: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddTwoStates(32, 24); + break; + case 33: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddTwoStates(33, 34); + break; + case 34: + if (curChar != 46) + break; + if (kind > 100) + kind = 100; + jjCheckNAdd(35); + break; + case 35: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 100) + kind = 100; + jjCheckNAdd(35); + break; + case 36: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 101) + kind = 101; + jjCheckNAdd(36); + break; + default : break; + } + } while(i != startsAt); + } + else if (curChar < 128) + { + long l = 1L << (curChar & 077); + do + { + switch(jjstateSet[--i]) + { + case 12: + if ((0x7fffffe87fffffeL & l) != 0L) + { + if (kind > 97) + kind = 97; + jjCheckNAdd(21); + } + if ((0x7fffffe07fffffeL & l) != 0L) + { + if (kind > 97) + kind = 97; + jjCheckNAddTwoStates(20, 21); + } + if ((0x8000000080000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 11; + break; + case 37: + if ((0x7fffffe87fffffeL & l) != 0L) + { + if (kind > 97) + kind = 97; + jjCheckNAdd(21); + } + if ((0x7fffffe07fffffeL & l) != 0L) + { + if (kind > 97) + kind = 97; + jjCheckNAddTwoStates(20, 21); + } + break; + case 0: + if ((0x7fffffe07fffffeL & l) != 0L) + { + if (kind > 97) + kind = 97; + jjCheckNAddTwoStates(20, 21); + } + if ((0x200000002L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 16; + else if ((0x1000000010L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 13; + break; + case 11: + if ((0x7fffffe87fffffeL & l) != 0L) + { + if (kind > 97) + kind = 97; + jjCheckNAdd(21); + } + if ((0x7fffffe07fffffeL & l) != 0L) + { + if (kind > 97) + kind = 97; + jjCheckNAddTwoStates(20, 21); + } + if ((0x10000000100000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 10; + break; + case 16: + if ((0x7fffffe87fffffeL & l) != 0L) + { + if (kind > 97) + kind = 97; + jjCheckNAdd(21); + } + if ((0x7fffffe07fffffeL & l) != 0L) + { + if (kind > 97) + kind = 97; + jjCheckNAddTwoStates(20, 21); + } + if ((0x100000001000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 15; + break; + case 13: + if ((0x7fffffe87fffffeL & l) != 0L) + { + if (kind > 97) + kind = 97; + jjCheckNAdd(21); + } + if ((0x7fffffe07fffffeL & l) != 0L) + { + if (kind > 97) + kind = 97; + jjCheckNAddTwoStates(20, 21); + } + if ((0x20000000200L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 12; + break; + case 10: + if ((0x7fffffe87fffffeL & l) != 0L) + { + if (kind > 97) + kind = 97; + jjCheckNAdd(21); + } + if ((0x7fffffe07fffffeL & l) != 0L) + { + if (kind > 97) + kind = 97; + jjCheckNAddTwoStates(20, 21); + } + if ((0x20000000200L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 9; + break; + case 7: + if ((0x10000000100000L & l) != 0L && kind > 19) + kind = 19; + break; + case 8: + if ((0x800000008L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 7; + break; + case 9: + if ((0x400000004000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 8; + break; + case 14: + if ((0x1000000010L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 13; + break; + case 15: + if ((0x100000001000L & l) != 0L && kind > 19) + kind = 19; + break; + case 17: + if ((0x200000002L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 16; + break; + case 20: + if ((0x7fffffe07fffffeL & l) == 0L) + break; + if (kind > 97) + kind = 97; + jjCheckNAddTwoStates(20, 21); + break; + case 21: + if ((0x7fffffe87fffffeL & l) == 0L) + break; + if (kind > 97) + kind = 97; + jjCheckNAdd(21); + break; + case 24: + if ((0x2000000020L & l) != 0L) + jjAddStates(7, 8); + break; + default : break; + } + } while(i != startsAt); + } + else + { + int i2 = (curChar & 0xff) >> 6; + long l2 = 1L << (curChar & 077); + do + { + switch(jjstateSet[--i]) + { + default : break; + } + } while(i != startsAt); + } + if (kind != 0x7fffffff) + { + jjmatchedKind = kind; + jjmatchedPos = curPos; + kind = 0x7fffffff; + } + ++curPos; + if ((i = jjnewStateCnt) == (startsAt = 37 - (jjnewStateCnt = startsAt))) + return curPos; + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { return curPos; } + } +} +private final int jjStopStringLiteralDfa_2(int pos, long active0, long active1) +{ + switch (pos) + { + default : + return -1; + } +} +private final int jjStartNfa_2(int pos, long active0, long active1) +{ + return jjMoveNfa_2(jjStopStringLiteralDfa_2(pos, active0, active1), pos + 1); +} +private int jjMoveStringLiteralDfa0_2() +{ + switch(curChar) + { + case 39: + return jjStartNfaWithStates_2(0, 93, 1); + default : + return jjMoveNfa_2(0, 0); + } +} +private int jjStartNfaWithStates_2(int pos, int kind, int state) +{ + jjmatchedKind = kind; + jjmatchedPos = pos; + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { return pos + 1; } + return jjMoveNfa_2(state, pos + 1); +} +private int jjMoveNfa_2(int startState, int curPos) +{ + int startsAt = 0; + jjnewStateCnt = 3; + int i = 1; + jjstateSet[0] = startState; + int kind = 0x7fffffff; + for (;;) + { + if (++jjround == 0x7fffffff) + ReInitRounds(); + if (curChar < 64) + { + long l = 1L << curChar; + do + { + switch(jjstateSet[--i]) + { + case 0: + if ((0xffffff7fffffffffL & l) != 0L) + { + if (kind > 92) + kind = 92; + } + else if (curChar == 39) + jjstateSet[jjnewStateCnt++] = 1; + break; + case 1: + if (curChar == 39 && kind > 92) + kind = 92; + break; + case 2: + if (curChar == 39) + jjstateSet[jjnewStateCnt++] = 1; + break; + default : break; + } + } while(i != startsAt); + } + else if (curChar < 128) + { + long l = 1L << (curChar & 077); + do + { + switch(jjstateSet[--i]) + { + case 0: + kind = 92; + break; + default : break; + } + } while(i != startsAt); + } + else + { + int i2 = (curChar & 0xff) >> 6; + long l2 = 1L << (curChar & 077); + do + { + switch(jjstateSet[--i]) + { + case 0: + if ((jjbitVec0[i2] & l2) != 0L && kind > 92) + kind = 92; + break; + default : break; + } + } while(i != startsAt); + } + if (kind != 0x7fffffff) + { + jjmatchedKind = kind; + jjmatchedPos = curPos; + kind = 0x7fffffff; + } + ++curPos; + if ((i = jjnewStateCnt) == (startsAt = 3 - (jjnewStateCnt = startsAt))) + return curPos; + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { return curPos; } + } +} +private int jjMoveStringLiteralDfa0_1() +{ + return jjMoveNfa_1(0, 0); +} +private int jjMoveNfa_1(int startState, int curPos) +{ + int startsAt = 0; + jjnewStateCnt = 3; + int i = 1; + jjstateSet[0] = startState; + int kind = 0x7fffffff; + for (;;) + { + if (++jjround == 0x7fffffff) + ReInitRounds(); + if (curChar < 64) + { + long l = 1L << curChar; + do + { + switch(jjstateSet[--i]) + { + case 0: + if ((0x2400L & l) != 0L) + { + if (kind > 89) + kind = 89; + } + if (curChar == 13) + jjstateSet[jjnewStateCnt++] = 1; + break; + case 1: + if (curChar == 10 && kind > 89) + kind = 89; + break; + case 2: + if (curChar == 13) + jjstateSet[jjnewStateCnt++] = 1; + break; + default : break; + } + } while(i != startsAt); + } + else if (curChar < 128) + { + long l = 1L << (curChar & 077); + do + { + switch(jjstateSet[--i]) + { + default : break; + } + } while(i != startsAt); + } + else + { + int i2 = (curChar & 0xff) >> 6; + long l2 = 1L << (curChar & 077); + do + { + switch(jjstateSet[--i]) + { + default : break; + } + } while(i != startsAt); + } + if (kind != 0x7fffffff) + { + jjmatchedKind = kind; + jjmatchedPos = curPos; + kind = 0x7fffffff; + } + ++curPos; + if ((i = jjnewStateCnt) == (startsAt = 3 - (jjnewStateCnt = startsAt))) + return curPos; + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { return curPos; } + } +} +static final int[] jjnextStates = { + 29, 30, 31, 24, 33, 34, 36, 25, 26, +}; - /** Constructor. */ - public ADQLParserTokenManager(SimpleCharStream stream, int lexState){ - this(stream); - SwitchTo(lexState); - } +/** Token literal values. */ +public static final String[] jjstrLiteralImages = { +"", null, "\50", "\51", "\56", "\54", "\73", "\174\174", "\53", "\55", "\52", +"\57", "\75", null, "\74", "\74\75", "\76", "\76\75", null, null, null, null, null, +null, null, null, null, null, null, null, null, null, null, null, null, null, null, +null, null, null, null, null, null, null, null, null, null, null, null, null, null, +null, null, null, null, null, null, null, null, null, null, null, null, null, null, +null, null, null, null, null, null, null, null, null, null, null, null, null, null, +null, null, null, null, null, null, null, null, null, null, null, null, null, null, +null, null, null, null, null, null, null, null, null, null, }; - /** Reinitialise parser. */ - public void ReInit(SimpleCharStream stream){ - jjmatchedPos = jjnewStateCnt = 0; - curLexState = defaultLexState; - input_stream = stream; - ReInitRounds(); - } +/** Lexer state names. */ +public static final String[] lexStateNames = { + "DEFAULT", + "WithinComment", + "WithinString", + "WithinDelimitedId", +}; - private void ReInitRounds(){ - int i; - jjround = 0x80000001; - for(i = 37; i-- > 0;) - jjrounds[i] = 0x80000000; - } +/** Lex State array. */ +public static final int[] jjnewLexState = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 0, -1, 2, -1, 0, 3, -1, 0, -1, -1, -1, + -1, -1, -1, +}; +static final long[] jjtoToken = { + 0xfffffffffffffffdL, 0x3b20ffffffL, +}; +static final long[] jjtoSkip = { + 0x2L, 0x2000000L, +}; +static final long[] jjtoMore = { + 0x0L, 0xdd000000L, +}; +protected SimpleCharStream input_stream; +private final int[] jjrounds = new int[37]; +private final int[] jjstateSet = new int[74]; +protected char curChar; +/** Constructor. */ +public ADQLParserTokenManager(SimpleCharStream stream){ + if (SimpleCharStream.staticFlag) + throw new Error("ERROR: Cannot use a static CharStream class with a non-static lexical analyzer."); + input_stream = stream; +} - /** Reinitialise parser. */ - public void ReInit(SimpleCharStream stream, int lexState){ - ReInit(stream); - SwitchTo(lexState); - } +/** Constructor. */ +public ADQLParserTokenManager(SimpleCharStream stream, int lexState){ + this(stream); + SwitchTo(lexState); +} - /** Switch to specified lex state. */ - public void SwitchTo(int lexState){ - if (lexState >= 4 || lexState < 0) - throw new TokenMgrError("Error: Ignoring invalid lexical state : " + lexState + ". State unchanged.", TokenMgrError.INVALID_LEXICAL_STATE); - else - curLexState = lexState; - } +/** Reinitialise parser. */ +public void ReInit(SimpleCharStream stream) +{ + jjmatchedPos = jjnewStateCnt = 0; + curLexState = defaultLexState; + input_stream = stream; + ReInitRounds(); +} +private void ReInitRounds() +{ + int i; + jjround = 0x80000001; + for (i = 37; i-- > 0;) + jjrounds[i] = 0x80000000; +} - protected Token jjFillToken(){ - final Token t; - final String curTokenImage; - final int beginLine; - final int endLine; - final int beginColumn; - final int endColumn; - String im = jjstrLiteralImages[jjmatchedKind]; - curTokenImage = (im == null) ? input_stream.GetImage() : im; - beginLine = input_stream.getBeginLine(); - beginColumn = input_stream.getBeginColumn(); - endLine = input_stream.getEndLine(); - endColumn = input_stream.getEndColumn(); - t = Token.newToken(jjmatchedKind, curTokenImage); +/** Reinitialise parser. */ +public void ReInit(SimpleCharStream stream, int lexState) +{ + ReInit(stream); + SwitchTo(lexState); +} - t.beginLine = beginLine; - t.endLine = endLine; - t.beginColumn = beginColumn; - t.endColumn = endColumn; +/** Switch to specified lex state. */ +public void SwitchTo(int lexState) +{ + if (lexState >= 4 || lexState < 0) + throw new TokenMgrError("Error: Ignoring invalid lexical state : " + lexState + ". State unchanged.", TokenMgrError.INVALID_LEXICAL_STATE); + else + curLexState = lexState; +} - return t; - } +protected Token jjFillToken() +{ + final Token t; + final String curTokenImage; + final int beginLine; + final int endLine; + final int beginColumn; + final int endColumn; + String im = jjstrLiteralImages[jjmatchedKind]; + curTokenImage = (im == null) ? input_stream.GetImage() : im; + beginLine = input_stream.getBeginLine(); + beginColumn = input_stream.getBeginColumn(); + endLine = input_stream.getEndLine(); + endColumn = input_stream.getEndColumn(); + t = Token.newToken(jjmatchedKind, curTokenImage); - int curLexState = 0; - int defaultLexState = 0; - int jjnewStateCnt; - int jjround; - int jjmatchedPos; - int jjmatchedKind; + t.beginLine = beginLine; + t.endLine = endLine; + t.beginColumn = beginColumn; + t.endColumn = endColumn; - /** Get the next Token. */ - public Token getNextToken(){ - Token matchedToken; - int curPos = 0; + return t; +} - EOFLoop: for(;;){ - try{ - curChar = input_stream.BeginToken(); - }catch(java.io.IOException e){ - jjmatchedKind = 0; - matchedToken = jjFillToken(); - return matchedToken; - } +int curLexState = 0; +int defaultLexState = 0; +int jjnewStateCnt; +int jjround; +int jjmatchedPos; +int jjmatchedKind; - for(;;){ - switch(curLexState){ - case 0: - jjmatchedKind = 0x7fffffff; - jjmatchedPos = 0; - curPos = jjMoveStringLiteralDfa0_0(); - break; - case 1: - jjmatchedKind = 0x7fffffff; - jjmatchedPos = 0; - curPos = jjMoveStringLiteralDfa0_1(); - if (jjmatchedPos == 0 && jjmatchedKind > 90){ - jjmatchedKind = 90; - } - break; - case 2: - jjmatchedKind = 0x7fffffff; - jjmatchedPos = 0; - curPos = jjMoveStringLiteralDfa0_2(); - break; - case 3: - jjmatchedKind = 0x7fffffff; - jjmatchedPos = 0; - curPos = jjMoveStringLiteralDfa0_3(); - break; - } - if (jjmatchedKind != 0x7fffffff){ - if (jjmatchedPos + 1 < curPos) - input_stream.backup(curPos - jjmatchedPos - 1); - if ((jjtoToken[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L){ - matchedToken = jjFillToken(); - if (jjnewLexState[jjmatchedKind] != -1) - curLexState = jjnewLexState[jjmatchedKind]; - return matchedToken; - }else if ((jjtoSkip[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L){ - if (jjnewLexState[jjmatchedKind] != -1) - curLexState = jjnewLexState[jjmatchedKind]; - continue EOFLoop; - } - if (jjnewLexState[jjmatchedKind] != -1) - curLexState = jjnewLexState[jjmatchedKind]; - curPos = 0; - jjmatchedKind = 0x7fffffff; - try{ - curChar = input_stream.readChar(); - continue; - }catch(java.io.IOException e1){} - } - int error_line = input_stream.getEndLine(); - int error_column = input_stream.getEndColumn(); - String error_after = null; - boolean EOFSeen = false; - try{ - input_stream.readChar(); - input_stream.backup(1); - }catch(java.io.IOException e1){ - EOFSeen = true; - error_after = curPos <= 1 ? "" : input_stream.GetImage(); - if (curChar == '\n' || curChar == '\r'){ - error_line++; - error_column = 0; - }else - error_column++; - } - if (!EOFSeen){ - input_stream.backup(1); - error_after = curPos <= 1 ? "" : input_stream.GetImage(); - } - throw new TokenMgrError(EOFSeen, curLexState, error_line, error_column, error_after, curChar, TokenMgrError.LEXICAL_ERROR); - } - } - } +/** Get the next Token. */ +public Token getNextToken() +{ + Token matchedToken; + int curPos = 0; - private void jjCheckNAdd(int state){ - if (jjrounds[state] != jjround){ - jjstateSet[jjnewStateCnt++] = state; - jjrounds[state] = jjround; - } - } + EOFLoop : + for (;;) + { + try + { + curChar = input_stream.BeginToken(); + } + catch(java.io.IOException e) + { + jjmatchedKind = 0; + matchedToken = jjFillToken(); + return matchedToken; + } - private void jjAddStates(int start, int end){ - do{ - jjstateSet[jjnewStateCnt++] = jjnextStates[start]; - }while(start++ != end); - } + for (;;) + { + switch(curLexState) + { + case 0: + jjmatchedKind = 0x7fffffff; + jjmatchedPos = 0; + curPos = jjMoveStringLiteralDfa0_0(); + break; + case 1: + jjmatchedKind = 0x7fffffff; + jjmatchedPos = 0; + curPos = jjMoveStringLiteralDfa0_1(); + if (jjmatchedPos == 0 && jjmatchedKind > 90) + { + jjmatchedKind = 90; + } + break; + case 2: + jjmatchedKind = 0x7fffffff; + jjmatchedPos = 0; + curPos = jjMoveStringLiteralDfa0_2(); + break; + case 3: + jjmatchedKind = 0x7fffffff; + jjmatchedPos = 0; + curPos = jjMoveStringLiteralDfa0_3(); + break; + } + if (jjmatchedKind != 0x7fffffff) + { + if (jjmatchedPos + 1 < curPos) + input_stream.backup(curPos - jjmatchedPos - 1); + if ((jjtoToken[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L) + { + matchedToken = jjFillToken(); + if (jjnewLexState[jjmatchedKind] != -1) + curLexState = jjnewLexState[jjmatchedKind]; + return matchedToken; + } + else if ((jjtoSkip[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L) + { + if (jjnewLexState[jjmatchedKind] != -1) + curLexState = jjnewLexState[jjmatchedKind]; + continue EOFLoop; + } + if (jjnewLexState[jjmatchedKind] != -1) + curLexState = jjnewLexState[jjmatchedKind]; + curPos = 0; + jjmatchedKind = 0x7fffffff; + try { + curChar = input_stream.readChar(); + continue; + } + catch (java.io.IOException e1) { } + } + int error_line = input_stream.getEndLine(); + int error_column = input_stream.getEndColumn(); + String error_after = null; + boolean EOFSeen = false; + try { input_stream.readChar(); input_stream.backup(1); } + catch (java.io.IOException e1) { + EOFSeen = true; + error_after = curPos <= 1 ? "" : input_stream.GetImage(); + if (curChar == '\n' || curChar == '\r') { + error_line++; + error_column = 0; + } + else + error_column++; + } + if (!EOFSeen) { + input_stream.backup(1); + error_after = curPos <= 1 ? "" : input_stream.GetImage(); + } + throw new TokenMgrError(EOFSeen, curLexState, error_line, error_column, error_after, curChar, TokenMgrError.LEXICAL_ERROR); + } + } +} - private void jjCheckNAddTwoStates(int state1, int state2){ - jjCheckNAdd(state1); - jjCheckNAdd(state2); - } +private void jjCheckNAdd(int state) +{ + if (jjrounds[state] != jjround) + { + jjstateSet[jjnewStateCnt++] = state; + jjrounds[state] = jjround; + } +} +private void jjAddStates(int start, int end) +{ + do { + jjstateSet[jjnewStateCnt++] = jjnextStates[start]; + } while (start++ != end); +} +private void jjCheckNAddTwoStates(int state1, int state2) +{ + jjCheckNAdd(state1); + jjCheckNAdd(state2); +} - private void jjCheckNAddStates(int start, int end){ - do{ - jjCheckNAdd(jjnextStates[start]); - }while(start++ != end); - } +private void jjCheckNAddStates(int start, int end) +{ + do { + jjCheckNAdd(jjnextStates[start]); + } while (start++ != end); +} } diff --git a/src/adql/parser/ADQLQueryFactory.java b/src/adql/parser/ADQLQueryFactory.java index daef3dc567acbd9ee71e4b6b6729220e0349fb4e..4543372ddc2903a5e4d5ccf4bbb7fc7ce4a83a5f 100644 --- a/src/adql/parser/ADQLQueryFactory.java +++ b/src/adql/parser/ADQLQueryFactory.java @@ -16,12 +16,13 @@ package adql.parser; * 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) + * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS), + * Astronomisches Rechen Institut (ARI) */ import java.util.Collection; -import java.util.Vector; +import adql.db.FunctionDef; import adql.parser.IdentifierItems.IdentifierItem; import adql.query.ADQLOrder; import adql.query.ADQLQuery; @@ -30,26 +31,24 @@ import adql.query.ColumnReference; import adql.query.IdentifierField; import adql.query.SelectItem; import adql.query.TextPosition; +import adql.query.constraint.ADQLConstraint; import adql.query.constraint.Between; import adql.query.constraint.Comparison; -import adql.query.constraint.ADQLConstraint; -import adql.query.constraint.ConstraintsGroup; import adql.query.constraint.ComparisonOperator; +import adql.query.constraint.ConstraintsGroup; import adql.query.constraint.Exists; import adql.query.constraint.In; import adql.query.constraint.IsNull; import adql.query.constraint.NotConstraint; - import adql.query.from.ADQLJoin; import adql.query.from.ADQLTable; -import adql.query.from.FromContent; import adql.query.from.CrossJoin; +import adql.query.from.FromContent; import adql.query.from.InnerJoin; import adql.query.from.OuterJoin; import adql.query.from.OuterJoin.OuterType; - -import adql.query.operand.ADQLOperand; import adql.query.operand.ADQLColumn; +import adql.query.operand.ADQLOperand; import adql.query.operand.Concatenation; import adql.query.operand.NegativeOperand; import adql.query.operand.NumericConstant; @@ -57,14 +56,12 @@ import adql.query.operand.Operation; import adql.query.operand.OperationType; import adql.query.operand.StringConstant; import adql.query.operand.WrappedOperand; - import adql.query.operand.function.DefaultUDF; import adql.query.operand.function.MathFunction; import adql.query.operand.function.MathFunctionType; import adql.query.operand.function.SQLFunction; import adql.query.operand.function.SQLFunctionType; import adql.query.operand.function.UserDefinedFunction; -import adql.query.operand.function.geometry.GeometryFunction.GeometryValue; import adql.query.operand.function.geometry.AreaFunction; import adql.query.operand.function.geometry.BoxFunction; import adql.query.operand.function.geometry.CentroidFunction; @@ -74,6 +71,7 @@ import adql.query.operand.function.geometry.DistanceFunction; import adql.query.operand.function.geometry.ExtractCoord; import adql.query.operand.function.geometry.ExtractCoordSys; import adql.query.operand.function.geometry.GeometryFunction; +import adql.query.operand.function.geometry.GeometryFunction.GeometryValue; import adql.query.operand.function.geometry.IntersectsFunction; import adql.query.operand.function.geometry.PointFunction; import adql.query.operand.function.geometry.PolygonFunction; @@ -84,27 +82,30 @@ import adql.query.operand.function.geometry.RegionFunction; * * <p>To customize the object representation you merely have to extends the appropriate functions of this class.</p> * - * @author Grégory Mantelet (CDS) - * @version 08/2011 + * @author Grégory Mantelet (CDS;ARI) + * @version 1.3 (10/2014) * * @see ADQLParser */ public class ADQLQueryFactory { - protected boolean allowUnknownFunctions = false; - + /** + * Type of table JOIN. + * + * @author Grégory Mantelet (CDS) + * @version 1.0 (08/2011) + */ public static enum JoinType{ CROSS, INNER, OUTER_LEFT, OUTER_RIGHT, OUTER_FULL; } + /** + * Create a query factory. + */ public ADQLQueryFactory(){ ; } - public ADQLQueryFactory(boolean allowUnknownFunctions){ - this.allowUnknownFunctions = allowUnknownFunctions; - } - public ADQLQuery createQuery() throws Exception{ return new ADQLQuery(); } @@ -273,21 +274,29 @@ public class ADQLQueryFactory { /** * <p>Creates the user defined functions called as the given name and with the given parameters.</p> - * <p><b>IMPORTANT: This function must be overridden if some user defined functions are available.</b></p> + * + * <p> + * By default, this function returns a {@link DefaultUDF} instance. It is generic enough to cover every kind of functions. + * But you can of course override this function in order to return your own instance of {@link UserDefinedFunction}. + * In this case, you may not forget to call the super function (super.createUserDefinedFunction(name, params)) so that + * all other unknown functions are still returned as {@link DefaultUDF} instances. + * </p> + * + * <p><i><b>IMPORTANT:</b> + * The tests done to check whether a user defined function is allowed/managed in this implementation, is done later by the parser. + * Only declared UDF will pass the test of the parser. For that, you should give it a list of allowed UDFs (each UDF will be then + * represented by a {@link FunctionDef} object). + * </i></p> * * @param name Name of the user defined function to create. * @param params Parameters of the user defined function to create. * - * @return The corresponding user defined function. + * @return The corresponding user defined function (by default an instance of {@link DefaultUDF}). * - * @throws Exception An {@link UnsupportedOperationException} by default, otherwise any other type of error may be - * thrown if there is a problem while creating the function. + * @throws Exception If there is a problem while creating the function. */ public UserDefinedFunction createUserDefinedFunction(String name, ADQLOperand[] params) throws Exception{ - if (allowUnknownFunctions) - return new DefaultUDF(name, params); - else - throw new UnsupportedOperationException("No ADQL function called \"" + name + "\" !"); + return new DefaultUDF(name, params); } public DistanceFunction createDistance(PointFunction point1, PointFunction point2) throws Exception{ @@ -322,7 +331,7 @@ public class ADQLQueryFactory { return new RegionFunction(param); } - public PolygonFunction createPolygon(ADQLOperand coordSys, Vector<ADQLOperand> coords) throws Exception{ + public PolygonFunction createPolygon(ADQLOperand coordSys, Collection<? extends ADQLOperand> coords) throws Exception{ return new PolygonFunction(coordSys, coords); } diff --git a/src/adql/parser/adqlGrammar.jj b/src/adql/parser/adqlGrammar.jj index bfac21d80477977153f30f41f3df1e0a7554b4fd..52e6ded3300d915ca5a701448aefd13215247d81 100644 --- a/src/adql/parser/adqlGrammar.jj +++ b/src/adql/parser/adqlGrammar.jj @@ -14,7 +14,7 @@ * 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-2014 - UDS/Centre de DonnM-CM-)es astronomiques de Strasbourg (CDS), + * Copyright 2012-2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS), * Astronomisches Rechen Institute (ARI) */ @@ -26,7 +26,7 @@ * If the syntax is not conform to the ADQL definition an error message is printed else it will be the message "Correct syntax". * * Author: Grégory Mantelet (CDS;ARI) - gmantele@ari.uni-heidelberg.de -* Version: 1.2 (03/2014) +* Version: 1.3 (10/2014) */ /* ########### */ @@ -35,7 +35,7 @@ options { STATIC = false; IGNORE_CASE = true; - DEBUG_PARSER = true; + DEBUG_PARSER = false; } /* ########## */ @@ -89,7 +89,7 @@ import adql.translator.TranslationException; * @see ADQLQueryFactory * * @author Grégory Mantelet (CDS;ARI) - gmantele@ari.uni-heidelberg.de -* @version 1.2 (03/2014) +* @version 1.3 (10/2014) */ public class ADQLParser { @@ -108,9 +108,6 @@ public class ADQLParser { /** The first token of a table/column name. This token is extracted by {@link #Identifier()}. */ private Token currentIdentifierToken = null; - /** List of all allowed coordinate systems. */ - private ArrayList<String> allowedCoordSys = new ArrayList<String>(); - /** * Builds an ADQL parser without a query to parse. */ @@ -348,24 +345,6 @@ public class ADQLParser { return Query(); } - public final void addCoordinateSystem(final String coordSys){ - allowedCoordSys.add(coordSys); - } - - public final void setCoordinateSystems(final Collection<String> coordSys){ - allowedCoordSys.clear(); - if (coordSys != null) - allowedCoordSys.addAll(coordSys); - } - - public final boolean isAllowedCoordSys(final String coordSys) { - for(String cs : allowedCoordSys){ - if (cs.equalsIgnoreCase(coordSys)) - return true; - } - return false; - } - public final void setDebug(boolean debug){ if (debug) enable_tracing(); else disable_tracing(); @@ -983,8 +962,8 @@ ADQLJoin JoinSpecification(FromContent leftTable): { boolean natural = false; Jo /* STRING */ /* ****** */ String String(): {Token t; String str="";} { - (t=<STRING_LITERAL> {str += t.image;})+ - {return (str!=null)?str.substring(1,str.length()-1):str;} + (t=<STRING_LITERAL> {str += t.image.substring(1,t.image.length()-1).replaceAll("''", "'");})+ + {return str;} } /* ************* */ @@ -1011,30 +990,48 @@ String SignedInteger(): {Token sign=null, number;} { /* *********** */ /* EXPRESSIONS */ /* *********** */ -ADQLOperand ValueExpressionPrimary(): {String expr; ADQLColumn column; ADQLOperand op;} { +ADQLOperand NumericValueExpressionPrimary(): {String expr; ADQLColumn column; ADQLOperand op;} { try{ (// unsigned_value_specification expr=UnsignedNumeric() {return queryFactory.createNumericConstant(expr);} - // string - | expr=String() {return queryFactory.createStringConstant(expr);} // column_reference - | column=Column() {return column;} + | column=Column() {column.setExpectedType('N'); return column;} // set_function_specification | op=SqlFunction() {return op;} // LEFT_PAR value_expression RIGHT_PAR - | (<LEFT_PAR> op=ValueExpression() <RIGHT_PAR>) {return queryFactory.createWrappedOperand(op);}) + | (<LEFT_PAR> op=NumericExpression() <RIGHT_PAR>) {return queryFactory.createWrappedOperand(op);}) + }catch(Exception ex){ + throw generateParseException(ex); + } +} + +ADQLOperand StringValueExpressionPrimary(): {String expr; ADQLColumn column; ADQLOperand op;} { + try{ + (// string + expr=String() {return queryFactory.createStringConstant(expr);} + // column_reference + | column=Column() {column.setExpectedType('S'); return column;} + // LEFT_PAR value_expression RIGHT_PAR + | (<LEFT_PAR> (op=StringExpression()) <RIGHT_PAR>) {return queryFactory.createWrappedOperand(op);}) }catch(Exception ex){ throw generateParseException(ex); } } ADQLOperand ValueExpression(): {ADQLOperand valueExpr = null; } { - (valueExpr=GeometryValueFunction() - | LOOKAHEAD(<PLUS> | <MINUS>) valueExpr=NumericExpression() - | LOOKAHEAD(<COORDSYS>) valueExpr=StringExpression() - | LOOKAHEAD(StringFactor() <CONCAT>) valueExpr=StringExpression() - | valueExpr=NumericExpression()) - {return valueExpr;} + try{ + (LOOKAHEAD((<PLUS>|<MINUS>) | (Factor() (<PLUS>|<MINUS>|<ASTERISK>|<DIVIDE>))) valueExpr=NumericExpression() + | LOOKAHEAD(<COORDSYS> | (StringFactor() <CONCAT>)) valueExpr=StringExpression() + | LOOKAHEAD(<LEFT_PAR>) <LEFT_PAR> valueExpr=ValueExpression() <RIGHT_PAR> { valueExpr = queryFactory.createWrappedOperand(valueExpr); } + | LOOKAHEAD(<REGULAR_IDENTIFIER> <LEFT_PAR>) valueExpr=UserDefinedFunction() + | valueExpr=GeometryValueFunction() + | LOOKAHEAD(Column()) valueExpr=Column() + | LOOKAHEAD(String()) valueExpr=StringFactor() + | valueExpr=Factor()) + {return valueExpr;} + }catch(Exception ex){ + throw generateParseException(ex); + } } ADQLOperand NumericExpression(): {Token sign=null; ADQLOperand leftOp, rightOp=null;} { @@ -1070,7 +1067,7 @@ ADQLOperand NumericTerm(): {Token sign=null; ADQLOperand leftOp, rightOp=null;} ADQLOperand Factor(): {boolean negative = false;; ADQLOperand op;} { ( (<PLUS> | (<MINUS> {negative = true;}))? - (LOOKAHEAD(2) op=NumericFunction() | op=ValueExpressionPrimary()) + (LOOKAHEAD(2) op=NumericFunction() | op=NumericValueExpressionPrimary()) ) { @@ -1109,17 +1106,17 @@ ADQLOperand StringExpression(): {ADQLOperand leftOp; ADQLOperand rightOp = null; ADQLOperand StringFactor(): {ADQLOperand op;} { (op=ExtractCoordSys() - | LOOKAHEAD(2) op=UserDefinedFunction() - | op=ValueExpressionPrimary()) + | LOOKAHEAD(2) op=UserDefinedFunction() { ((UserDefinedFunction)op).setExpectedType('S'); } + | op=StringValueExpressionPrimary()) {return op;} } GeometryValue<GeometryFunction> GeometryExpression(): {ADQLColumn col = null; GeometryFunction gf = null;} { (col=Column() | gf=GeometryValueFunction()) { - if (col != null) + if (col != null){ col.setExpectedType('G'); return new GeometryValue<GeometryFunction>(col); - else + }else return new GeometryValue<GeometryFunction>(gf); } } @@ -1282,24 +1279,26 @@ GeometryFunction GeometryFunction(): {Token t=null; GeometryValue<GeometryFuncti }) // non_predicate_geometry_function | (<AREA> <LEFT_PAR> gvf1=GeometryExpression() <RIGHT_PAR>) {gf = queryFactory.createArea(gvf1);} - | (<COORD1> <LEFT_PAR> (p1=Point() {gf = queryFactory.createCoord1(p1);} | col1=Column() {gf = queryFactory.createCoord1(col1);}) <RIGHT_PAR>) - | (<COORD2> <LEFT_PAR> (p1=Point() {gf = queryFactory.createCoord2(p1);} | col1=Column() {gf = queryFactory.createCoord2(col1);}) <RIGHT_PAR>) + | (<COORD1> <LEFT_PAR> (p1=Point() {gf = queryFactory.createCoord1(p1);} | col1=Column() {col1.setExpectedType('G'); gf = queryFactory.createCoord1(col1);}) <RIGHT_PAR>) + | (<COORD2> <LEFT_PAR> (p1=Point() {gf = queryFactory.createCoord2(p1);} | col1=Column() {col1.setExpectedType('G'); gf = queryFactory.createCoord2(col1);}) <RIGHT_PAR>) | (<DISTANCE> <LEFT_PAR> (p1=Point()|col1=Column()) { if (p1 != null) gvp1 = new GeometryValue<PointFunction>(p1); - else + else{ col1.setExpectedType('G'); gvp1 = new GeometryValue<PointFunction>(col1); + } } <COMMA> (p2=Point()|col2=Column()) { if (p2 != null) gvp2 = new GeometryValue<PointFunction>(p2); - else + else{ col2.setExpectedType('G'); gvp2 = new GeometryValue<PointFunction>(col2); + } } <RIGHT_PAR> {gf = queryFactory.createDistance(gvp1, gvp2);} @@ -1312,19 +1311,9 @@ GeometryFunction GeometryFunction(): {Token t=null; GeometryValue<GeometryFuncti { return gf; } } -ADQLOperand CoordinateSystem(): { Token oldToken = token; ADQLOperand coordSys=null;}{ +ADQLOperand CoordinateSystem(): { ADQLOperand coordSys=null;}{ coordSys=StringExpression() - { - if (allowedCoordSys.size() > 0){ - TextPosition position = new TextPosition(oldToken.next, token); - if (coordSys == null) - throw new ParseException("A coordinate system must always be provided !", position); - if (coordSys instanceof StringConstant && !isAllowedCoordSys(((StringConstant)coordSys).getValue())) - throw new ParseException("\""+coordSys.toADQL()+"\" is not an allowed coordinate systems !", position); - } - - return coordSys; - } + { return coordSys; } } GeometryFunction GeometryValueFunction(): {ADQLOperand coordSys; ADQLOperand width, height; ADQLOperand[] coords, tmp; Vector<ADQLOperand> vCoords; ADQLOperand op=null; GeometryValue<GeometryFunction> gvf = null; GeometryFunction gf = null;} { @@ -1396,7 +1385,7 @@ ADQLFunction NumericFunction(): {ADQLFunction fct;} { (fct=MathFunction() | fct=TrigFunction() | fct=GeometryFunction() - | fct=UserDefinedFunction()) + | fct=UserDefinedFunction() { ((UserDefinedFunction)fct).setExpectedType('N'); }) {return fct;} } @@ -1449,17 +1438,22 @@ MathFunction TrigFunction(): {Token fct=null; ADQLOperand param1=null, param2=nu } } -/* /!\ WARNING: The function name may be prefixed by "udf_" but there is no way to check it here ! */ UserDefinedFunction UserDefinedFunction(): {Token fct; Vector<ADQLOperand> params = new Vector<ADQLOperand>(); ADQLOperand op;} { fct=<REGULAR_IDENTIFIER> <LEFT_PAR> (op=ValueExpression() {params.add(op);} (<COMMA> op=ValueExpression() {params.add(op);})*)? <RIGHT_PAR> { //System.out.println("INFO [ADQLParser]: \""+fct.image+"\" (from line "+fct.beginLine+" and column "+fct.beginColumn+" to line "+token.endLine+" and column "+(token.endColumn+1)+") is considered as an user defined function !"); try{ + // Build the parameters list: ADQLOperand[] parameters = new ADQLOperand[params.size()]; for(int i=0; i<params.size(); i++) parameters[i] = params.get(i); + + // Create the UDF function: return queryFactory.createUserDefinedFunction(fct.image, parameters); }catch(UnsupportedOperationException uoe){ + /* This catch clause is just for backward compatibility: + * if the createUserDefinedFunction(...) is overridden and + * the function can not be identified a such exception may be thrown). */ throw new ParseException(uoe.getMessage(), new TextPosition(fct, token)); }catch(Exception ex){ throw generateParseException(ex); diff --git a/src/adql/query/ADQLList.java b/src/adql/query/ADQLList.java index 25d5933bdc4692b6e6297090ab6c902315fead9c..68c93a19bedc6e973a513dc89aa0a00103bbb5d0 100644 --- a/src/adql/query/ADQLList.java +++ b/src/adql/query/ADQLList.java @@ -16,7 +16,8 @@ package adql.query; * 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) + * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS), + * Astronomisches Rechen Institut (ARI) */ import java.util.Iterator; @@ -27,8 +28,8 @@ import java.util.Vector; * * <p>Since it is a list, it is possible to add, remove, modify and iterate on a such object.</p> * - * @author Grégory Mantelet (CDS) - * @version 06/2011 + * @author Grégory Mantelet (CDS;ARI) + * @version 2.2 (10/2014) * * @see ClauseADQL * @see ClauseConstraints @@ -164,23 +165,30 @@ public abstract class ADQLList< T extends ADQLObject > implements ADQLObject, It return list.isEmpty(); } + @Override public String getName(){ return name; } + @Override public String toADQL(){ - String adql = (getName() == null) ? "" : (getName() + " "); + StringBuffer adql = new StringBuffer((getName() == null) ? "" : (getName() + " ")); - for(int i = 0; i < size(); i++) - adql += ((i == 0) ? "" : (" " + getSeparator(i) + " ")) + get(i).toADQL(); + for(int i = 0; i < size(); i++){ + if (i > 0) + adql.append(" " + getSeparator(i) + " "); + adql.append(get(i).toADQL()); + } - return adql; + return adql.toString(); } + @Override public Iterator<T> iterator(){ return list.iterator(); } + @Override public ADQLIterator adqlIterator(){ return new ADQLListIterator(this); } @@ -201,6 +209,7 @@ public abstract class ADQLList< T extends ADQLObject > implements ADQLObject, It */ public abstract String getSeparator(int index) throws ArrayIndexOutOfBoundsException; + @Override public abstract ADQLObject getCopy() throws Exception; /** @@ -219,15 +228,18 @@ public abstract class ADQLList< T extends ADQLObject > implements ADQLObject, It list = (ADQLList<ADQLObject>)lst; } + @Override public boolean hasNext(){ return index + 1 < list.size(); } + @Override public ADQLObject next(){ removed = false; return list.get(++index); } + @Override public void replace(ADQLObject replacer) throws UnsupportedOperationException, IllegalStateException{ if (index <= -1) throw new IllegalStateException("replace(ADQLObject) impossible: next() has not yet been called !"); @@ -241,6 +253,7 @@ public abstract class ADQLList< T extends ADQLObject > implements ADQLObject, It list.set(index, replacer); } + @Override public void remove(){ if (index <= -1) throw new IllegalStateException("remove() impossible: next() has not yet been called !"); diff --git a/src/adql/query/ADQLQuery.java b/src/adql/query/ADQLQuery.java index 75f3a647200aa376f34feee2fb92e852291c8d72..95725e4859a72b761739af9a21aa114fb7e8a354 100644 --- a/src/adql/query/ADQLQuery.java +++ b/src/adql/query/ADQLQuery.java @@ -17,7 +17,7 @@ package adql.query; * along with ADQLLibrary. If not, see <http://www.gnu.org/licenses/>. * * Copyright 2012-2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS), - * Astronomishes Rechen Institut (ARI) + * Astronomisches Rechen Institut (ARI) */ import java.util.ArrayList; diff --git a/src/adql/query/from/ADQLJoin.java b/src/adql/query/from/ADQLJoin.java index c7199334473bda2086332fe453cacab2026a12b4..bbc7482c288bace985ffc94cf0e425ad6cbae745 100644 --- a/src/adql/query/from/ADQLJoin.java +++ b/src/adql/query/from/ADQLJoin.java @@ -17,7 +17,7 @@ package adql.query.from; * along with ADQLLibrary. If not, see <http://www.gnu.org/licenses/>. * * Copyright 2012-2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS), - * Astronomishes Rechen Institut (ARI) + * Astronomisches Rechen Institut (ARI) */ import java.util.ArrayList; diff --git a/src/adql/query/from/FromContent.java b/src/adql/query/from/FromContent.java index 64da1e5220d2f434c807f7f1e26b2a3f43b9b62a..1660ebff4ba389588bcbcef2d3b1c2430ca3fb41 100644 --- a/src/adql/query/from/FromContent.java +++ b/src/adql/query/from/FromContent.java @@ -17,7 +17,7 @@ package adql.query.from; * along with ADQLLibrary. If not, see <http://www.gnu.org/licenses/>. * * Copyright 2012-2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS), - * Astronomishes Rechen Institut (ARI) + * Astronomisches Rechen Institut (ARI) */ import java.util.ArrayList; diff --git a/src/adql/query/operand/ADQLColumn.java b/src/adql/query/operand/ADQLColumn.java index d148bd70b061976d74f32df28891bed940bd9e11..57b30b5353b9871f16ebd7083912eddbf0a9112a 100644 --- a/src/adql/query/operand/ADQLColumn.java +++ b/src/adql/query/operand/ADQLColumn.java @@ -16,11 +16,11 @@ package adql.query.operand; * 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) + * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS), + * Astronomisches Rechen Institut (ARI) */ import adql.db.DBColumn; - import adql.query.ADQLIterator; import adql.query.ADQLObject; import adql.query.IdentifierField; @@ -31,10 +31,10 @@ import adql.query.from.ADQLTable; /** * Represents the complete (literal) reference to a column ({schema(s)}.{table}.{column}). * - * @author Grégory Mantelet (CDS) - * @version 07/2011 + * @author Grégory Mantelet (CDS;ARI) + * @version 1.3 (10/2014) */ -public class ADQLColumn implements ADQLOperand { +public class ADQLColumn implements ADQLOperand, UnknownType { /** Position in the original ADQL query string. */ private TextPosition position = null; @@ -60,6 +60,10 @@ public class ADQLColumn implements ADQLOperand { /** The {@link ADQLTable} which is supposed to contain this column. By default, this field is automatically filled by {@link adql.db.DBChecker}. */ private ADQLTable adqlTable = null; + /** Type expected by the parser. + * @since 1.3 */ + private char expectedType = '?'; + /* ************ */ /* CONSTRUCTORS */ /* ************ */ @@ -457,26 +461,47 @@ public class ADQLColumn implements ADQLOperand { /* ***************** */ /* INHERITED METHODS */ /* ***************** */ + @Override + public char getExpectedType(){ + return expectedType; + } + + @Override + public void setExpectedType(final char c){ + expectedType = c; + } + + @Override public boolean isNumeric(){ - return true; + return (dbLink == null || dbLink.getDatatype() == null || dbLink.getDatatype().isNumeric()); } + @Override public boolean isString(){ - return true; + return (dbLink == null || dbLink.getDatatype() == null || dbLink.getDatatype().isString()); + } + + @Override + public boolean isGeometry(){ + return (dbLink == null || dbLink.getDatatype() == null || dbLink.getDatatype().isGeometry()); } + @Override public ADQLObject getCopy() throws Exception{ return new ADQLColumn(this); } + @Override public String getName(){ return getColumnName(); } + @Override public ADQLIterator adqlIterator(){ return new NullADQLIterator(); } + @Override public String toADQL(){ return getFullColumnName(); } diff --git a/src/adql/query/operand/ADQLOperand.java b/src/adql/query/operand/ADQLOperand.java index 61dc647cfc22f38eebf4f731deb0d0469b97a221..413546b4f505b01dea9666c93c346fdcf6118336 100644 --- a/src/adql/query/operand/ADQLOperand.java +++ b/src/adql/query/operand/ADQLOperand.java @@ -16,22 +16,42 @@ package adql.query.operand; * 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) + * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS), + * Astronomisches Rechen Institut (ARI) */ import adql.query.ADQLObject; /** * <p>Any ADQL operand (an operation, a constant, a column name, a function, ...) must implement this interface - * and indicates whether it corresponds to a numeric or a string value.</p> + * and indicates whether it corresponds to a numeric, a string or a geometrical region value.</p> * - * @author Grégory Mantelet (CDS) - * @version 11/2010 + * @author Grégory Mantelet (CDS;ARI) + * @version 1.3 (10/2014) */ public interface ADQLOperand extends ADQLObject { + /** + * Tell whether this operand is numeric or not. + * + * @return <i>true</i> if this operand is numeric, <i>false</i> otherwise. + */ public boolean isNumeric(); + /** + * Tell whether this operand is a string or not. + * + * @return <i>true</i> if this operand is a string, <i>false</i> otherwise. + */ public boolean isString(); + /** + * Tell whether this operand is a geometrical region or not. + * + * @return <i>true</i> if this operand is a geometry, <i>false</i> otherwise. + * + * @since 1.3 + */ + public boolean isGeometry(); + } diff --git a/src/adql/query/operand/Concatenation.java b/src/adql/query/operand/Concatenation.java index a09b7905adc6e885cb0af492d19ef8a05e990782..24536c72cfafd754bc359a462ca7afe757b62dfc 100644 --- a/src/adql/query/operand/Concatenation.java +++ b/src/adql/query/operand/Concatenation.java @@ -16,7 +16,8 @@ package adql.query.operand; * 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) + * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS), + * Astronomisches Rechen Institut (ARI) */ import adql.query.ADQLList; @@ -25,8 +26,8 @@ import adql.query.ADQLObject; /** * Represents a concatenation in ADQL (ex: <i>"_s_ra" || ':' || "_s_dec"</i>). * - * @author Grégory Mantelet (CDS) - * @version 11/2010 + * @author Grégory Mantelet (CDS;ARI) + * @version 1.3 (10/2014) */ public final class Concatenation extends ADQLList<ADQLOperand> implements ADQLOperand { @@ -65,12 +66,19 @@ public final class Concatenation extends ADQLList<ADQLOperand> implements ADQLOp return "||"; } + @Override public final boolean isNumeric(){ return false; } + @Override public final boolean isString(){ return true; } + @Override + public final boolean isGeometry(){ + return false; + } + } \ No newline at end of file diff --git a/src/adql/query/operand/NegativeOperand.java b/src/adql/query/operand/NegativeOperand.java index 82fad6bb3691b3dbaa474902526b68a8c3fdbc4c..b6e4dd7c022473e531b296c21c39ad7cd1eb3998 100644 --- a/src/adql/query/operand/NegativeOperand.java +++ b/src/adql/query/operand/NegativeOperand.java @@ -16,7 +16,8 @@ package adql.query.operand; * 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) + * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS), + * Astronomisches Rechen Institut (ARI) */ import java.util.NoSuchElementException; @@ -27,8 +28,8 @@ import adql.query.ADQLObject; /** * Lets putting a minus sign in front of any numeric operand. * - * @author Grégory Mantelet (CDS) - * @version 06/2011 + * @author Grégory Mantelet (CDS;ARI) + * @version 1.3 (10/2014) */ public final class NegativeOperand implements ADQLOperand { @@ -66,6 +67,7 @@ public final class NegativeOperand implements ADQLOperand { /** Always returns <i>true</i>. * @see adql.query.operand.ADQLOperand#isNumeric() */ + @Override public final boolean isNumeric(){ return true; } @@ -73,24 +75,37 @@ public final class NegativeOperand implements ADQLOperand { /** Always returns <i>false</i>. * @see adql.query.operand.ADQLOperand#isString() */ + @Override public final boolean isString(){ return false; } + /** Always returns <i>false</i>. + * @see adql.query.operand.ADQLOperand#isGeometry() + */ + @Override + public final boolean isGeometry(){ + return false; + } + + @Override public ADQLObject getCopy() throws Exception{ NegativeOperand copy = new NegativeOperand((ADQLOperand)operand.getCopy()); return copy; } + @Override public String getName(){ return "-" + operand.getName(); } + @Override public ADQLIterator adqlIterator(){ return new ADQLIterator(){ private boolean operandGot = (operand == null); + @Override public ADQLObject next(){ if (operandGot) throw new NoSuchElementException(); @@ -98,10 +113,12 @@ public final class NegativeOperand implements ADQLOperand { return operand; } + @Override public boolean hasNext(){ return !operandGot; } + @Override public void replace(ADQLObject replacer) throws UnsupportedOperationException, IllegalStateException{ if (!operandGot) throw new IllegalStateException("replace(ADQLObject) impossible: next() has not yet been called !"); @@ -114,6 +131,7 @@ public final class NegativeOperand implements ADQLOperand { throw new UnsupportedOperationException("Impossible to replace the operand \"" + operand.toADQL() + "\" by \"" + replacer.toADQL() + "\" in the NegativeOperand \"" + toADQL() + "\" because the replacer is not an ADQLOperand or is not numeric !"); } + @Override public void remove(){ if (!operandGot) throw new IllegalStateException("remove() impossible: next() has not yet been called !"); @@ -123,6 +141,7 @@ public final class NegativeOperand implements ADQLOperand { }; } + @Override public String toADQL(){ return "-" + operand.toADQL(); } diff --git a/src/adql/query/operand/NumericConstant.java b/src/adql/query/operand/NumericConstant.java index 2baa6d260079d0f290cab19b9f1983f1a1d3881f..8baa697effca3d8f284383d834eb5095d103c2af 100644 --- a/src/adql/query/operand/NumericConstant.java +++ b/src/adql/query/operand/NumericConstant.java @@ -16,7 +16,8 @@ package adql.query.operand; * 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) + * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS), + * Astronomisches Rechen Institut (ARI) */ import adql.query.ADQLIterator; @@ -26,8 +27,8 @@ import adql.query.NullADQLIterator; /** * A numeric (integer, double, ...) constant. * - * @author Grégory Mantelet (CDS) - * @version 06/2011 + * @author Grégory Mantelet (CDS;ARI) + * @version 1.3 (10/2014) */ public final class NumericConstant implements ADQLOperand { @@ -149,6 +150,7 @@ public final class NumericConstant implements ADQLOperand { /** Always returns <i>true</i>. * @see adql.query.operand.ADQLOperand#isNumeric() */ + @Override public final boolean isNumeric(){ return true; } @@ -156,22 +158,35 @@ public final class NumericConstant implements ADQLOperand { /** Always returns <i>false</i>. * @see adql.query.operand.ADQLOperand#isString() */ + @Override public final boolean isString(){ return false; } + /** Always returns <i>false</i>. + * @see adql.query.operand.ADQLOperand#isGeometry() + */ + @Override + public final boolean isGeometry(){ + return false; + } + + @Override public ADQLObject getCopy(){ return new NumericConstant(this); } + @Override public String getName(){ return value; } + @Override public ADQLIterator adqlIterator(){ return new NullADQLIterator(); } + @Override public String toADQL(){ return value; } diff --git a/src/adql/query/operand/Operation.java b/src/adql/query/operand/Operation.java index b5398ffeabc4864e09e40bf369402850cefd1c6e..d890770377557406eff06a686b0f11031322f1e9 100644 --- a/src/adql/query/operand/Operation.java +++ b/src/adql/query/operand/Operation.java @@ -16,7 +16,8 @@ package adql.query.operand; * 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) + * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS), + * Astronomisches Rechen Institut (ARI) */ import java.util.NoSuchElementException; @@ -27,8 +28,8 @@ import adql.query.ADQLObject; /** * It represents a simple numeric operation (sum, difference, multiplication and division). * - * @author Grégory Mantelet (CDS) - * @version 06/2011 + * @author Grégory Mantelet (CDS;ARI) + * @version 1.3 (10/2014) * * @see OperationType */ @@ -160,6 +161,7 @@ public class Operation implements ADQLOperand { /** Always returns <i>true</i>. * @see adql.query.operand.ADQLOperand#isNumeric() */ + @Override public final boolean isNumeric(){ return true; } @@ -167,24 +169,37 @@ public class Operation implements ADQLOperand { /** Always returns <i>false</i>. * @see adql.query.operand.ADQLOperand#isString() */ + @Override public final boolean isString(){ return false; } + /** Always returns <i>false</i>. + * @see adql.query.operand.ADQLOperand#isGeometry() + */ + @Override + public final boolean isGeometry(){ + return false; + } + + @Override public ADQLObject getCopy() throws Exception{ return new Operation(this); } + @Override public String getName(){ return operation.toString(); } + @Override public ADQLIterator adqlIterator(){ return new ADQLIterator(){ private int index = -1; private ADQLOperand operand = null; + @Override public ADQLObject next(){ index++; @@ -197,10 +212,12 @@ public class Operation implements ADQLOperand { return operand; } + @Override public boolean hasNext(){ return index + 1 < 2; } + @Override public void replace(ADQLObject replacer) throws UnsupportedOperationException, IllegalStateException{ if (index <= -1) throw new IllegalStateException("replace(ADQLObject) impossible: next() has not yet been called !"); @@ -218,6 +235,7 @@ public class Operation implements ADQLOperand { } } + @Override public void remove(){ if (index <= -1) throw new IllegalStateException("remove() impossible: next() has not yet been called !"); @@ -227,6 +245,7 @@ public class Operation implements ADQLOperand { }; } + @Override public String toADQL(){ return leftOperand.toADQL() + operation.toADQL() + rightOperand.toADQL(); } diff --git a/src/adql/query/operand/StringConstant.java b/src/adql/query/operand/StringConstant.java index 2e2b0d4ff1e5cc5e942f9c16120909ff5d687a0c..6c115e74b2287f87e4c2d021b69d9cbd3f8f2408 100644 --- a/src/adql/query/operand/StringConstant.java +++ b/src/adql/query/operand/StringConstant.java @@ -16,7 +16,8 @@ package adql.query.operand; * 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) + * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS), + * Astronomisches Rechen Institut (ARI) */ import adql.query.ADQLIterator; @@ -26,8 +27,8 @@ import adql.query.NullADQLIterator; /** * A string constant. * - * @author Grégory Mantelet (CDS) - * @version 06/2011 + * @author Grégory Mantelet (CDS;ARI) + * @version 1.3 (10/2014) */ public final class StringConstant implements ADQLOperand { @@ -49,28 +50,39 @@ public final class StringConstant implements ADQLOperand { this.value = value; } + @Override public final boolean isNumeric(){ return false; } + @Override public final boolean isString(){ return true; } + @Override + public final boolean isGeometry(){ + return false; + } + + @Override public ADQLObject getCopy(){ return new StringConstant(this); } + @Override public String getName(){ - return "'" + value + "'"; + return toADQL(); } + @Override public ADQLIterator adqlIterator(){ return new NullADQLIterator(); } + @Override public String toADQL(){ - return "'" + value + "'"; + return "'" + value.replaceAll("'", "''") + "'"; } } diff --git a/src/adql/query/operand/UnknownType.java b/src/adql/query/operand/UnknownType.java new file mode 100644 index 0000000000000000000000000000000000000000..bae9d9bb728c2aa5947dced16dd86d73fb446f86 --- /dev/null +++ b/src/adql/query/operand/UnknownType.java @@ -0,0 +1,52 @@ +package adql.query.operand; + +/* + * 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 2014 - Astronomisches Rechen Institut (ARI) + */ + +import adql.query.operand.function.UserDefinedFunction; + +/** + * <p>Operand whose the type can not be known at the parsing time. + * A post-parsing step with column metadata is needed to resolved their types.</p> + * + * <p><i>Note: + * For the moment, only two operands are concerned: columns ({@link ADQLColumn}) and user defined functions ({@link UserDefinedFunction}). + * </i></p> + * + * @author Grégory Mantelet (ARI) + * @version 1.3 (10/2014) + * @since 1.3 + */ +public interface UnknownType extends ADQLOperand { + + /** + * Get the type expected by the syntactic parser according to the context. + * + * @return Expected type: 'n' or 'N' for numeric, 's' or 'S' for string, 'g' or 'G' for geometry. + */ + public char getExpectedType(); + + /** + * Set the type expected for this operand. + * + * @param c Expected type: 'n' or 'N' for numeric, 's' or 'S' for string, 'g' or 'G' for geometry. + */ + public void setExpectedType(final char c); + +} diff --git a/src/adql/query/operand/WrappedOperand.java b/src/adql/query/operand/WrappedOperand.java index 2ffae9bfd13bb85ed39029eef00bea7b5f9760dc..98fde1d171ef34f4a8d63998003a93755e6086f7 100644 --- a/src/adql/query/operand/WrappedOperand.java +++ b/src/adql/query/operand/WrappedOperand.java @@ -16,7 +16,8 @@ package adql.query.operand; * 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) + * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS), + * Astronomisches Rechen Institut (ARI) */ import java.util.NoSuchElementException; @@ -27,8 +28,8 @@ import adql.query.ADQLObject; /** * Lets wrapping an operand by parenthesis. * - * @author Grégory Mantelet (CDS) - * @version 06/2011 + * @author Grégory Mantelet (CDS;ARI) + * @version 1.3 (10/2014) */ public class WrappedOperand implements ADQLOperand { @@ -57,27 +58,38 @@ public class WrappedOperand implements ADQLOperand { return operand; } + @Override public final boolean isNumeric(){ return operand.isNumeric(); } + @Override public final boolean isString(){ return operand.isString(); } + @Override + public final boolean isGeometry(){ + return operand.isGeometry(); + } + + @Override public ADQLObject getCopy() throws Exception{ return new WrappedOperand((ADQLOperand)operand.getCopy()); } + @Override public String getName(){ return "(" + operand.getName() + ")"; } + @Override public ADQLIterator adqlIterator(){ return new ADQLIterator(){ private boolean operandGot = (operand == null); + @Override public ADQLObject next(){ if (operandGot) throw new NoSuchElementException(); @@ -85,10 +97,12 @@ public class WrappedOperand implements ADQLOperand { return operand; } + @Override public boolean hasNext(){ return !operandGot; } + @Override public void replace(ADQLObject replacer) throws UnsupportedOperationException, IllegalStateException{ if (!operandGot) throw new IllegalStateException("replace(ADQLObject) impossible: next() has not yet been called !"); @@ -101,6 +115,7 @@ public class WrappedOperand implements ADQLOperand { throw new UnsupportedOperationException("Impossible to replace an ADQLOperand (\"" + operand + "\") by a " + replacer.getClass().getName() + " (\"" + replacer.toADQL() + "\") !"); } + @Override public void remove(){ if (!operandGot) throw new IllegalStateException("remove() impossible: next() has not yet been called !"); @@ -110,6 +125,7 @@ public class WrappedOperand implements ADQLOperand { }; } + @Override public String toADQL(){ return "(" + operand.toADQL() + ")"; } diff --git a/src/adql/query/operand/function/DefaultUDF.java b/src/adql/query/operand/function/DefaultUDF.java index c08436508295c7a080a3151f2b74494607f9f382..dd0c615843e0282855415d4c9b50c7fd4f9dda74 100644 --- a/src/adql/query/operand/function/DefaultUDF.java +++ b/src/adql/query/operand/function/DefaultUDF.java @@ -16,9 +16,11 @@ package adql.query.operand.function; * 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-2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS), Astronomisches Rechen Institut (ARI) + * Copyright 2012-2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS), + * Astronomisches Rechen Institut (ARI) */ +import adql.db.FunctionDef; import adql.query.ADQLList; import adql.query.ADQLObject; import adql.query.ClauseADQL; @@ -28,13 +30,18 @@ import adql.query.operand.ADQLOperand; * It represents any function which is not managed by ADQL. * * @author Grégory Mantelet (CDS;ARI) - * @version 1.2 (04/2014) + * @version 1.3 (10/2014) */ public final class DefaultUDF extends UserDefinedFunction { - /** Its parameters. */ + /** Define/Describe this user defined function. + * This object gives the return type and the number and type of all parameters. */ + protected FunctionDef definition = null; + + /** Its parsed parameters. */ protected final ADQLList<ADQLOperand> parameters; + /** Parsed name of this UDF. */ protected final String functionName; /** @@ -62,19 +69,56 @@ public final class DefaultUDF extends UserDefinedFunction { parameters = (ADQLList<ADQLOperand>)(toCopy.parameters.getCopy()); } + /** + * Get the signature/definition/description of this user defined function. + * The returned object provides information on the return type and the number and type of parameters. + * + * @return Definition of this function. (MAY be NULL) + */ + public final FunctionDef getDefinition(){ + return definition; + } + + /** + * <p>Let set the signature/definition/description of this user defined function.</p> + * + * <p><i><b>IMPORTANT:</b> + * No particular checks are done here except on the function name which MUST + * be the same (case insensitive) as the name of the given definition. + * Advanced checks must have been done before calling this setter. + * </i></p> + * + * @param def The definition applying to this parsed UDF, or NULL if none has been found. + * + * @throws IllegalArgumentException If the name in the given definition does not match the name of this parsed function. + */ + public final void setDefinition(final FunctionDef def) throws IllegalArgumentException{ + if (def != null && (def.name == null || !functionName.equalsIgnoreCase(def.name))) + throw new IllegalArgumentException("The parsed function name (" + functionName + ") does not match to the name of the given UDF definition (" + def.name + ")."); + + this.definition = def; + } + @Override public final boolean isNumeric(){ - return true; + return (definition == null || definition.isNumeric()); } @Override public final boolean isString(){ - return true; + return (definition == null || definition.isString()); + } + + @Override + public final boolean isGeometry(){ + return (definition == null || definition.isGeometry()); } @Override public ADQLObject getCopy() throws Exception{ - return new DefaultUDF(this); + DefaultUDF copy = new DefaultUDF(this); + copy.setDefinition(definition); + return copy; } @Override diff --git a/src/adql/query/operand/function/MathFunction.java b/src/adql/query/operand/function/MathFunction.java index 15acf0a2f4a9689c483e22814477f150cc2d5631..c29d64a8c6f333fc241c5e10e24dc46cbccff4fd 100644 --- a/src/adql/query/operand/function/MathFunction.java +++ b/src/adql/query/operand/function/MathFunction.java @@ -27,7 +27,7 @@ import adql.query.operand.ADQLOperand; * It represents any basic mathematical function. * * @author Grégory Mantelet (CDS;ARI) - * @version 1.2 (03/2014) + * @version 1.3 (10/2014) * * @see MathFunctionType */ @@ -149,6 +149,11 @@ public class MathFunction extends ADQLFunction { return false; } + @Override + public final boolean isGeometry(){ + return false; + } + @Override public ADQLOperand[] getParameters(){ switch(getNbParameters()){ diff --git a/src/adql/query/operand/function/SQLFunction.java b/src/adql/query/operand/function/SQLFunction.java index 3442aea581efa2e092d1eb65a78bdab9f62db74c..6603fd90b6c0083feb4468cde5b7e0a1bff5270f 100644 --- a/src/adql/query/operand/function/SQLFunction.java +++ b/src/adql/query/operand/function/SQLFunction.java @@ -16,18 +16,18 @@ package adql.query.operand.function; * 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) + * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS), + * Astronomisches Rechen Institut (ARI) */ import adql.query.ADQLObject; - import adql.query.operand.ADQLOperand; /** * It represents any SQL function (COUNT, MAX, MIN, AVG, SUM, etc...). * - * @author Grégory Mantelet (CDS) - * @version 06/2011 + * @author Grégory Mantelet (CDS;ARI) + * @version 1.3 (10/2014) * * @see SQLFunctionType */ @@ -116,22 +116,31 @@ public class SQLFunction extends ADQLFunction { return type; } + @Override public ADQLObject getCopy() throws Exception{ return new SQLFunction(this); } + @Override public String getName(){ return type.name(); } + @Override public final boolean isNumeric(){ return true; } + @Override public final boolean isString(){ return false; } + @Override + public final boolean isGeometry(){ + return false; + } + @Override public ADQLOperand[] getParameters(){ if (param != null) diff --git a/src/adql/query/operand/function/UserDefinedFunction.java b/src/adql/query/operand/function/UserDefinedFunction.java index 39d87784e8a0c71fa26e6774277054eee98bb4f5..78026e72d5429d4b6d76f07b42c3226ca241bbeb 100644 --- a/src/adql/query/operand/function/UserDefinedFunction.java +++ b/src/adql/query/operand/function/UserDefinedFunction.java @@ -1,5 +1,7 @@ package adql.query.operand.function; +import adql.query.operand.UnknownType; + /* * This file is part of ADQLLibrary. * @@ -16,17 +18,32 @@ package adql.query.operand.function; * 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) + * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS), + * Astronomisches Rechen Institut (ARI) */ /** * Function defined by the user (i.e. PSQL functions). * - * @author Grégory Mantelet (CDS) - * @version 01/2012 + * @author Grégory Mantelet (CDS;ARI) + * @version 1.3 (10/2014) * * @see DefaultUDF */ -public abstract class UserDefinedFunction extends ADQLFunction { +public abstract class UserDefinedFunction extends ADQLFunction implements UnknownType { + + /** Type expected by the parser. + * @since 1.3 */ + private char expectedType = '?'; + + @Override + public char getExpectedType(){ + return expectedType; + } + + @Override + public void setExpectedType(final char c){ + expectedType = c; + } } diff --git a/src/adql/query/operand/function/geometry/AreaFunction.java b/src/adql/query/operand/function/geometry/AreaFunction.java index 42906c9811341c3c2929f26b3befe67f801fddef..6b163aca0a6775956801405384fb447e8b66de91 100644 --- a/src/adql/query/operand/function/geometry/AreaFunction.java +++ b/src/adql/query/operand/function/geometry/AreaFunction.java @@ -16,13 +16,13 @@ package adql.query.operand.function.geometry; * 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) + * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS), + * Astronomisches Rechen Institut (ARI) */ import adql.query.ADQLObject; - -import adql.query.operand.ADQLOperand; import adql.query.operand.ADQLColumn; +import adql.query.operand.ADQLOperand; /** * <p>It represents the AREA function of ADQL.</p> @@ -33,8 +33,8 @@ import adql.query.operand.ADQLColumn; * * <p>Inappropriate geometries for this construct (e.g. POINT) SHOULD either return zero or throw an error message. <b>This choice must be done in an extended class of {@link AreaFunction}</b>.</p> * - * @author Grégory Mantelet (CDS) - * @version 06/2011 + * @author Grégory Mantelet (CDS;ARI) + * @version 1.3 (10/2014) */ public class AreaFunction extends GeometryFunction { @@ -47,7 +47,6 @@ public class AreaFunction extends GeometryFunction { * @param param Parameter of AREA. * @throws NullPointerException If the given operand is <i>null</i> or if it's not a {@link GeometryFunction}. */ - @SuppressWarnings("unchecked") public AreaFunction(GeometryValue<GeometryFunction> param) throws NullPointerException{ super(); if (param == null) @@ -88,22 +87,31 @@ public class AreaFunction extends GeometryFunction { this.parameter = parameter; } + @Override public ADQLObject getCopy() throws Exception{ return new AreaFunction(this); } + @Override public String getName(){ return "AREA"; } + @Override public boolean isNumeric(){ return true; } + @Override public boolean isString(){ return false; } + @Override + public boolean isGeometry(){ + return false; + } + @Override public ADQLOperand[] getParameters(){ return new ADQLOperand[]{parameter.getValue()}; diff --git a/src/adql/query/operand/function/geometry/BoxFunction.java b/src/adql/query/operand/function/geometry/BoxFunction.java index e9071330227d2d550e05cebba42a20ae8faca7fa..7e064a4f32d88b372036b606ea07443bcb02529f 100644 --- a/src/adql/query/operand/function/geometry/BoxFunction.java +++ b/src/adql/query/operand/function/geometry/BoxFunction.java @@ -16,11 +16,11 @@ package adql.query.operand.function.geometry; * 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) + * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS), + * Astronomisches Rechen Institut (ARI) */ import adql.query.ADQLObject; - import adql.query.operand.ADQLOperand; /** @@ -38,9 +38,8 @@ import adql.query.operand.ADQLOperand; * In this second example the coordinates of the center position are extracted from a coordinate's column reference. * </i></p> * - * - * @author Grégory Mantelet (CDS) - * @version 06/2011 + * @author Grégory Mantelet (CDS;ARI) + * @version 1.3 (10/2014) */ public class BoxFunction extends GeometryFunction { @@ -93,19 +92,28 @@ public class BoxFunction extends GeometryFunction { height = (ADQLOperand)(toCopy.height.getCopy()); } + @Override public ADQLObject getCopy() throws Exception{ return new BoxFunction(this); } + @Override public String getName(){ return "BOX"; } + @Override public boolean isNumeric(){ return false; } + @Override public boolean isString(){ + return false; + } + + @Override + public boolean isGeometry(){ return true; } diff --git a/src/adql/query/operand/function/geometry/CentroidFunction.java b/src/adql/query/operand/function/geometry/CentroidFunction.java index 88f80e3fe0a3d97d516f0b73b79ec35c71fcc0af..3b3b0147982cbd9a1f50a2d8a6282e4e238484cb 100644 --- a/src/adql/query/operand/function/geometry/CentroidFunction.java +++ b/src/adql/query/operand/function/geometry/CentroidFunction.java @@ -16,13 +16,13 @@ package adql.query.operand.function.geometry; * 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) + * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS), + * Astronomisches Rechen Institut (ARI) */ import adql.query.ADQLObject; - -import adql.query.operand.ADQLOperand; import adql.query.operand.ADQLColumn; +import adql.query.operand.ADQLOperand; /** * <p>It represents the CENTROID function of the ADQL language.</p> @@ -35,8 +35,8 @@ import adql.query.operand.ADQLColumn; * in a position of (25.4,-20.0) degrees and defined according to the ICRS coordinate system with GEOCENTER reference position. * </i></p> * - * @author Grégory Mantelet (CDS) - * @version 06/2011 + * @author Grégory Mantelet (CDS;ARI) + * @version 1.3 (10/2014) */ public class CentroidFunction extends GeometryFunction { @@ -68,22 +68,31 @@ public class CentroidFunction extends GeometryFunction { parameter = (GeometryValue<GeometryFunction>)(toCopy.parameter.getCopy()); } + @Override public ADQLObject getCopy() throws Exception{ return new CentroidFunction(this); } + @Override public String getName(){ return "CENTROID"; } + @Override public boolean isNumeric(){ return true; } + @Override public boolean isString(){ return false; } + @Override + public boolean isGeometry(){ + return false; + } + @Override public ADQLOperand[] getParameters(){ return new ADQLOperand[]{parameter.getValue()}; diff --git a/src/adql/query/operand/function/geometry/CircleFunction.java b/src/adql/query/operand/function/geometry/CircleFunction.java index aff59d89e1832212617fff22d4a6a8f2b27ad34a..f979d3850bf3afe53526fe67e68cf47a85a6e3fa 100644 --- a/src/adql/query/operand/function/geometry/CircleFunction.java +++ b/src/adql/query/operand/function/geometry/CircleFunction.java @@ -16,11 +16,11 @@ package adql.query.operand.function.geometry; * 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) + * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS), + * Astronomisches Rechen Institut (ARI) */ import adql.query.ADQLObject; - import adql.query.operand.ADQLOperand; /** @@ -35,8 +35,8 @@ import adql.query.operand.ADQLOperand; * according to the ICRS coordinate system with GEOCENTER reference position. * </i></p> * - * @author Grégory Mantelet (CDS) - * @version 06/2011 + * @author Grégory Mantelet (CDS;ARI) + * @version 1.3 (10/2014) */ public class CircleFunction extends GeometryFunction { @@ -83,19 +83,28 @@ public class CircleFunction extends GeometryFunction { radius = (ADQLOperand)(toCopy.radius.getCopy()); } + @Override public ADQLObject getCopy() throws Exception{ return new CircleFunction(this); } + @Override public String getName(){ return "CIRCLE"; } + @Override public boolean isNumeric(){ return false; } + @Override public boolean isString(){ + return false; + } + + @Override + public boolean isGeometry(){ return true; } diff --git a/src/adql/query/operand/function/geometry/ContainsFunction.java b/src/adql/query/operand/function/geometry/ContainsFunction.java index f97a9c7614240b3703aa1c75c97c9bcef54bbc2d..4cb4aad040c85f5a8bc225b1c3b5fc03ac60b4d0 100644 --- a/src/adql/query/operand/function/geometry/ContainsFunction.java +++ b/src/adql/query/operand/function/geometry/ContainsFunction.java @@ -16,13 +16,13 @@ package adql.query.operand.function.geometry; * 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) + * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS), + * Astronomisches Rechen Institut (ARI) */ import adql.query.ADQLObject; - -import adql.query.operand.ADQLOperand; import adql.query.operand.ADQLColumn; +import adql.query.operand.ADQLOperand; /** * <p>It represents the CONTAINS function of the ADQL language.</p> @@ -41,8 +41,8 @@ import adql.query.operand.ADQLColumn; * If it can not do so, it SHOULD throw an error message, to be defined by the service making use of ADQL.</li></ul> * </b></p> * - * @author Grégory Mantelet (CDS) - * @version 06/2011 + * @author Grégory Mantelet (CDS;ARI) + * @version 1.3 (10/2014) */ public class ContainsFunction extends GeometryFunction { @@ -81,22 +81,31 @@ public class ContainsFunction extends GeometryFunction { rightParam = (GeometryValue<GeometryFunction>)(toCopy.rightParam.getCopy()); } + @Override public ADQLObject getCopy() throws Exception{ return new ContainsFunction(this); } + @Override public String getName(){ return "CONTAINS"; } + @Override public boolean isNumeric(){ return true; } + @Override public boolean isString(){ return false; } + @Override + public boolean isGeometry(){ + return false; + } + /** * @return The leftParam. */ diff --git a/src/adql/query/operand/function/geometry/DistanceFunction.java b/src/adql/query/operand/function/geometry/DistanceFunction.java index d9429675837a943e30a23ad807ef5611ba98964c..ead9b4b465c21e70cad5d6a1623b57c7efac19bc 100644 --- a/src/adql/query/operand/function/geometry/DistanceFunction.java +++ b/src/adql/query/operand/function/geometry/DistanceFunction.java @@ -16,13 +16,13 @@ package adql.query.operand.function.geometry; * 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) + * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS), + * Astronomisches Rechen Institut (ARI) */ import adql.query.ADQLObject; - -import adql.query.operand.ADQLOperand; import adql.query.operand.ADQLColumn; +import adql.query.operand.ADQLOperand; /** * <p>It represents the DISTANCE function of the ADQL language.</p> @@ -34,8 +34,8 @@ import adql.query.operand.ADQLColumn; * In this example the function computes the distance between two points of coordinates (25, -19.5) and (25.4, -20) both expressed according to the ICRS * coordinate system with GEOCENTER reference position.</i></p> * - * @author Grégory Mantelet (CDS) - * @version 06/2011 + * @author Grégory Mantelet (CDS;ARI) + * @version 1.3 (10/2014) */ public class DistanceFunction extends GeometryFunction { @@ -79,22 +79,31 @@ public class DistanceFunction extends GeometryFunction { throw new UnsupportedOperationException("A DISTANCE function is not associated to a coordinate system !"); } + @Override public ADQLObject getCopy() throws Exception{ return new DistanceFunction(this); } + @Override public String getName(){ return "DISTANCE"; } + @Override public boolean isNumeric(){ return true; } + @Override public boolean isString(){ return false; } + @Override + public boolean isGeometry(){ + return false; + } + /** * Gets the first point. * diff --git a/src/adql/query/operand/function/geometry/ExtractCoord.java b/src/adql/query/operand/function/geometry/ExtractCoord.java index 6f016c9c0ca356d495587262df438eb758ba4116..2fa17cd953ceb46f0da616199f7c9e1283156489 100644 --- a/src/adql/query/operand/function/geometry/ExtractCoord.java +++ b/src/adql/query/operand/function/geometry/ExtractCoord.java @@ -16,13 +16,13 @@ package adql.query.operand.function.geometry; * 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) + * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS), + * Astronomisches Rechen Institut (ARI) */ import adql.query.ADQLObject; - -import adql.query.operand.ADQLOperand; import adql.query.operand.ADQLColumn; +import adql.query.operand.ADQLOperand; /** * <p>It represents the COORD1 and the COORD2 functions of the ADQL language.</p> @@ -35,8 +35,8 @@ import adql.query.operand.ADQLColumn; * system with GEOCENTER reference position. * </i></p> * - * @author Grégory Mantelet (CDS) - * @version 06/2011 + * @author Grégory Mantelet (CDS;ARI) + * @version 1.3 (10/2014) */ public class ExtractCoord extends GeometryFunction { @@ -78,22 +78,31 @@ public class ExtractCoord extends GeometryFunction { point = (GeometryValue<PointFunction>)(toCopy.point.getCopy()); } + @Override public String getName(){ return "COORD" + indCoord; } + @Override public ADQLObject getCopy() throws Exception{ return new ExtractCoord(this); } + @Override public boolean isNumeric(){ return true; } + @Override public boolean isString(){ return false; } + @Override + public boolean isGeometry(){ + return false; + } + @Override public ADQLOperand[] getParameters(){ return new ADQLOperand[]{point.getValue()}; diff --git a/src/adql/query/operand/function/geometry/ExtractCoordSys.java b/src/adql/query/operand/function/geometry/ExtractCoordSys.java index 5337f494b43151115804d82f0139fa3c1bd4083c..dcd8e542a75d8a11d7961788fd3ed64a7996e05b 100644 --- a/src/adql/query/operand/function/geometry/ExtractCoordSys.java +++ b/src/adql/query/operand/function/geometry/ExtractCoordSys.java @@ -16,13 +16,13 @@ package adql.query.operand.function.geometry; * 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) + * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS), + * Astronomisches Rechen Institut (ARI) */ import adql.query.ADQLObject; - -import adql.query.operand.ADQLOperand; import adql.query.operand.ADQLColumn; +import adql.query.operand.ADQLOperand; /** * <p>It represents the COORDSYS function the ADQL language.</p> @@ -35,8 +35,8 @@ import adql.query.operand.ADQLColumn; * system with GEOCENTER reference position. * </i></p> * - * @author Grégory Mantelet (CDS) - * @version 06/2011 + * @author Grégory Mantelet (CDS;ARI) + * @version 1.3 (10/2014) */ public class ExtractCoordSys extends GeometryFunction { @@ -65,22 +65,31 @@ public class ExtractCoordSys extends GeometryFunction { geomExpr = (GeometryValue<GeometryFunction>)(toCopy.geomExpr.getCopy()); } + @Override public ADQLObject getCopy() throws Exception{ return new ExtractCoordSys(this); } + @Override public String getName(){ return "COORDSYS"; } + @Override public boolean isNumeric(){ return false; } + @Override public boolean isString(){ return true; } + @Override + public boolean isGeometry(){ + return false; + } + @Override public ADQLOperand[] getParameters(){ return new ADQLOperand[]{geomExpr.getValue()}; diff --git a/src/adql/query/operand/function/geometry/GeometryFunction.java b/src/adql/query/operand/function/geometry/GeometryFunction.java index 4270eb183e469f6c6f144d7202a57766b9e64b19..e6e10ecf2513847a9ca922fd53e78e621f8ff670 100644 --- a/src/adql/query/operand/function/geometry/GeometryFunction.java +++ b/src/adql/query/operand/function/geometry/GeometryFunction.java @@ -16,20 +16,23 @@ package adql.query.operand.function.geometry; * 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) + * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS), + * Astronomisches Rechen Institut (ARI) */ +import adql.parser.ParseException; import adql.query.ADQLIterator; import adql.query.ADQLObject; -import adql.query.operand.ADQLOperand; import adql.query.operand.ADQLColumn; +import adql.query.operand.ADQLOperand; +import adql.query.operand.StringConstant; import adql.query.operand.function.ADQLFunction; /** * <p>It represents any geometric function of ADQL.</p> * - * @author Grégory Mantelet (CDS) - * @version 06/2011 + * @author Grégory Mantelet (CDS;ARI) + * @version 1.3 (10/2014) */ public abstract class GeometryFunction extends ADQLFunction { @@ -80,13 +83,13 @@ public abstract class GeometryFunction extends ADQLFunction { * @param coordSys Its new coordinate system. * @throws UnsupportedOperationException If this function is not associated with a coordinate system. * @throws NullPointerException If the given operand is <i>null</i>. - * @throws Exception If the given operand is not a string. + * @throws ParseException If the given operand is not a string. */ - public void setCoordinateSystem(ADQLOperand coordSys) throws UnsupportedOperationException, NullPointerException, Exception{ + public void setCoordinateSystem(ADQLOperand coordSys) throws UnsupportedOperationException, NullPointerException, ParseException{ if (coordSys == null) - throw new NullPointerException(""); + this.coordSys = new StringConstant(""); else if (!coordSys.isString()) - throw new Exception("A coordinate system must be a string literal: \"" + coordSys.toADQL() + "\" is not a string operand !"); + throw new ParseException("A coordinate system must be a string literal: \"" + coordSys.toADQL() + "\" is not a string operand!"); else this.coordSys = coordSys; } @@ -95,8 +98,8 @@ public abstract class GeometryFunction extends ADQLFunction { * This class represents a parameter of a geometry function * which, in general, is either a GeometryFunction or a Column. * - * @author Grégory Mantelet (CDS) - * @version 06/2011 + * @author Grégory Mantelet (CDS;ARI) + * @version 1.3 (10/2014) */ public static final class GeometryValue< F extends GeometryFunction > implements ADQLOperand { private ADQLColumn column; @@ -142,26 +145,37 @@ public abstract class GeometryFunction extends ADQLFunction { return column != null; } + @Override public boolean isNumeric(){ return getValue().isNumeric(); } + @Override public boolean isString(){ return getValue().isString(); } + @Override + public boolean isGeometry(){ + return getValue().isGeometry(); + } + + @Override public ADQLObject getCopy() throws Exception{ return new GeometryValue<F>(this); } + @Override public String getName(){ return getValue().getName(); } + @Override public ADQLIterator adqlIterator(){ return getValue().adqlIterator(); } + @Override public String toADQL(){ return getValue().toADQL(); } diff --git a/src/adql/query/operand/function/geometry/IntersectsFunction.java b/src/adql/query/operand/function/geometry/IntersectsFunction.java index 0a37597eadac5b751740c327abb68402f33be157..29bc881fdf61bd455068e3afe694dca137a7a2c4 100644 --- a/src/adql/query/operand/function/geometry/IntersectsFunction.java +++ b/src/adql/query/operand/function/geometry/IntersectsFunction.java @@ -16,13 +16,13 @@ package adql.query.operand.function.geometry; * 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) + * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS), + * Astronomisches Rechen Institut (ARI) */ import adql.query.ADQLObject; - -import adql.query.operand.ADQLOperand; import adql.query.operand.ADQLColumn; +import adql.query.operand.ADQLOperand; /** * <p>It represents the INTERSECTS function of the ADQL language.</p> @@ -42,8 +42,8 @@ import adql.query.operand.ADQLColumn; * If it can not do so, it SHOULD throw an error message, to be defined by the service making use of ADQL.</li></ul> * </b></p> * - * @author Grégory Mantelet (CDS) - * @version 06/2011 + * @author Grégory Mantelet (CDS;ARI) + * @version 1.3 (10/2014) */ public class IntersectsFunction extends GeometryFunction { @@ -82,22 +82,31 @@ public class IntersectsFunction extends GeometryFunction { rightParam = (GeometryValue<GeometryFunction>)(toCopy.rightParam.getCopy()); } + @Override public ADQLObject getCopy() throws Exception{ return new IntersectsFunction(this); } + @Override public String getName(){ return "INTERSECTS"; } + @Override public boolean isNumeric(){ return true; } + @Override public boolean isString(){ return false; } + @Override + public boolean isGeometry(){ + return false; + } + /** * @return The leftParam. */ diff --git a/src/adql/query/operand/function/geometry/PointFunction.java b/src/adql/query/operand/function/geometry/PointFunction.java index 626e34f22a0cbd7ed93ec71ea5f228cc87643f6a..1b736ffabe897b65ee20200f0a9db0602d0f4f00 100644 --- a/src/adql/query/operand/function/geometry/PointFunction.java +++ b/src/adql/query/operand/function/geometry/PointFunction.java @@ -16,11 +16,11 @@ package adql.query.operand.function.geometry; * 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) + * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS), + * Astronomisches Rechen Institut (ARI) */ import adql.query.ADQLObject; - import adql.query.operand.ADQLOperand; /** @@ -34,8 +34,8 @@ import adql.query.operand.ADQLOperand; * In this example the function expresses a point with right ascension of 25 degrees and declination of -19.5 degrees according * to the ICRS coordinate system with GEOCENTER reference position.</i></p> * - * @author Grégory Mantelet (CDS) - * @version 06/2011 + * @author Grégory Mantelet (CDS;ARI) + * @version 1.3 (10/2014) */ public class PointFunction extends GeometryFunction { @@ -59,7 +59,7 @@ public class PointFunction extends GeometryFunction { super(coordinateSystem); if (firstCoord == null || secondCoord == null) - throw new NullPointerException("The POINT function must have non-null coordinates !"); + throw new NullPointerException("The POINT function must have non-null coordinates!"); coord1 = firstCoord; coord2 = secondCoord; @@ -127,19 +127,28 @@ public class PointFunction extends GeometryFunction { this.coord2 = coord2; } + @Override public ADQLObject getCopy() throws Exception{ return new PointFunction(this); } + @Override public String getName(){ return "POINT"; } + @Override public boolean isNumeric(){ return false; } + @Override public boolean isString(){ + return false; + } + + @Override + public boolean isGeometry(){ return true; } diff --git a/src/adql/query/operand/function/geometry/PolygonFunction.java b/src/adql/query/operand/function/geometry/PolygonFunction.java index 07e47ba629e47d979dae71d4db2c36f33819f866..33dd2a629c49bc989025a4fba21fe7d8ab343a9c 100644 --- a/src/adql/query/operand/function/geometry/PolygonFunction.java +++ b/src/adql/query/operand/function/geometry/PolygonFunction.java @@ -16,13 +16,14 @@ package adql.query.operand.function.geometry; * 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) + * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS), + * Astronomisches Rechen Institut (ARI) */ +import java.util.Collection; import java.util.Vector; import adql.query.ADQLObject; - import adql.query.operand.ADQLOperand; /** @@ -40,8 +41,8 @@ import adql.query.operand.ADQLOperand; * In this example the function expresses a triangle, whose vertices are (10.0, -10.5), (20.0, 20.5) and (30.0, 30.5) in degrees * according to the STC coordinate system with GEOCENTER reference position.</i></p> * - * @author Grégory Mantelet (CDS) - * @version 06/2011 + * @author Grégory Mantelet (CDS;ARI) + * @version 1.3 (10/2014) */ public class PolygonFunction extends GeometryFunction { @@ -79,7 +80,7 @@ public class PolygonFunction extends GeometryFunction { * @throws NullPointerException If one of the parameters is <i>null</i>. * @throws Exception If there is another error. */ - public PolygonFunction(ADQLOperand coordSystem, Vector<ADQLOperand> coords) throws UnsupportedOperationException, NullPointerException, Exception{ + public PolygonFunction(ADQLOperand coordSystem, Collection<? extends ADQLOperand> coords) throws UnsupportedOperationException, NullPointerException, Exception{ super(coordSystem); if (coords == null || coords.size() < 6) throw new NullPointerException("A POLYGON function must have at least 3 2-D coordinates !"); @@ -102,19 +103,28 @@ public class PolygonFunction extends GeometryFunction { coordinates.add((ADQLOperand)(item.getCopy())); } + @Override public ADQLObject getCopy() throws Exception{ return new PolygonFunction(this); } + @Override public String getName(){ return "POLYGON"; } + @Override public boolean isNumeric(){ return false; } + @Override public boolean isString(){ + return false; + } + + @Override + public boolean isGeometry(){ return true; } diff --git a/src/adql/query/operand/function/geometry/RegionFunction.java b/src/adql/query/operand/function/geometry/RegionFunction.java index dea04a27d30356320f9e011fa7e9288d7c5878d1..998d4a56a7abb22bc75cf9810334e6db7daa4a5b 100644 --- a/src/adql/query/operand/function/geometry/RegionFunction.java +++ b/src/adql/query/operand/function/geometry/RegionFunction.java @@ -38,7 +38,7 @@ import adql.query.operand.ADQLOperand; * Inappropriate geometries for this construct SHOULD throw an error message, to be defined by the service making use of ADQL.</b></p> * * @author Grégory Mantelet (CDS;ARI) - * @version 1.2 (02/2014) + * @version 1.3 (10/2014) */ public class RegionFunction extends GeometryFunction { @@ -88,6 +88,11 @@ public class RegionFunction extends GeometryFunction { @Override public boolean isString(){ + return false; + } + + @Override + public boolean isGeometry(){ return true; } diff --git a/src/tap/ADQLExecutor.java b/src/tap/ADQLExecutor.java index fc9c6c4481eb529331b769d177b1733b8a5556be..43b18fbfd1f271d06c5abcfc40643602a1bc2643 100644 --- a/src/tap/ADQLExecutor.java +++ b/src/tap/ADQLExecutor.java @@ -496,8 +496,6 @@ public class ADQLExecutor { parser = new ADQLParser(queryChecker); else parser = new ADQLParser(queryChecker, queryFactory); - parser.setCoordinateSystems(service.getCoordinateSystems()); - parser.setDebug(false); ADQLQuery query = parser.parseQuery(tapParams.getQuery()); // Set or check the row limit: diff --git a/src/tap/AbstractTAPFactory.java b/src/tap/AbstractTAPFactory.java index 642aa10b6cf3152f49c2ad1aeea8909fd55a23f2..36984fac6ae7b123c3899bea600228f91148db59 100644 --- a/src/tap/AbstractTAPFactory.java +++ b/src/tap/AbstractTAPFactory.java @@ -44,6 +44,7 @@ import uws.service.backup.UWSBackupManager; import uws.service.error.ServiceErrorWriter; import adql.db.DBChecker; import adql.parser.ADQLQueryFactory; +import adql.parser.ParseException; import adql.parser.QueryChecker; import adql.query.ADQLQuery; @@ -52,7 +53,7 @@ import adql.query.ADQLQuery; * Only the functions related with the database connection stay abstract. * * @author Grégory Mantelet (CDS;ARI) - * @version 2.0 (09/2014) + * @version 2.0 (10/2014) */ public abstract class AbstractTAPFactory extends TAPFactory { @@ -130,7 +131,7 @@ public abstract class AbstractTAPFactory extends TAPFactory { * </p> * * <p><i>Note: - * This function can not be overrided, but {@link #createQueryChecker(Collection)} can be. + * This function can not be overridded, but {@link #createQueryChecker(Collection)} can be. * </i></p> */ @Override @@ -172,7 +173,11 @@ public abstract class AbstractTAPFactory extends TAPFactory { * @throws TAPException If any error occurs while creating the query checker. */ protected QueryChecker createQueryChecker(final Collection<TAPTable> tables) throws TAPException{ - return new DBChecker(tables); + try{ + return new DBChecker(tables, service.getUDFs(), service.getGeometries(), service.getCoordinateSystems()); + }catch(ParseException e){ + throw new TAPException("Unable to build a DBChecker instance! " + e.getMessage(), e, UWSException.INTERNAL_SERVER_ERROR); + } } /* ****** */ diff --git a/src/tap/ServiceConnection.java b/src/tap/ServiceConnection.java index 360fcece32850ec82e8c2e2abcac7b157e47de46..f849d8283bee98b6ec763afb837c75049ba882b5 100644 --- a/src/tap/ServiceConnection.java +++ b/src/tap/ServiceConnection.java @@ -23,64 +23,420 @@ package tap; import java.util.Collection; import java.util.Iterator; +import tap.file.LocalTAPFileManager; import tap.file.TAPFileManager; import tap.formatter.OutputFormat; +import tap.log.DefaultTAPLog; import tap.log.TAPLog; import tap.metadata.TAPMetadata; import uws.service.UserIdentifier; +import adql.db.FunctionDef; /** - * TODO JAVADOC OF THE WHOLE CLASS! + * <p>Description and parameters list of a TAP service.</p> + * + * <p> + * Through this object, it is possible to configure the different limits and formats, + * but also to list all available tables and columns, to declare geometry features as all allowed user defined functions + * and to say where log and other kinds of files must be stored. + * </p> * * @author Grégory Mantelet (CDS;ARI) - * @version 2.0 (09/2014) + * @version 2.0 (10/2014) */ public interface ServiceConnection { + /** + * List of possible limit units. + * + * @author Grégory Mantelet (CDS;ARI) + * @version 2.0 (10/2014) + */ public static enum LimitUnit{ - rows("row"), - bytes("byte"); - + rows("row"), bytes("byte"); + private final String str; + private LimitUnit(final String str){ this.str = str; } + + @Override public String toString(){ return str; } } + /** + * <i>[OPTIONAL]</i> + * <p>Name of the service provider ; it can be an organization as an individual person.</p> + * + * <p>There is no restriction on the syntax or on the label to use ; this information is totally free</p> + * + * <p>It will be used as additional information (INFO tag) in any VOTable and HTML output.</p> + * + * @return The TAP service provider or NULL to leave this field blank. + */ public String getProviderName(); + /** + * <i>[OPTIONAL]</i> + * <p>Description of the service provider.</p> + * + * <p>It will be used as additional information (INFO tag) in any VOTable output.</p> + * + * @return The TAP service description or NULL to leave this field blank. + */ public String getProviderDescription(); + /** + * <i><b>[MANDATORY]</b></i> + * <p>This function controls the state of the whole TAP service.</p> + * + * <p> + * A message explaining the current state of the TAP service could be provided thanks to {@link #getAvailability()}. + * </p> + * + * @return <i>true</i> to enable all TAP resources, <i>false</i> to disable all of them (except /availability). + */ public boolean isAvailable(); + /** + * <i>[OPTIONAL]</i> + * <p>Get an explanation about the current TAP service state (working or not). + * This message aims to provide more details to the users about the availability of this service, + * or more particularly about its unavailability.</p> + * + * @return Explanation about the TAP service state. + */ public String getAvailability(); + /** + * <i>[OPTIONAL]</i> + * <p>Get the limit of the retention period.</p> + * + * <p> + * It is the maximum period while an asynchronous job can leave in the jobs list + * and so can stay on the server. + * </p> + * + * <p><b>Important notes:</b></p> + * <ul> + * <li><b>Exactly 2 values or a NULL object is expected here.</b></li> + * <li><b>If NULL</b>, the retention period is not limited and jobs will + * theoretically stay infinitely on the server.</li> + * <li><b>If not NULL</b>, the 2 values must correspond to the default retention period + * and the maximum retention period.</li> + * <li><b>The default value</b> is used to set the retention period when a job is created with no user defined retention period.</li> + * <li><b>The maximum value</b> is used to limit the retention period when specified by the user while creating a job.</li> + * <li><b>The default value</b> MUST be less or equals the maximum value.</li> + * <li><b>Both values must be positive</b>. If a negative value is given it will be interpreted as "no limit".</li> + * </ul> + * + * @return NULL if no limit must be set, or a two-items array ([0]: default value, [1]: maximum value). + */ public int[] getRetentionPeriod(); + /** + * <i>[OPTIONAL]</i> + * <p>Get the limit of the job execution duration.</p> + * + * <p> + * It is the duration of a running job (including the query execution). + * This duration is used for synchronous AND asynchronous jobs. + * </p> + * + * <p><b>Important notes:</b></p> + * <ul> + * <li><b>Exactly 2 values or a NULL object is expected here.</b></li> + * <li><b>If NULL</b>, the execution duration is not limited and jobs could + * theoretically run infinitely.</li> + * <li><b>If not NULL</b>, the 2 values must correspond to the default execution duration + * and the maximum execution duration.</li> + * <li><b>The default value</b> is used to set the execution duration when a job is created with no user defined execution duration.</li> + * <li><b>The maximum value</b> is used to limit the execution duration when specified by the user while creating a job.</li> + * <li><b>The default value</b> MUST be less or equals the maximum value.</li> + * <li><b>Both values must be positive</b>. If a negative value is given it will be interpreted as "no limit".</li> + * </ul> + * + * @return NULL if no limit must be set, or a two-items array ([0]: default value, [1]: maximum value). + */ public int[] getExecutionDuration(); + /** + * <i>[OPTIONAL]</i> + * <p>Get the limit of the job execution result.</p> + * + * <p> + * This value will limit the size of the query results, either in rows or in bytes. + * The type of limit is defined by the function {@link #getOutputLimitType()}. + * </p> + * + * <p><b>Important notes:</b></p> + * <ul> + * <li><b>Exactly 2 values or a NULL object is expected here.</b></li> + * <li><b>If NULL</b>, the output limit is not limited and jobs could theoretically + * return very big files.</li> + * <li><b>If not NULL</b>, the 2 values must correspond to the default output limit + * and the maximum output limit.</li> + * <li><b>The default value</b> is used to set the output limit when a job is created with no user defined output limit.</li> + * <li><b>The maximum value</b> is used to limit the output limit when specified by the user while creating a job.</li> + * <li><b>The structure of the object</b> returned by this function MUST be the same as the object returned by {@link #getOutputLimitType()}. + * Particularly, the type given by the N-th item of {@link #getOutputLimitType()} must correspond to the N-th limit returned by this function.</li> + * <li><b>The default value</b> MUST be less or equals the maximum value.</li> + * <li><b>Both values must be positive</b>. If a negative value is given it will be interpreted as "no limit".</li> + * </ul> + * + * <p><i><b>Important note:</b> + * To save performances, it is strongly recommended to use ROWS limit rather than in bytes. Indeed, the rows limit can be taken + * into account at the effective execution of the query (so before getting the result), on the contrary of the bytes limit which + * will be applied on the query result. + * </i></p> + * + * @return NULL if no limit must be set, or a two-items array ([0]: default value, [1]: maximum value). + * + * @see #getOutputLimitType() + */ public int[] getOutputLimit(); + /** + * <i>[OPTIONAL]</i> + * <p>Get the type of each output limit set by this service connection (and accessible with {@link #getOutputLimit()}).</p> + * + * <p><b>Important notes:</b></p> + * <ul> + * <li><b>Exactly 2 values or a NULL object is expected here.</b></li> + * <li><b>If NULL</b>, the output limit will be considered as expressed in ROWS.</li> + * <li><b>The structure of the object</b> returned by this function MUST be the same as the object returned by {@link #getOutputLimit()}. + * Particularly, the type given by the N-th item of this function must correspond to the N-th limit returned by {@link #getOutputLimit()}.</li> + * </ul> + * + * <p><i><b>Important note:</b> + * To save performances, it is strongly recommended to use ROWS limit rather than in bytes. Indeed, the rows limit can be taken + * into account at the effective execution of the query (so before getting the result), on the contrary of the bytes limit which + * will be applied on the query result. + * </i></p> + * + * @return NULL if limits should be expressed in ROWS, or a two-items array ([0]: type of getOutputLimit()[0], [1]: type of getOutputLimit()[1]). + * + * @see #getOutputLimit() + */ public LimitUnit[] getOutputLimitType(); + /** + * <i>[OPTIONAL]</i> + * <p>Get the object to use in order to identify users at the origin of requests.</p> + * + * @return NULL if no user identification should be done, a {@link UserIdentifier} instance otherwise. + */ public UserIdentifier getUserIdentifier(); + /** + * <i><b>[MANDATORY]</b></i> + * <p>This function let enable or disable the upload capability of this TAP service.</p> + * + * <p><i>Note: + * If the upload is disabled, the request is aborted and an HTTP-400 error is thrown each time some tables are uploaded. + * </i></p> + * + * @return <i>true</i> to enable the upload capability, <i>false</i> to disable it. + */ public boolean uploadEnabled(); + /** + * <i>[OPTIONAL]</i> + * <p>Get the maximum size of EACH uploaded table.</p> + * + * <p> + * This value is expressed either in rows or in bytes. + * The unit limit is defined by the function {@link #getUploadLimitType()}. + * </p> + * + * <p><b>Important notes:</b></p> + * <ul> + * <li><b>Exactly 2 values or a NULL object is expected here.</b></li> + * <li><b>If NULL</b>, the upload limit is not limited and uploads could be + * theoretically unlimited.</li> + * <li><b>If not NULL</b>, the 2 values must correspond to the default upload limit + * and the maximum upload limit.</li> + * <li><b>The default value</b> is used inform the user about the server wishes.</li> + * <li><b>The maximum value</b> is used to really limit the upload limit.</li> + * <li><b>The structure of the object</b> returned by this function MUST be the same as the object returned by {@link #getUploadLimitType()}. + * Particularly, the type given by the N-th item of {@link #getUploadLimitType()} must correspond to the N-th limit returned by this function.</li> + * <li><b>The default value</b> MUST be less or equals the maximum value.</li> + * <li><b>Both values must be positive</b>. If a negative value is given it will be interpreted as "no limit".</li> + * </ul> + * + * <p><i><b>Important note:</b> + * To save performances, it is recommended to use BYTES limit rather than in rows. Indeed, the bytes limit can be taken + * into account at directly when reading the bytes of the request, on the contrary of the rows limit which + * requires to parse the uploaded tables. + * </i></p> + * + * @return NULL if no limit must be set, or a two-items array ([0]: default value, [1]: maximum value). + * + * @see #getUploadLimitType() + */ public int[] getUploadLimit(); + /** + * <i>[OPTIONAL]</i> + * <p>Get the type of each upload limit set by this service connection (and accessible with {@link #getUploadLimit()}).</p> + * + * <p><b>Important notes:</b></p> + * <ul> + * <li><b>Exactly 2 values or a NULL object is expected here.</b></li> + * <li><b>If NULL</b>, the upload limit will be considered as expressed in ROWS.</li> + * <li><b>The structure of the object</b> returned by this function MUST be the same as the object returned by {@link #getUploadLimit()}. + * Particularly, the type given by the N-th item of this function must correspond to the N-th limit returned by {@link #getUploadLimit()}.</li> + * </ul> + * + * <p><i><b>Important note:</b> + * To save performances, it is recommended to use BYTES limit rather than in rows. Indeed, the bytes limit can be taken + * into account at directly when reading the bytes of the request, on the contrary of the rows limit which + * requires to parse the uploaded tables. + * </i></p> + * + * @return NULL if limits should be expressed in ROWS, or a two-items array ([0]: type of getUploadLimit()[0], [1]: type of getUploadLimit()[1]). + * + * @see #getUploadLimit() + */ public LimitUnit[] getUploadLimitType(); + /** + * <i>[OPTIONAL]</i> + * <p>Get the maximum size of the whole set of all tables uploaded in one request. + * This size is expressed in bytes.</p> + * + * <p><b>IMPORTANT 1: + * This value is always used when the upload capability is enabled. + * </b></p> + * + * <p><b>IMPORTANT 2: + * The value returned by this function MUST always be positive. + * A zero or negative value will throw an exception later while + * reading parameters in a request with some uploaded tables. + * </b></p> + * + * @return A positive (>0) value corresponding to the maximum number of bytes of all uploaded tables sent in one request. + */ public int getMaxUploadSize(); + /** + * <i><b>[MANDATORY]</b></i> + * <p>Get the list of all available tables and columns.</p> + * + * <p> + * This object is really important since it lets the library check ADQL queries properly and set the good type + * and formatting in the query results. + * </p> + * + * @return A TAPMetadata object. <b>NULL is not allowed and will throw a grave error at the service initialization.</b> + */ public TAPMetadata getTAPMetadata(); + /** + * <i>[OPTIONAL]</i> + * <p>Get the list of all allowed coordinate systems.</p> + * + * <u><b>Special values</b></u> + * + * <p>Two special values can be returned by this function:</p> + * <ul> + * <li><b>NULL</b> which means that all coordinate systems are allowed,</li> + * <li><b>the empty list</b> which means that no coordinate system - except + * the default one (which can be reduced to an empty string) - is allowed.</li> + * </ul> + * + * <u><b>List item syntax</b></u> + * + * <p> + * Each item of this list is a <b>pattern</b> and not a simple coordinate system. + * Thus each item MUST respect the following syntax: + * </p> + * <pre>{framePattern} {refposPattern} {flavorPattern}</pre> + * <p> + * Contrary to a coordinate system expression, all these 3 information are required. + * Each may take 3 kinds of value: + * </p> + * <ul> + * <li>a single value (i.e. "ICRS"),</li> + * <li>a list of values with the syntax <code>({value1}|{value2}|...)</code> (i.e. "(ICRS|FK4)"),</li> + * <li>a "*" which means that all values are possible. + * </ul> + * <p> + * For instance: <code>(ICRS|FK4) HELIOCENTER *</code> is a good syntax, + * but not <code>ICRS</code> or <code>ICRS HELIOCENTER</code>. + * </p> + * + * <p><i>Note: + * Even if not explicitly part of the possible values, the default value of each part (i.e. UNKNOWNFRAME for frame) is always taken into account by the library. + * Particularly, the empty string will always be allowed even if not explicitly listed in the list returned by this function. + * </i></p> + * + * @return NULL to allow ALL coordinate systems, an empty list to allow NO coordinate system, + * or a list of coordinate system patterns otherwise. + * + * @since 2.0 + */ public Collection<String> getCoordinateSystems(); /** + * <i>[OPTIONAL]</i> + * <p>Get the list of all allowed geometrical functions.</p> + * + * <u><b>Special values</b></u> + * + * <p>Two special values can be returned by this function:</p> + * <ul> + * <li><b>NULL</b> which means that all geometrical functions are allowed,</li> + * <li><b>the empty list</b> which means that no geometrical functions is allowed.</li> + * </ul> + * + * <u><b>List item syntax</b></u> + * + * <p> + * Each item of the returned list MUST be a function name (i.e. "CONTAINS", "POINT"). + * It can also be a type of STC region to forbid (i.e. "POSITION", "UNION"). + * </p> + * + * <p>The given names are not case sensitive.</p> + * + * @return NULL to allow ALL geometrical functions, an empty list to allow NO geometrical function, + * or a list of geometrical function names otherwise. + * + * @since 2.0 + */ + public Collection<String> getGeometries(); + + /** + * <i>[OPTIONAL]</i> + * <p>Get the list of all allowed User Defined Functions (UDFs).</p> + * + * <u><b>Special values</b></u> + * + * <p>Two special values can be returned by this function:</p> + * <ul> + * <li><b>NULL</b> which means that all unknown functions (which should be UDFs) are allowed,</li> + * <li><b>the empty list</b> which means that no unknown functions (which should be UDFs) is allowed.</li> + * </ul> + * + * <u><b>List item syntax</b></u> + * + * <p> + * Each item of the returned list MUST be an instance of {@link FunctionDef}. + * </p> + * + * @return NULL to allow ALL unknown functions, an empty list to allow NO unknown function, + * or a list of user defined functions otherwise. + * + * @since 2.0 + */ + public Collection<FunctionDef> getUDFs(); + + /** + * <i>[OPTIONAL]</i> + * * <p>Get the maximum number of asynchronous jobs that can run in the same time.</p> * * <p>A null or negative value means <b>no limit</b> on the number of running asynchronous jobs.</p> @@ -91,14 +447,88 @@ public interface ServiceConnection { */ public int getNbMaxAsyncJobs(); + /** + * <i><b>[MANDATORY]</b></i> + * <p>Get the logger to use in the whole service when any error, warning or info happens.</p> + * + * <p><b>IMPORTANT: + * If NULL is returned by this function, grave errors will occur while executing a query or managing an error. + * It is strongly recommended to provide a logger, even a basic implementation. + * </b></p> + * + * <p><i>Piece of advice: + * A default implementation like {@link DefaultTAPLog} would be most of time largely enough. + * </i></p> + * + * @return An instance of {@link TAPLog}. + */ public TAPLog getLogger(); + /** + * <i><b>[MANDATORY]</b></i> + * <p>Get the object able to build other objects essentials to configure the TAP service or to run every queries.</p> + * + * <p><b>IMPORTANT: + * If NULL is returned by this function, grave errors will occur while initializing the service. + * </b></p> + * + * <p><i>Piece of advice: + * The {@link TAPFactory} is an interface which contains a lot of functions to implement. + * It is rather recommended to extend {@link AbstractTAPFactory}: just 3 functions ({@link AbstractTAPFactory#countFreeConnections()}, + * {@link AbstractTAPFactory#freeConnection()}, {@link AbstractTAPFactory#getConnection(String)}) will have to be implemented. + * </i></p> + * + * @return An instance of {@link TAPFactory}. + * + * @see AbstractTAPFactory + */ public TAPFactory getFactory(); + /** + * <i><b>[MANDATORY]</b></i> + * <p>Get the object in charge of the files management. + * This object manages log, error, result and backup files of the whole service.</p> + * + * <p><b>IMPORTANT: + * If NULL is returned by this function, grave errors will occur while initializing the service. + * </b></p> + * + * <p><i>Piece of advice: + * The library provides a default implementation of the interface {@link TAPFileManager}: + * {@link LocalTAPFileManager}, which stores all files on the local file-system. + * </i></p> + * + * @return An instance of {@link TAPFileManager}. + */ public TAPFileManager getFileManager(); + /** + * <i><b>[MANDATORY]</b></i> + * <p>Get the list of all available output formats.</p> + * + * <p><b>IMPORTANT:</b></p> + * <ul> + * <li>All formats of this list MUST have a different MIME type.</li> + * <li>At least one item must correspond to the MIME type "votable".</li> + * <li>If NULL is returned by this function, grave errors will occur while writing the capabilities of this service.</li> + * </li> + * + * @return An iterator on the list of all available output formats. + */ public Iterator<OutputFormat> getOutputFormats(); + /** + * <i><b>[MANDATORY]</b></i> + * <p>Get the output format having the given MIME type (or short MIME type ~ alias).</p> + * + * <p><b>IMPORTANT: + * This function MUST always return an {@link OutputFormat} instance when the MIME type "votable" is given in parameter. + * </b></p> + * + * @param mimeOrAlias MIME type or short MIME type of the format to get. + * + * @return The corresponding {@link OutputFormat} or NULL if not found. + */ public OutputFormat getOutputFormat(final String mimeOrAlias); } diff --git a/src/tap/data/LimitedTableIterator.java b/src/tap/data/LimitedTableIterator.java index 570351137980821c99384fb5fc829b439b8a9f29..97f82e6661285782af2ed190f65e3b07c51f4912 100644 --- a/src/tap/data/LimitedTableIterator.java +++ b/src/tap/data/LimitedTableIterator.java @@ -27,8 +27,8 @@ import java.util.NoSuchElementException; import tap.ServiceConnection.LimitUnit; import tap.metadata.TAPColumn; -import tap.metadata.TAPType; import tap.upload.LimitedSizeInputStream; +import adql.db.DBType; import com.oreilly.servlet.multipart.ExceededSizeException; @@ -219,7 +219,7 @@ public class LimitedTableIterator implements TableIterator { } @Override - public TAPType getColType() throws IllegalStateException, DataReadException{ + public DBType getColType() throws IllegalStateException, DataReadException{ testOverflow(); return innerIt.getColType(); } diff --git a/src/tap/data/ResultSetTableIterator.java b/src/tap/data/ResultSetTableIterator.java index 6f9f6d740fe44be98d7ece03236a7e3a8bc48b2a..a580c87fbfec937fb3008eb44504d10bc2a0d1d3 100644 --- a/src/tap/data/ResultSetTableIterator.java +++ b/src/tap/data/ResultSetTableIterator.java @@ -26,10 +26,10 @@ import java.sql.Timestamp; import java.util.NoSuchElementException; import tap.metadata.TAPColumn; -import tap.metadata.TAPType; -import tap.metadata.TAPType.TAPDatatype; import uws.ISO8601Format; import adql.db.DBColumn; +import adql.db.DBType; +import adql.db.DBType.DBDatatype; /** * <p>{@link TableIterator} which lets iterate over a SQL {@link ResultSet}.</p> @@ -198,11 +198,11 @@ public class ResultSetTableIterator implements TableIterator { try{ colMeta[i - 1] = (TAPColumn)resultMeta[i - 1]; }catch(ClassCastException cce){ - TAPType datatype = convertType(metadata.getColumnTypeName(i), dbms); + DBType datatype = convertType(metadata.getColumnTypeName(i), dbms); colMeta[i - 1] = new TAPColumn(resultMeta[i - 1].getADQLName(), datatype); } }else{ - TAPType datatype = convertType(metadata.getColumnTypeName(i), dbms); + DBType datatype = convertType(metadata.getColumnTypeName(i), dbms); colMeta[i - 1] = new TAPColumn(metadata.getColumnLabel(i), datatype); } } @@ -284,7 +284,7 @@ public class ResultSetTableIterator implements TableIterator { } @Override - public TAPType getColType() throws IllegalStateException, DataReadException{ + public DBType getColType() throws IllegalStateException, DataReadException{ // Basically check the read state (for rows iteration): checkReadState(); @@ -299,7 +299,7 @@ public class ResultSetTableIterator implements TableIterator { } /** - * <p>Convert the given DBMS type into the better matching {@link TAPType} instance. + * <p>Convert the given DBMS type into the better matching {@link DBType} instance. * This function is used to guess the TAP type of a column when it is not provided in the constructor. * It aims not to be exhaustive, but just to provide a type when the given TAP metadata are incomplete.</p> * @@ -328,12 +328,12 @@ public class ResultSetTableIterator implements TableIterator { * @param dbmsType DBMS column datatype name. * @param dbms Lower-case string which indicates which DBMS the ResultSet is coming from. <i>note: MAY be NULL.</i> * - * @return The best suited {@link TAPType} object. + * @return The best suited {@link DBType} object. */ - protected TAPType convertType(String dbmsType, final String dbms){ + protected DBType convertType(String dbmsType, final String dbms){ // If no type is provided return VARCHAR: if (dbmsType == null || dbmsType.trim().length() == 0) - return new TAPType(TAPDatatype.VARCHAR, TAPType.NO_LENGTH); + return new DBType(DBDatatype.VARCHAR, DBType.NO_LENGTH); // Extract the type prefix and lower-case it: dbmsType = dbmsType.toLowerCase(); @@ -345,61 +345,61 @@ public class ResultSetTableIterator implements TableIterator { if (dbms != null && dbms.equals("sqlite")){ // INTEGER -> SMALLINT, INTEGER, BIGINT if (dbmsTypePrefix.equals("integer")) - return new TAPType(TAPDatatype.BIGINT); + return new DBType(DBDatatype.BIGINT); // REAL -> REAL, DOUBLE else if (dbmsTypePrefix.equals("real")) - return new TAPType(TAPDatatype.DOUBLE); + return new DBType(DBDatatype.DOUBLE); // TEXT -> CHAR, VARCHAR, CLOB, TIMESTAMP else if (dbmsTypePrefix.equals("text")) - return new TAPType(TAPDatatype.VARCHAR); + return new DBType(DBDatatype.VARCHAR); // BLOB -> BINARY, VARBINARY, BLOB else if (dbmsTypePrefix.equals("blob")) - return new TAPType(TAPDatatype.BLOB); + return new DBType(DBDatatype.BLOB); // Default: else - return new TAPType(TAPDatatype.VARCHAR, TAPType.NO_LENGTH); + return new DBType(DBDatatype.VARCHAR, DBType.NO_LENGTH); } // CASE: OTHER DBMS else{ // SMALLINT if (dbmsTypePrefix.equals("smallint") || dbmsTypePrefix.equals("int2")) - return new TAPType(TAPDatatype.SMALLINT); + return new DBType(DBDatatype.SMALLINT); // INTEGER else if (dbmsTypePrefix.equals("integer") || dbmsTypePrefix.equals("int") || dbmsTypePrefix.equals("int4")) - return new TAPType(TAPDatatype.INTEGER); + return new DBType(DBDatatype.INTEGER); // BIGINT - else if (dbmsTypePrefix.equals("bigint") || dbmsTypePrefix.equals("int8") || dbmsTypePrefix.equals("int4") || dbmsTypePrefix.equals("number")) - return new TAPType(TAPDatatype.BIGINT); + else if (dbmsTypePrefix.equals("bigint") || dbmsTypePrefix.equals("int8") || dbmsTypePrefix.equals("number")) + return new DBType(DBDatatype.BIGINT); // REAL else if (dbmsTypePrefix.equals("float4") || (dbmsTypePrefix.equals("float") && firstParam <= 63)) - return new TAPType(TAPDatatype.REAL); + return new DBType(DBDatatype.REAL); // DOUBLE else if (dbmsTypePrefix.equals("double") || dbmsTypePrefix.equals("double precision") || dbmsTypePrefix.equals("float8") || (dbmsTypePrefix.equals("float") && firstParam > 63)) - return new TAPType(TAPDatatype.DOUBLE); + return new DBType(DBDatatype.DOUBLE); // BINARY else if (dbmsTypePrefix.equals("binary") || dbmsTypePrefix.equals("raw") || ((dbmsTypePrefix.equals("char") || dbmsTypePrefix.equals("character")) && dbmsType.endsWith(" for bit data"))) - return new TAPType(TAPDatatype.BINARY, firstParam); + return new DBType(DBDatatype.BINARY, firstParam); // VARBINARY else if (dbmsTypePrefix.equals("varbinary") || dbmsTypePrefix.equals("long raw") || ((dbmsTypePrefix.equals("varchar") || dbmsTypePrefix.equals("character varying")) && dbmsType.endsWith(" for bit data"))) - return new TAPType(TAPDatatype.VARBINARY, firstParam); + return new DBType(DBDatatype.VARBINARY, firstParam); // CHAR else if (dbmsTypePrefix.equals("char") || dbmsTypePrefix.equals("character")) - return new TAPType(TAPDatatype.CHAR, firstParam); + return new DBType(DBDatatype.CHAR, firstParam); // VARCHAR else if (dbmsTypePrefix.equals("varchar") || dbmsTypePrefix.equals("varchar2") || dbmsTypePrefix.equals("character varying")) - return new TAPType(TAPDatatype.VARBINARY, firstParam); + return new DBType(DBDatatype.VARBINARY, firstParam); // BLOB else if (dbmsTypePrefix.equals("bytea") || dbmsTypePrefix.equals("blob") || dbmsTypePrefix.equals("binary large object")) - return new TAPType(TAPDatatype.BLOB); + return new DBType(DBDatatype.BLOB); // CLOB else if (dbmsTypePrefix.equals("text") || dbmsTypePrefix.equals("clob") || dbmsTypePrefix.equals("character large object")) - return new TAPType(TAPDatatype.CLOB); + return new DBType(DBDatatype.CLOB); // TIMESTAMP else if (dbmsTypePrefix.equals("timestamp")) - return new TAPType(TAPDatatype.TIMESTAMP); + return new DBType(DBDatatype.TIMESTAMP); // Default: else - return new TAPType(TAPDatatype.VARCHAR, TAPType.NO_LENGTH); + return new DBType(DBDatatype.VARCHAR, DBType.NO_LENGTH); } } @@ -409,22 +409,22 @@ public class ResultSetTableIterator implements TableIterator { * <p> * If the given type string does not contain any parameter * OR if the first parameter can not be casted into an integer, - * {@link TAPType#NO_LENGTH} will be returned. + * {@link DBType#NO_LENGTH} will be returned. * </p> * * @param dbmsType DBMS type string (containing the datatype and the 'length' parameter). * @param paramIndex Index of the open bracket. * - * @return The 'length' parameter value if found, {@link TAPType#NO_LENGTH} otherwise. + * @return The 'length' parameter value if found, {@link DBType#NO_LENGTH} otherwise. */ protected final int getLengthParam(final String dbmsType, final int paramIndex){ // If no parameter has been previously detected, no length parameter: if (paramIndex <= 0) - return TAPType.NO_LENGTH; + return DBType.NO_LENGTH; // If there is one and that at least ONE parameter is provided.... else{ - int lengthParam = TAPType.NO_LENGTH; + int lengthParam = DBType.NO_LENGTH; String paramsStr = dbmsType.substring(paramIndex + 1); // ...extract the 'length' parameter: diff --git a/src/tap/data/TableIterator.java b/src/tap/data/TableIterator.java index 0aed73cc51e660db38c53a58a752a471df8fa766..17d8445d1e3e7a681685e0bd73b6254d0ba63cb4 100644 --- a/src/tap/data/TableIterator.java +++ b/src/tap/data/TableIterator.java @@ -21,8 +21,8 @@ package tap.data; import java.util.NoSuchElementException; +import adql.db.DBType; import tap.metadata.TAPColumn; -import tap.metadata.TAPType; /** * <p>Let's iterate on each row and then on each column over a table dataset.</p> @@ -126,7 +126,7 @@ public interface TableIterator { * @throws IllegalStateException If {@link #nextCol()} has not yet been called. * @throws DataReadException If an error occurs while reading the table dataset. */ - public TAPType getColType() throws IllegalStateException, DataReadException; + public DBType getColType() throws IllegalStateException, DataReadException; /** * Close the stream or input over which this class iterates. diff --git a/src/tap/data/VOTableIterator.java b/src/tap/data/VOTableIterator.java index 861ac52b8dc9e6d9bfcb5e59d117db9508a80501..c79dd05eeb33ffd48169d84174f420e5aa476b42 100644 --- a/src/tap/data/VOTableIterator.java +++ b/src/tap/data/VOTableIterator.java @@ -23,9 +23,9 @@ import java.io.IOException; import java.io.InputStream; import java.util.NoSuchElementException; +import adql.db.DBType; import tap.TAPException; import tap.metadata.TAPColumn; -import tap.metadata.TAPType; import tap.metadata.VotType; import tap.metadata.VotType.VotDatatype; import uk.ac.starlink.table.ColumnInfo; @@ -131,7 +131,7 @@ public class VOTableIterator implements TableIterator { String xtype = getAuxDatumValue(colInfo, "xtype"); // Resolve the field type: - TAPType type = resolveVotType(datatype, arraysize, xtype).toTAPType(); + DBType type = resolveVotType(datatype, arraysize, xtype).toTAPType(); // build the TAPColumn object: TAPColumn col = new TAPColumn(colInfo.getName(), type, colInfo.getDescription(), colInfo.getUnitString(), colInfo.getUCD(), colInfo.getUtype()); @@ -255,7 +255,7 @@ public class VOTableIterator implements TableIterator { } @Override - public TAPType getColType() throws IllegalStateException, DataReadException{ + public DBType getColType() throws IllegalStateException, DataReadException{ // Basically check the read state (for rows iteration): checkReadState(); diff --git a/src/tap/db/JDBCConnection.java b/src/tap/db/JDBCConnection.java index fc1331fcbcf320b0f280e86d7eef9bc5ce4192d5..1e1a836f92d422fbf8ed4f89247d203993947a56 100644 --- a/src/tap/db/JDBCConnection.java +++ b/src/tap/db/JDBCConnection.java @@ -17,7 +17,7 @@ package tap.db; * along with TAPLibrary. If not, see <http://www.gnu.org/licenses/>. * * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS), - * Astronomishes Rechen Institut (ARI) + * Astronomisches Rechen Institut (ARI) */ import java.sql.Connection; @@ -47,10 +47,10 @@ import tap.metadata.TAPMetadata.STDTable; import tap.metadata.TAPSchema; import tap.metadata.TAPTable; import tap.metadata.TAPTable.TableType; -import tap.metadata.TAPType; -import tap.metadata.TAPType.TAPDatatype; import uws.ISO8601Format; import uws.service.log.UWSLog.LogLevel; +import adql.db.DBType; +import adql.db.DBType.DBDatatype; import adql.query.ADQLQuery; import adql.query.IdentifierField; import adql.translator.ADQLTranslator; @@ -97,7 +97,7 @@ import adql.translator.TranslationException; * * <h3>Datatypes</h3> * - * <p>Column types are converted from DBMS to TAP types with {@link #getTAPType(String)} and from TAP to DBMS types with {@link #getDBMSDatatype(TAPType)}.</p> + * <p>Column types are converted from DBMS to TAP types with {@link #getTAPType(String)} and from TAP to DBMS types with {@link #getDBMSDatatype(DBType)}.</p> * * <p> * All typical DBMS datatypes are taken into account, <b>EXCEPT the geometrical types</b> (POINT and REGION). For these types, the only object having this @@ -635,19 +635,19 @@ public class JDBCConnection implements DBConnection { } // resolve the column type (if any) ; by default, it will be "VARCHAR" if unknown or missing: - TAPDatatype tapDatatype = null; + DBDatatype tapDatatype = null; // ...try to resolve the datatype in function of all datatypes declared by the TAP standard. if (datatype != null){ try{ - tapDatatype = TAPDatatype.valueOf(datatype.toUpperCase()); + tapDatatype = DBDatatype.valueOf(datatype.toUpperCase()); }catch(IllegalArgumentException iae){} } // ...build the column type: - TAPType type; + DBType type; if (tapDatatype == null) - type = new TAPType(TAPDatatype.VARCHAR); + type = new DBType(DBDatatype.VARCHAR); else - type = new TAPType(tapDatatype, size); + type = new DBType(tapDatatype, size); // create the new column: TAPColumn newColumn = new TAPColumn(columnName, type, nullifyIfNeeded(description), nullifyIfNeeded(unit), nullifyIfNeeded(ucd), nullifyIfNeeded(utype)); @@ -1591,7 +1591,7 @@ public class JDBCConnection implements DBConnection { Object val = data.nextCol(); /* If the value is supposed to be a Timestamp, parse it * and build an appropriate SQL object: */ - if (val != null && cols[c - 1].getDatatype().type == TAPDatatype.TIMESTAMP){ + if (val != null && cols[c - 1].getDatatype().type == DBDatatype.TIMESTAMP){ try{ val = new Timestamp(ISO8601Format.parse(val.toString())); }catch(ParseException pe){ @@ -1728,9 +1728,9 @@ public class JDBCConnection implements DBConnection { * * @return The corresponding DB type, or NULL if the given type is not managed or is NULL. */ - protected String getDBMSDatatype(TAPType datatype){ + protected String getDBMSDatatype(DBType datatype){ if (datatype == null) - datatype = new TAPType(TAPDatatype.VARCHAR); + datatype = new DBType(DBDatatype.VARCHAR); switch(datatype.type){ diff --git a/src/tap/error/DefaultTAPErrorWriter.java b/src/tap/error/DefaultTAPErrorWriter.java index d347c673585433407fd56e73bf7e55cbb07f031b..eb194e35711bd4606a0272d959ae7b1ceed93505 100644 --- a/src/tap/error/DefaultTAPErrorWriter.java +++ b/src/tap/error/DefaultTAPErrorWriter.java @@ -114,7 +114,7 @@ public class DefaultTAPErrorWriter implements ServiceErrorWriter { // Otherwise, log it and write a message to the user: else // write a message to the user: - writeError("INTERNAL SERVER ERROR! Sorry, this error is grave and unexpected. No explaination can be provided for the moment. Details about this error have been reported in the service log files ; you should try again your request later or notify the administrator(s) by yourself (with the following REQ_ID).", ErrorType.FATAL, UWSException.INTERNAL_SERVER_ERROR, response, request, reqID, user, action); + writeError("INTERNAL SERVER ERROR! Sorry, this error is grave and unexpected. No explanation can be provided for the moment. Details about this error have been reported in the service log files ; you should try again your request later or notify the administrator(s) by yourself (with the following REQ_ID).", ErrorType.FATAL, UWSException.INTERNAL_SERVER_ERROR, response, request, reqID, user, action); } @Override diff --git a/src/tap/formatter/JSONFormat.java b/src/tap/formatter/JSONFormat.java index 06f3e230231c8341f395d90f4dc29a6960269514..1596827b50b8459c191c808c29a9c51c0c2f1091 100644 --- a/src/tap/formatter/JSONFormat.java +++ b/src/tap/formatter/JSONFormat.java @@ -32,11 +32,11 @@ import tap.TAPException; import tap.TAPExecutionReport; import tap.data.TableIterator; import tap.metadata.TAPColumn; -import tap.metadata.TAPType; -import tap.metadata.TAPType.TAPDatatype; import tap.metadata.VotType; import uws.service.log.UWSLog.LogLevel; import adql.db.DBColumn; +import adql.db.DBType; +import adql.db.DBType.DBDatatype; /** * Format any given query (table) result into JSON. @@ -212,7 +212,7 @@ public class JSONFormat implements OutputFormat { else return (TAPColumn)typeFromResult.copy(); }else - return new TAPColumn((typeFromQuery != null) ? typeFromQuery.getADQLName() : "?", new TAPType(TAPDatatype.VARCHAR), "?"); + return new TAPColumn((typeFromQuery != null) ? typeFromQuery.getADQLName() : "?", new DBType(DBDatatype.VARCHAR), "?"); } /** @@ -237,7 +237,7 @@ public class JSONFormat implements OutputFormat { out.key("description").value(tapCol.getDescription()); // "datatype": "..." - VotType votType = tapCol.getDatatype().toVotType(); + VotType votType = new VotType(tapCol.getDatatype()); out.key("datatype").value(votType.datatype); // "arraysize": "..." (if any) diff --git a/src/tap/formatter/VOTableFormat.java b/src/tap/formatter/VOTableFormat.java index a1beb23fcb8edc20b4236bf255a5425961e35c86..7ce1f63abe5fc1bed42e3ffe77db86dad6000c97 100644 --- a/src/tap/formatter/VOTableFormat.java +++ b/src/tap/formatter/VOTableFormat.java @@ -35,8 +35,6 @@ import tap.data.DataReadException; import tap.data.TableIterator; import tap.error.DefaultTAPErrorWriter; import tap.metadata.TAPColumn; -import tap.metadata.TAPType; -import tap.metadata.TAPType.TAPDatatype; import tap.metadata.VotType; import tap.metadata.VotType.VotDatatype; import uk.ac.starlink.table.AbstractStarTable; @@ -50,6 +48,8 @@ import uk.ac.starlink.votable.VOSerializer; import uk.ac.starlink.votable.VOTableVersion; import uws.service.log.UWSLog.LogLevel; import adql.db.DBColumn; +import adql.db.DBType; +import adql.db.DBType.DBDatatype; /** * <p>Format any given query (table) result into VOTable.</p> @@ -426,6 +426,12 @@ public class VOTableFormat implements OutputFormat { out.newLine(); } + /* TODO Add somewhere in the table header the different Coordinate Systems used in this result! + * 2 ways to do so: + * 1/ COOSYS (deprecated from VOTable 1.2, but soon un-deprecated) + * 2/ a GROUP item with the STC expression of the coordinate system. + */ + out.flush(); } @@ -495,7 +501,7 @@ public class VOTableFormat implements OutputFormat { else return (TAPColumn)typeFromResult.copy(); }else - return new TAPColumn((typeFromQuery != null) ? typeFromQuery.getADQLName() : "?", new TAPType(TAPDatatype.VARCHAR), "?"); + return new TAPColumn((typeFromQuery != null) ? typeFromQuery.getADQLName() : "?", new DBType(DBDatatype.VARCHAR), "?"); } /** @@ -507,7 +513,7 @@ public class VOTableFormat implements OutputFormat { */ protected static final ColumnInfo getColumnInfo(final TAPColumn tapCol){ // Get the VOTable type: - VotType votType = tapCol.getDatatype().toVotType(); + VotType votType = new VotType(tapCol.getDatatype()); // Build a ColumnInfo with the name, type and description: ColumnInfo colInfo = new ColumnInfo(tapCol.getADQLName(), getDatatypeClass(votType.datatype, votType.arraysize), tapCol.getDescription()); diff --git a/src/tap/metadata/TAPColumn.java b/src/tap/metadata/TAPColumn.java index 3e56db180277b7df80385d058868e706bc1f4cdc..13cb81a25ce9d59dc184c3a7c9737a2ea5cc58a1 100644 --- a/src/tap/metadata/TAPColumn.java +++ b/src/tap/metadata/TAPColumn.java @@ -25,9 +25,10 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.Map; -import tap.metadata.TAPType.TAPDatatype; import adql.db.DBColumn; import adql.db.DBTable; +import adql.db.DBType; +import adql.db.DBType.DBDatatype; /** * <p>Represent a column as described by the IVOA standard in the TAP protocol definition.</p> @@ -101,7 +102,7 @@ public class TAPColumn implements DBColumn { /** Type of this column. * <i>Note: Standard TAP column field ; CAN'T be NULL.</i> */ - private TAPType datatype = new TAPType(TAPDatatype.VARCHAR); + private DBType datatype = new DBType(DBDatatype.VARCHAR); /** Flag indicating whether this column is one of those that should be returned by default. * <i>Note: Standard TAP column field ; FALSE by default.</i> */ @@ -170,16 +171,16 @@ public class TAPColumn implements DBColumn { * </i></p> * * <p><i>Note: - * The datatype is set by calling the function {@link #setDatatype(TAPType)} which does not do + * The datatype is set by calling the function {@link #setDatatype(DBType)} which does not do * anything if the given datatype is NULL. * </i></p> * * @param columnName Name that this column MUST have in ADQL queries. <i>CAN'T be NULL ; this name can never be changed after.</i> * @param type Datatype of this column. <i>If NULL, VARCHAR will be the datatype of this column</i> * - * @see #setDatatype(TAPType) + * @see #setDatatype(DBType) */ - public TAPColumn(String columnName, TAPType type){ + public TAPColumn(String columnName, DBType type){ this(columnName); setDatatype(type); } @@ -201,7 +202,7 @@ public class TAPColumn implements DBColumn { * @param description Description of the column's content. <i>May be NULL</i> */ public TAPColumn(String columnName, String description){ - this(columnName, (TAPType)null, description); + this(columnName, (DBType)null, description); } /** @@ -218,7 +219,7 @@ public class TAPColumn implements DBColumn { * </i></p> * * <p><i>Note: - * The datatype is set by calling the function {@link #setDatatype(TAPType)} which does do + * The datatype is set by calling the function {@link #setDatatype(DBType)} which does do * anything if the given datatype is NULL. * </i></p> * @@ -226,7 +227,7 @@ public class TAPColumn implements DBColumn { * @param type Datatype of this column. <i>If NULL, VARCHAR will be the datatype of this column</i> * @param description Description of the column's content. <i>May be NULL</i> */ - public TAPColumn(String columnName, TAPType type, String description){ + public TAPColumn(String columnName, DBType type, String description){ this(columnName, type); this.description = description; } @@ -266,7 +267,7 @@ public class TAPColumn implements DBColumn { * </i></p> * * <p><i>Note: - * The datatype is set by calling the function {@link #setDatatype(TAPType)} which does do + * The datatype is set by calling the function {@link #setDatatype(DBType)} which does do * anything if the given datatype is NULL. * </i></p> * @@ -275,7 +276,7 @@ public class TAPColumn implements DBColumn { * @param description Description of the column's content. <i>May be NULL</i> * @param unit Unit of the column's values. <i>May be NULL</i> */ - public TAPColumn(String columnName, TAPType type, String description, String unit){ + public TAPColumn(String columnName, DBType type, String description, String unit){ this(columnName, type, description); this.unit = unit; } @@ -294,7 +295,7 @@ public class TAPColumn implements DBColumn { * </i></p> * * <p><i>Note: - * The datatype is set by calling the function {@link #setDatatype(TAPType)} which does do + * The datatype is set by calling the function {@link #setDatatype(DBType)} which does do * anything if the given datatype is NULL. * </i></p> * @@ -322,7 +323,7 @@ public class TAPColumn implements DBColumn { * </i></p> * * <p><i>Note: - * The datatype is set by calling the function {@link #setDatatype(TAPType)} which does do + * The datatype is set by calling the function {@link #setDatatype(DBType)} which does do * anything if the given datatype is NULL. * </i></p> * @@ -333,7 +334,7 @@ public class TAPColumn implements DBColumn { * @param ucd UCD describing the scientific content of this column. * @param utype UType associating this column with a data-model. */ - public TAPColumn(String columnName, TAPType type, String description, String unit, String ucd, String utype){ + public TAPColumn(String columnName, DBType type, String description, String unit, String ucd, String utype){ this(columnName, type, description, unit); this.ucd = ucd; this.utype = utype; @@ -479,7 +480,7 @@ public class TAPColumn implements DBColumn { * * @return Its datatype. <i>CAN'T be NULL</i> */ - public final TAPType getDatatype(){ + public final DBType getDatatype(){ return datatype; } @@ -492,7 +493,7 @@ public class TAPColumn implements DBColumn { * * @param type Its new datatype. */ - public final void setDatatype(final TAPType type){ + public final void setDatatype(final DBType type){ if (type != null) datatype = type; } diff --git a/src/tap/metadata/TAPMetadata.java b/src/tap/metadata/TAPMetadata.java index 15a57b044b4259a1e6f2cf5b06fa374a58f8aa4c..68e0b1c63b15ea90cf1fbec001147e61da00989f 100644 --- a/src/tap/metadata/TAPMetadata.java +++ b/src/tap/metadata/TAPMetadata.java @@ -34,11 +34,12 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import tap.metadata.TAPTable.TableType; -import tap.metadata.TAPType.TAPDatatype; import tap.resource.Capabilities; import tap.resource.TAPResource; import tap.resource.VOSIResource; import adql.db.DBTable; +import adql.db.DBType; +import adql.db.DBType.DBDatatype; /** * <p>Let listing all schemas, tables and columns available in a TAP service. @@ -730,49 +731,49 @@ public class TAPMetadata implements Iterable<TAPSchema>, VOSIResource, TAPResour case SCHEMAS: TAPTable schemas = new TAPTable(STDTable.SCHEMAS.toString(), TableType.table, "List of schemas published in this TAP service.", null); - schemas.addColumn("schema_name", new TAPType(TAPDatatype.VARCHAR), "schema name, possibly qualified", null, null, null, true, true, true); - schemas.addColumn("description", new TAPType(TAPDatatype.VARCHAR), "brief description of schema", null, null, null, false, false, true); - schemas.addColumn("utype", new TAPType(TAPDatatype.VARCHAR), "UTYPE if schema corresponds to a data model", null, null, null, false, false, true); + schemas.addColumn("schema_name", new DBType(DBDatatype.VARCHAR), "schema name, possibly qualified", null, null, null, true, true, true); + schemas.addColumn("description", new DBType(DBDatatype.VARCHAR), "brief description of schema", null, null, null, false, false, true); + schemas.addColumn("utype", new DBType(DBDatatype.VARCHAR), "UTYPE if schema corresponds to a data model", null, null, null, false, false, true); return schemas; case TABLES: TAPTable tables = new TAPTable(STDTable.TABLES.toString(), TableType.table, "List of tables published in this TAP service.", null); - tables.addColumn("schema_name", new TAPType(TAPDatatype.VARCHAR), "the schema name from TAP_SCHEMA.schemas", null, null, null, true, true, true); - tables.addColumn("table_name", new TAPType(TAPDatatype.VARCHAR), "table name as it should be used in queries", null, null, null, true, true, true); - tables.addColumn("table_type", new TAPType(TAPDatatype.VARCHAR), "one of: table, view", null, null, null, false, false, true); - tables.addColumn("description", new TAPType(TAPDatatype.VARCHAR), "brief description of table", null, null, null, false, false, true); - tables.addColumn("utype", new TAPType(TAPDatatype.VARCHAR), "UTYPE if table corresponds to a data model", null, null, null, false, false, true); + tables.addColumn("schema_name", new DBType(DBDatatype.VARCHAR), "the schema name from TAP_SCHEMA.schemas", null, null, null, true, true, true); + tables.addColumn("table_name", new DBType(DBDatatype.VARCHAR), "table name as it should be used in queries", null, null, null, true, true, true); + tables.addColumn("table_type", new DBType(DBDatatype.VARCHAR), "one of: table, view", null, null, null, false, false, true); + tables.addColumn("description", new DBType(DBDatatype.VARCHAR), "brief description of table", null, null, null, false, false, true); + tables.addColumn("utype", new DBType(DBDatatype.VARCHAR), "UTYPE if table corresponds to a data model", null, null, null, false, false, true); return tables; case COLUMNS: TAPTable columns = new TAPTable(STDTable.COLUMNS.toString(), TableType.table, "List of columns of all tables listed in TAP_SCHEMA.TABLES and published in this TAP service.", null); - columns.addColumn("table_name", new TAPType(TAPDatatype.VARCHAR), "table name from TAP_SCHEMA.tables", null, null, null, true, true, true); - columns.addColumn("column_name", new TAPType(TAPDatatype.VARCHAR), "column name", null, null, null, true, true, true); - columns.addColumn("description", new TAPType(TAPDatatype.VARCHAR), "brief description of column", null, null, null, false, false, true); - columns.addColumn("unit", new TAPType(TAPDatatype.VARCHAR), "unit in VO standard format", null, null, null, false, false, true); - columns.addColumn("ucd", new TAPType(TAPDatatype.VARCHAR), "UCD of column if any", null, null, null, false, false, true); - columns.addColumn("utype", new TAPType(TAPDatatype.VARCHAR), "UTYPE of column if any", null, null, null, false, false, true); - columns.addColumn("datatype", new TAPType(TAPDatatype.VARCHAR), "ADQL datatype as in section 2.5", null, null, null, false, false, true); - columns.addColumn("size", new TAPType(TAPDatatype.INTEGER), "length of variable length datatypes", null, null, null, false, false, true); - columns.addColumn("principal", new TAPType(TAPDatatype.INTEGER), "a principal column; 1 means true, 0 means false", null, null, null, false, false, true); - columns.addColumn("indexed", new TAPType(TAPDatatype.INTEGER), "an indexed column; 1 means true, 0 means false", null, null, null, false, false, true); - columns.addColumn("std", new TAPType(TAPDatatype.INTEGER), "a standard column; 1 means true, 0 means false", null, null, null, false, false, true); + columns.addColumn("table_name", new DBType(DBDatatype.VARCHAR), "table name from TAP_SCHEMA.tables", null, null, null, true, true, true); + columns.addColumn("column_name", new DBType(DBDatatype.VARCHAR), "column name", null, null, null, true, true, true); + columns.addColumn("description", new DBType(DBDatatype.VARCHAR), "brief description of column", null, null, null, false, false, true); + columns.addColumn("unit", new DBType(DBDatatype.VARCHAR), "unit in VO standard format", null, null, null, false, false, true); + columns.addColumn("ucd", new DBType(DBDatatype.VARCHAR), "UCD of column if any", null, null, null, false, false, true); + columns.addColumn("utype", new DBType(DBDatatype.VARCHAR), "UTYPE of column if any", null, null, null, false, false, true); + columns.addColumn("datatype", new DBType(DBDatatype.VARCHAR), "ADQL datatype as in section 2.5", null, null, null, false, false, true); + columns.addColumn("size", new DBType(DBDatatype.INTEGER), "length of variable length datatypes", null, null, null, false, false, true); + columns.addColumn("principal", new DBType(DBDatatype.INTEGER), "a principal column; 1 means true, 0 means false", null, null, null, false, false, true); + columns.addColumn("indexed", new DBType(DBDatatype.INTEGER), "an indexed column; 1 means true, 0 means false", null, null, null, false, false, true); + columns.addColumn("std", new DBType(DBDatatype.INTEGER), "a standard column; 1 means true, 0 means false", null, null, null, false, false, true); return columns; case KEYS: TAPTable keys = new TAPTable(STDTable.KEYS.toString(), TableType.table, "List all foreign keys but provides just the tables linked by the foreign key. To know which columns of these tables are linked, see in TAP_SCHEMA.key_columns using the key_id.", null); - keys.addColumn("key_id", new TAPType(TAPDatatype.VARCHAR), "unique key identifier", null, null, null, true, true, true); - keys.addColumn("from_table", new TAPType(TAPDatatype.VARCHAR), "fully qualified table name", null, null, null, false, false, true); - keys.addColumn("target_table", new TAPType(TAPDatatype.VARCHAR), "fully qualified table name", null, null, null, false, false, true); - keys.addColumn("description", new TAPType(TAPDatatype.VARCHAR), "description of this key", null, null, null, false, false, true); - keys.addColumn("utype", new TAPType(TAPDatatype.VARCHAR), "utype of this key", null, null, null, false, false, true); + keys.addColumn("key_id", new DBType(DBDatatype.VARCHAR), "unique key identifier", null, null, null, true, true, true); + keys.addColumn("from_table", new DBType(DBDatatype.VARCHAR), "fully qualified table name", null, null, null, false, false, true); + keys.addColumn("target_table", new DBType(DBDatatype.VARCHAR), "fully qualified table name", null, null, null, false, false, true); + keys.addColumn("description", new DBType(DBDatatype.VARCHAR), "description of this key", null, null, null, false, false, true); + keys.addColumn("utype", new DBType(DBDatatype.VARCHAR), "utype of this key", null, null, null, false, false, true); return keys; case KEY_COLUMNS: TAPTable key_columns = new TAPTable(STDTable.KEY_COLUMNS.toString(), TableType.table, "List all foreign keys but provides just the columns linked by the foreign key. To know the table of these columns, see in TAP_SCHEMA.keys using the key_id.", null); - key_columns.addColumn("key_id", new TAPType(TAPDatatype.VARCHAR), "unique key identifier", null, null, null, true, true, true); - key_columns.addColumn("from_column", new TAPType(TAPDatatype.VARCHAR), "key column name in the from_table", null, null, null, false, false, true); - key_columns.addColumn("target_column", new TAPType(TAPDatatype.VARCHAR), "key column name in the target_table", null, null, null, false, false, true); + key_columns.addColumn("key_id", new DBType(DBDatatype.VARCHAR), "unique key identifier", null, null, null, true, true, true); + key_columns.addColumn("from_column", new DBType(DBDatatype.VARCHAR), "key column name in the from_table", null, null, null, false, false, true); + key_columns.addColumn("target_column", new DBType(DBDatatype.VARCHAR), "key column name in the target_table", null, null, null, false, false, true); return key_columns; default: diff --git a/src/tap/metadata/TAPTable.java b/src/tap/metadata/TAPTable.java index 4685a41eb315ce175d9f23a6b5b907d768814976..9f001f323b24bc37c9eec525e3bcee1784ffe74f 100644 --- a/src/tap/metadata/TAPTable.java +++ b/src/tap/metadata/TAPTable.java @@ -30,6 +30,7 @@ import java.util.Map; import tap.TAPException; import adql.db.DBColumn; import adql.db.DBTable; +import adql.db.DBType; /** * <p>Represent a table as described by the IVOA standard in the TAP protocol definition.</p> @@ -433,10 +434,10 @@ public class TAPTable implements DBTable { * @return The created and added {@link TAPColumn} object, * or NULL if the given name is NULL or an empty string. * - * @see TAPColumn#TAPColumn(String, TAPType, String, String, String, String) + * @see TAPColumn#TAPColumn(String, DBType, String, String, String, String) * @see #addColumn(TAPColumn) */ - public TAPColumn addColumn(String columnName, TAPType datatype, String description, String unit, String ucd, String utype){ + public TAPColumn addColumn(String columnName, DBType datatype, String description, String unit, String ucd, String utype){ if (columnName == null || columnName.trim().length() <= 0) return null; @@ -466,13 +467,13 @@ public class TAPTable implements DBTable { * @return The created and added {@link TAPColumn} object, * or NULL if the given name is NULL or an empty string. * - * @see TAPColumn#TAPColumn(String, TAPType, String, String, String, String) + * @see TAPColumn#TAPColumn(String, DBType, String, String, String, String) * @see TAPColumn#setPrincipal(boolean) * @see TAPColumn#setIndexed(boolean) * @see TAPColumn#setStd(boolean) * @see #addColumn(TAPColumn) */ - public TAPColumn addColumn(String columnName, TAPType datatype, String description, String unit, String ucd, String utype, boolean principal, boolean indexed, boolean std){ + public TAPColumn addColumn(String columnName, DBType datatype, String description, String unit, String ucd, String utype, boolean principal, boolean indexed, boolean std){ if (columnName == null || columnName.trim().length() <= 0) return null; diff --git a/src/tap/metadata/VotType.java b/src/tap/metadata/VotType.java index 203c01d0733c73c3797b883fa9b78fe7611c65f9..35f8babfd4e5863b573ef993d29c876975dbf742 100644 --- a/src/tap/metadata/VotType.java +++ b/src/tap/metadata/VotType.java @@ -17,11 +17,12 @@ package tap.metadata; * along with TAPLibrary. If not, see <http://www.gnu.org/licenses/>. * * Copyright 2012,2014 - UDS/Centre de Données astronomiques de Strasbourg (CDS), - * Astronomishes Rechen Institut (ARI) + * Astronomisches Rechen Institut (ARI) */ +import adql.db.DBType; +import adql.db.DBType.DBDatatype; import tap.TAPException; -import tap.metadata.TAPType.TAPDatatype; import uk.ac.starlink.votable.VOSerializer; /** @@ -120,11 +121,11 @@ public final class VotType { } /** - * Build a {@link VotType} object by converting the given {@link TAPType}. + * Build a {@link VotType} object by converting the given {@link DBType}. * - * @param tapType {@link TAPType} to convert. + * @param tapType {@link DBType} to convert. */ - public VotType(final TAPType tapType){ + public VotType(final DBType tapType){ switch(tapType.type){ case SMALLINT: this.datatype = VotDatatype.SHORT; @@ -250,11 +251,11 @@ public final class VotType { /** * Convert this VOTable type definition into a TAPColumn type. * - * @return The corresponding {@link TAPType}. + * @return The corresponding {@link DBType}. * * @throws TAPException If the conversion is impossible (particularly if the array-size refers to a multi-dimensional array ; only 1D arrays are allowed). */ - public TAPType toTAPType() throws TAPException{ + public DBType toTAPType() throws TAPException{ /* Stop immediately if the arraysize refers to a multi-dimensional array: * (Note: 'x' is the dimension separator of the VOTable attribute 'arraysize') */ @@ -266,29 +267,29 @@ public final class VotType { /* NUMERIC TYPES */ case SHORT: case BOOLEAN: - return convertNumericType(TAPDatatype.SMALLINT); + return convertNumericType(DBDatatype.SMALLINT); case INT: - return convertNumericType(TAPDatatype.INTEGER); + return convertNumericType(DBDatatype.INTEGER); case LONG: - return convertNumericType(TAPDatatype.BIGINT); + return convertNumericType(DBDatatype.BIGINT); case FLOAT: - return convertNumericType(TAPDatatype.REAL); + return convertNumericType(DBDatatype.REAL); case DOUBLE: - return convertNumericType(TAPDatatype.DOUBLE); + return convertNumericType(DBDatatype.DOUBLE); /* BINARY TYPES */ case UNSIGNED_BYTE: // BLOB exception: if (xtype != null && xtype.equalsIgnoreCase(XTYPE_BLOB)) - return new TAPType(TAPDatatype.BLOB); + return new DBType(DBDatatype.BLOB); // Or else, just (var)binary: else - return convertVariableLengthType(TAPDatatype.VARBINARY, TAPDatatype.BINARY); + return convertVariableLengthType(DBDatatype.VARBINARY, DBDatatype.BINARY); /* CHARACTER TYPES */ case CHAR: @@ -296,47 +297,47 @@ public final class VotType { /* Special type cases: */ if (xtype != null){ if (xtype.equalsIgnoreCase(VotType.XTYPE_CLOB)) - return new TAPType(TAPDatatype.CLOB); + return new DBType(DBDatatype.CLOB); else if (xtype.equalsIgnoreCase(VotType.XTYPE_TIMESTAMP)) - return new TAPType(TAPDatatype.TIMESTAMP); + return new DBType(DBDatatype.TIMESTAMP); else if (xtype.equalsIgnoreCase(VotType.XTYPE_POINT)) - return new TAPType(TAPDatatype.POINT); + return new DBType(DBDatatype.POINT); else if (xtype.equalsIgnoreCase(VotType.XTYPE_REGION)) - return new TAPType(TAPDatatype.REGION); + return new DBType(DBDatatype.REGION); } // Or if not known or missing, just a (var)char: - return convertVariableLengthType(TAPDatatype.VARCHAR, TAPDatatype.CHAR); + return convertVariableLengthType(DBDatatype.VARCHAR, DBDatatype.CHAR); } } /** - * <p>Convert this numeric {@link VotType} object into a corresponding {@link TAPType} whose the datatype is provided in parameter.</p> + * <p>Convert this numeric {@link VotType} object into a corresponding {@link DBType} whose the datatype is provided in parameter.</p> * * <p> * Thus, just the arraysize must be managed here. If there is no arraysize or if equals to '1', the given datatype will be used. - * Otherwise, it is ignored and a {@link TAPType} with VARBINARY is returned. + * Otherwise, it is ignored and a {@link DBType} with VARBINARY is returned. * </p> * * @param tapDatatype TAP datatype corresponding to this {@link VotType} (only when arraysize != '*' and 'n'). * - * @return The corresponding {@link TAPType}. + * @return The corresponding {@link DBType}. */ - protected TAPType convertNumericType(final TAPDatatype tapDatatype){ + protected DBType convertNumericType(final DBDatatype tapDatatype){ // If no arraysize: if (arraysize == null || arraysize.equals("1")) - return new TAPType(tapDatatype); + return new DBType(tapDatatype); // If only one dimension: else - return new TAPType(TAPDatatype.VARBINARY); + return new DBType(DBDatatype.VARBINARY); /* Note: The test of multi-dimensional array should have been already done at the beginning of #toTAPType(). */ } /** * <p> - * Convert this variable length {@link VotType} (unsignedByte and char) object into a corresponding {@link TAPType} + * Convert this variable length {@link VotType} (unsignedByte and char) object into a corresponding {@link DBType} * whose the variable length and fixed length versions are given in parameters. * </p> * @@ -350,23 +351,23 @@ public final class VotType { * @param varType Variable length type (i.e. VARCHAR, VARBINARY). * @param fixedType Fixed length type (i.e. CHAR, BINARY). * - * @return The corresponding {@link TAPType}. + * @return The corresponding {@link DBType}. * * @throws TAPException If the arraysize is not valid (that's to say, different from the following syntaxes: NULL, '*', 'n' or 'n*' (where n is a positive and not-null integer)). */ - protected TAPType convertVariableLengthType(final TAPDatatype varType, final TAPDatatype fixedType) throws TAPException{ + protected DBType convertVariableLengthType(final DBDatatype varType, final DBDatatype fixedType) throws TAPException{ try{ // no arraysize or '*' => VARCHAR or VARBINARY if (arraysize == null || arraysize.equals("*")) - return new TAPType(varType); + return new DBType(varType); // 'n*' => VARCHAR(n) or VARBINARY(n) else if (arraysize.charAt(arraysize.length() - 1) == '*') - return new TAPType(varType, Integer.parseInt(arraysize.substring(0, arraysize.length() - 1))); + return new DBType(varType, Integer.parseInt(arraysize.substring(0, arraysize.length() - 1))); // 'n' => CHAR(n) or BINARY(n) else - return new TAPType(fixedType, Integer.parseInt(arraysize)); + return new DBType(fixedType, Integer.parseInt(arraysize)); }catch(NumberFormatException nfe){ throw new TAPException("failed conversion of a VOTable datatype: non-numeric arraysize (" + arraysize + ")!"); diff --git a/src/tap/parameters/TAPParameters.java b/src/tap/parameters/TAPParameters.java index 461c7ee024abb59fca941b3de91cc070f194b54c..6eb4f0936bc064396a551acdf551928e97f9f248 100644 --- a/src/tap/parameters/TAPParameters.java +++ b/src/tap/parameters/TAPParameters.java @@ -81,7 +81,7 @@ public class TAPParameters extends UWSParameters { // Multipart HTTP parameters: if (isMultipartContent(request)){ if (!service.uploadEnabled()) - throw new TAPException("Request error ! This TAP service has no Upload capability !", UWSException.BAD_REQUEST); + throw new TAPException("Request error! This TAP service has no Upload capability!", UWSException.BAD_REQUEST); File uploadDir = service.getFileManager().getUploadDirectory(); try{ @@ -97,14 +97,14 @@ public class TAPParameters extends UWSParameters { set(param, multipart.getParameter(param)); } }catch(IOException ioe){ - throw new TAPException("Error while reading the Multipart content !", ioe); + throw new TAPException("Error while reading the Multipart content!", ioe); }catch(IllegalArgumentException iae){ String confError = iae.getMessage(); if (service.getMaxUploadSize() <= 0) - confError = "The maximum upload size (see ServiceConnection.getMaxUploadSize() must be positive !"; + confError = "The maximum upload size (see ServiceConnection.getMaxUploadSize() must be positive!"; else if (uploadDir == null) - confError = "Missing upload directory (see TAPFileManager.getUploadDirectory()) !"; - throw new TAPException("Incorrect Upload capability configuration ! " + confError, iae); + confError = "Missing upload directory (see TAPFileManager.getUploadDirectory())!"; + throw new TAPException("Incorrect Upload capability configuration! " + confError, iae); } }// Classic HTTP parameters (GET or POST): diff --git a/src/tap/resource/TAP.java b/src/tap/resource/TAP.java index 00e8496d6547e24c377da95de8fd3fc81a848655..54724c86cb256439473e6e916468bbda58293d2a 100644 --- a/src/tap/resource/TAP.java +++ b/src/tap/resource/TAP.java @@ -50,6 +50,7 @@ import uws.service.UWSService; import uws.service.UWSUrl; import uws.service.error.ServiceErrorWriter; import uws.service.log.UWSLog.LogLevel; +import adql.db.FunctionDef; /** * <p>Root/Home of the TAP service. It is also the resource (HOME) which gathers all the others of the same TAP service.</p> @@ -57,7 +58,7 @@ import uws.service.log.UWSLog.LogLevel; * <p>At its creation it is creating and configuring the other resources in function of the given description of the TAP service.</p> * * @author Grégory Mantelet (CDS;ARI) - * @version 2.0 (09/2014) + * @version 2.0 (10/2014) */ public class TAP implements VOSIResource { @@ -113,8 +114,7 @@ public class TAP implements VOSIResource { resources.put(res.getName(), res); TAPMetadata metadata = service.getTAPMetadata(); - if (metadata != null) - resources.put(metadata.getName(), metadata); + resources.put(metadata.getName(), metadata); } /** @@ -422,6 +422,35 @@ public class TAP implements VOSIResource { xml.append("\t\t<name>ADQL</name>\n"); xml.append("\t\t<version ivo-id=\"ivo://ivoa.net/std/ADQL#v2.0\">2.0</version>\n"); xml.append("\t\t<description>ADQL 2.0</description>\n"); + + // Geometrical functions: + if (service.getGeometries() != null && service.getGeometries().size() > 0){ + xml.append("\t\t<languageFeatures type=\"ivo://ivoa.net/std/TAPRegExt#features-adqlgeo\">"); + for(String geom : service.getGeometries()){ + if (geom != null){ + xml.append("\t\t\t<feature>"); + xml.append("\t\t\t\t<form>").append(VOSerializer.formatText(geom.toUpperCase())).append("</form>"); + xml.append("\t\t\t</feature>"); + } + } + xml.append("\t\t</languageFeatures>"); + } + + // User Defined Functions (UDFs): + if (service.getUDFs() != null && service.getUDFs().size() > 0){ + xml.append("\t\t<languageFeatures type=\"ivo://ivoa.net/std/TAPRegExt#features-udf\">"); + for(FunctionDef udf : service.getUDFs()){ + if (udf != null){ + xml.append("\t\t\t<feature>"); + xml.append("\t\t\t\t<form>").append(VOSerializer.formatText(udf.toString())).append("</form>"); + if (udf.description != null && udf.description.length() > 0) + xml.append("\t\t\t\t<description>").append(VOSerializer.formatText(udf.description)).append("</description>"); + xml.append("\t\t\t</feature>"); + } + } + xml.append("\t\t</languageFeatures>"); + } + xml.append("\t</language>\n"); // Available output formats: diff --git a/src/uws/service/error/DefaultUWSErrorWriter.java b/src/uws/service/error/DefaultUWSErrorWriter.java index f9854a45268be0311ba30205dce08abc51e82a65..74366d32d4f489cfe085670c21559ca9e0a3a4ec 100644 --- a/src/uws/service/error/DefaultUWSErrorWriter.java +++ b/src/uws/service/error/DefaultUWSErrorWriter.java @@ -104,7 +104,7 @@ public class DefaultUWSErrorWriter implements ServiceErrorWriter { // log the error as GRAVE/FATAL (because unexpected/unmanaged): logger.logUWS(LogLevel.FATAL, null, null, "[REQUEST N°" + reqID + "] " + t.getMessage(), t); // write a message to the user: - writeError("INTERNAL SERVER ERROR! Sorry, this error is unexpected and no explaination can be provided for the moment. Details about this error have been reported in the service log files ; you should try again your request later or notify the administrator(s) by yourself (with the following 'Request ID').", ErrorType.FATAL, UWSException.INTERNAL_SERVER_ERROR, response, request, reqID, user, action); + writeError("INTERNAL SERVER ERROR! Sorry, this error is unexpected and no explanation can be provided for the moment. Details about this error have been reported in the service log files ; you should try again your request later or notify the administrator(s) by yourself (with the following 'Request ID').", ErrorType.FATAL, UWSException.INTERNAL_SERVER_ERROR, response, request, reqID, user, action); } } diff --git a/test/adql/SearchColumnListTest.java b/test/adql/SearchColumnListTest.java index b2e5988b240207115cf923cbef2f1ee1d738315b..d3f614fb650fd9833f836fa84f1976de3238e07f 100644 --- a/test/adql/SearchColumnListTest.java +++ b/test/adql/SearchColumnListTest.java @@ -9,12 +9,12 @@ import tap.metadata.TAPColumn; import tap.metadata.TAPSchema; import tap.metadata.TAPTable; import tap.metadata.TAPTable.TableType; -import tap.metadata.TAPType; -import tap.metadata.TAPType.TAPDatatype; import adql.db.DBColumn; import adql.db.DBCommonColumn; import adql.db.DBTable; +import adql.db.DBType; import adql.db.SearchColumnList; +import adql.db.DBType.DBDatatype; import adql.db.exception.UnresolvedJoin; import adql.parser.ParseException; import adql.query.IdentifierField; @@ -32,16 +32,16 @@ public class SearchColumnListTest { TAPTable tableD = new TAPTable("D", TableType.table, "NATURAL JOIN Test table", null); // Describe its columns: - tableA.addColumn(new TAPColumn("id", new TAPType(TAPDatatype.VARCHAR), "Object ID")); - tableA.addColumn(new TAPColumn("txta", new TAPType(TAPDatatype.VARCHAR), "Text of table A")); - tableB.addColumn(new TAPColumn("id", new TAPType(TAPDatatype.VARCHAR), "Object ID")); - tableB.addColumn(new TAPColumn("txtb", new TAPType(TAPDatatype.VARCHAR), "Text of table B")); - tableC.addColumn(new TAPColumn("Id", new TAPType(TAPDatatype.VARCHAR), "Object ID")); - tableC.addColumn(new TAPColumn("txta", new TAPType(TAPDatatype.VARCHAR), "Text of table A")); - tableC.addColumn(new TAPColumn("txtc", new TAPType(TAPDatatype.VARCHAR), "Text of table C")); - tableD.addColumn(new TAPColumn("id", new TAPType(TAPDatatype.VARCHAR), "Object ID")); - tableD.addColumn(new TAPColumn("txta", new TAPType(TAPDatatype.VARCHAR), "Text of table A")); - tableD.addColumn(new TAPColumn("txtd", new TAPType(TAPDatatype.VARCHAR), "Text of table D")); + tableA.addColumn(new TAPColumn("id", new DBType(DBDatatype.VARCHAR), "Object ID")); + tableA.addColumn(new TAPColumn("txta", new DBType(DBDatatype.VARCHAR), "Text of table A")); + tableB.addColumn(new TAPColumn("id", new DBType(DBDatatype.VARCHAR), "Object ID")); + tableB.addColumn(new TAPColumn("txtb", new DBType(DBDatatype.VARCHAR), "Text of table B")); + tableC.addColumn(new TAPColumn("Id", new DBType(DBDatatype.VARCHAR), "Object ID")); + tableC.addColumn(new TAPColumn("txta", new DBType(DBDatatype.VARCHAR), "Text of table A")); + tableC.addColumn(new TAPColumn("txtc", new DBType(DBDatatype.VARCHAR), "Text of table C")); + tableD.addColumn(new TAPColumn("id", new DBType(DBDatatype.VARCHAR), "Object ID")); + tableD.addColumn(new TAPColumn("txta", new DBType(DBDatatype.VARCHAR), "Text of table A")); + tableD.addColumn(new TAPColumn("txtd", new DBType(DBDatatype.VARCHAR), "Text of table D")); // List all available tables: TAPSchema schema = new TAPSchema("public"); diff --git a/test/adql/db/TestDBChecker.java b/test/adql/db/TestDBChecker.java new file mode 100644 index 0000000000000000000000000000000000000000..c8e8b4b43dd1440f9371b6ae575837b560549084 --- /dev/null +++ b/test/adql/db/TestDBChecker.java @@ -0,0 +1,609 @@ +package adql.db; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import adql.db.DBType.DBDatatype; +import adql.db.FunctionDef.FunctionParam; +import adql.db.exception.UnresolvedIdentifiersException; +import adql.parser.ADQLParser; +import adql.parser.ParseException; +import adql.query.ADQLQuery; +import adql.query.operand.ADQLColumn; +import adql.query.operand.ADQLOperand; +import adql.query.operand.function.DefaultUDF; + +public class TestDBChecker { + + private static List<DBTable> tables; + + @BeforeClass + public static void setUpBeforeClass() throws Exception{ + tables = new ArrayList<DBTable>(); + + DefaultDBTable fooTable = new DefaultDBTable("foo"); + DBColumn col = new DefaultDBColumn("colS", new DBType(DBDatatype.VARCHAR), fooTable); + fooTable.addColumn(col); + col = new DefaultDBColumn("colI", new DBType(DBDatatype.INTEGER), fooTable); + fooTable.addColumn(col); + col = new DefaultDBColumn("colG", new DBType(DBDatatype.POINT), fooTable); + fooTable.addColumn(col); + + tables.add(fooTable); + } + + @AfterClass + public static void tearDownAfterClass() throws Exception{} + + @Before + public void setUp() throws Exception{} + + @After + public void tearDown() throws Exception{} + + @Test + public void testNumericOrStringValueExpressionPrimary(){ + ADQLParser parser = new ADQLParser(); + try{ + assertNotNull(parser.parseQuery("SELECT 'toto' FROM foo;")); + assertNotNull(parser.parseQuery("SELECT ('toto') FROM foo;")); + assertNotNull(parser.parseQuery("SELECT (('toto')) FROM foo;")); + assertNotNull(parser.parseQuery("SELECT 'toto' || 'blabla' FROM foo;")); + assertNotNull(parser.parseQuery("SELECT ('toto' || 'blabla') FROM foo;")); + assertNotNull(parser.parseQuery("SELECT (('toto' || 'blabla')) FROM foo;")); + assertNotNull(parser.parseQuery("SELECT (('toto') || (('blabla'))) FROM foo;")); + assertNotNull(parser.parseQuery("SELECT 3 FROM foo;")); + assertNotNull(parser.parseQuery("SELECT ((2+3)*5) FROM foo;")); + assertNotNull(parser.parseQuery("SELECT ABS(-123) FROM foo;")); + assertNotNull(parser.parseQuery("SELECT ABS(2*-1+5) FROM foo;")); + assertNotNull(parser.parseQuery("SELECT ABS(COUNT(*)) FROM foo;")); + assertNotNull(parser.parseQuery("SELECT toto FROM foo;")); + assertNotNull(parser.parseQuery("SELECT toto * 3 FROM foo;")); + assertNotNull(parser.parseQuery("SELECT toto || 'blabla' FROM foo;")); + }catch(ParseException pe){ + pe.printStackTrace(); + fail(); + } + try{ + parser.parseQuery("SELECT ABS('toto') FROM foo;"); + fail(); + }catch(ParseException pe){} + try{ + parser.parseQuery("SELECT ABS(('toto' || 'blabla')) FROM foo;"); + fail(); + }catch(ParseException pe){} + try{ + parser.parseQuery("SELECT 'toto' || 1 FROM foo;"); + fail(); + }catch(ParseException pe){} + try{ + parser.parseQuery("SELECT 1 || 'toto' FROM foo;"); + fail(); + }catch(ParseException pe){} + try{ + parser.parseQuery("SELECT 'toto' * 3 FROM foo;"); + fail(); + }catch(ParseException pe){} + } + + @Test + public void testUDFManagement(){ + // UNKNOWN FUNCTIONS ARE NOT ALLOWED: + ADQLParser parser = new ADQLParser(new DBChecker(tables, new ArrayList<FunctionDef>(0))); + + // Test with a simple ADQL query without unknown or user defined function: + try{ + assertNotNull(parser.parseQuery("SELECT * FROM foo;")); + }catch(ParseException e){ + e.printStackTrace(); + fail("A simple and basic query should not be a problem for the parser!"); + } + + // Test with an ADQL query containing one not declared UDF: + try{ + parser.parseQuery("SELECT toto() FROM foo;"); + fail("This query contains a UDF while it's not allowed: this test should have failed!"); + }catch(ParseException e){ + assertTrue(e instanceof UnresolvedIdentifiersException); + UnresolvedIdentifiersException ex = (UnresolvedIdentifiersException)e; + assertEquals(1, ex.getNbErrors()); + assertEquals("Unresolved function: \"toto()\"! No UDF has been defined or found with the signature: toto().", ex.getErrors().next().getMessage()); + } + + // DECLARE THE UDFs: + FunctionDef[] udfs = new FunctionDef[]{new FunctionDef("toto", new DBType(DBDatatype.VARCHAR)),new FunctionDef("tata", new DBType(DBDatatype.INTEGER))}; + parser = new ADQLParser(new DBChecker(tables, Arrays.asList(udfs))); + + // Test again: + try{ + assertNotNull(parser.parseQuery("SELECT toto() FROM foo;")); + assertNotNull(parser.parseQuery("SELECT tata() FROM foo;")); + }catch(ParseException e){ + e.printStackTrace(); + fail("This query contains a DECLARED UDF: this test should have succeeded!"); + } + + // Test but with at least one parameter: + try{ + parser.parseQuery("SELECT toto('blabla') FROM foo;"); + fail("This query contains an unknown UDF signature (the fct toto is declared with no parameter): this test should have failed!"); + }catch(ParseException e){ + assertTrue(e instanceof UnresolvedIdentifiersException); + UnresolvedIdentifiersException ex = (UnresolvedIdentifiersException)e; + assertEquals(1, ex.getNbErrors()); + assertEquals("Unresolved function: \"toto('blabla')\"! No UDF has been defined or found with the signature: toto(STRING).", ex.getErrors().next().getMessage()); + } + } + + @Test + public void testGeometry(){ + // DECLARE A SIMPLE PARSER where all geometries are allowed by default: + ADQLParser parser = new ADQLParser(new DBChecker(tables)); + + // Test with several geometries while all are allowed: + try{ + assertNotNull(parser.parseQuery("SELECT * FROM foo WHERE CONTAINS(POINT('', 12.3, 45.6), CIRCLE('', 1.2, 2.3, 5)) = 1;")); + }catch(ParseException pe){ + pe.printStackTrace(); + fail("This query contains several geometries, and all are theoretically allowed: this test should have succeeded!"); + } + + // Test with several geometries while only the allowed ones: + try{ + parser = new ADQLParser(new DBChecker(tables, new ArrayList<FunctionDef>(0), Arrays.asList(new String[]{"CONTAINS","POINT","CIRCLE"}), null)); + assertNotNull(parser.parseQuery("SELECT * FROM foo WHERE CONTAINS(POINT('', 12.3, 45.6), CIRCLE('', 1.2, 2.3, 5)) = 1;")); + }catch(ParseException pe){ + pe.printStackTrace(); + fail("This query contains several geometries, and all are theoretically allowed: this test should have succeeded!"); + } + try{ + parser.parseQuery("SELECT * FROM foo WHERE INTERSECTS(POINT('', 12.3, 45.6), CIRCLE('', 1.2, 2.3, 5)) = 1;"); + fail("This query contains a not-allowed geometry function (INTERSECTS): this test should have failed!"); + }catch(ParseException pe){ + assertTrue(pe instanceof UnresolvedIdentifiersException); + UnresolvedIdentifiersException ex = (UnresolvedIdentifiersException)pe; + assertEquals(1, ex.getNbErrors()); + assertEquals("The geometrical function \"INTERSECTS\" is not available in this implementation!", ex.getErrors().next().getMessage()); + } + + // Test by adding REGION: + try{ + parser = new ADQLParser(new DBChecker(tables, new ArrayList<FunctionDef>(0), Arrays.asList(new String[]{"CONTAINS","POINT","CIRCLE","REGION"}), null)); + assertNotNull(parser.parseQuery("SELECT * FROM foo WHERE CONTAINS(REGION('Position 12.3 45.6'), REGION('circle 1.2 2.3 5')) = 1;")); + }catch(ParseException pe){ + pe.printStackTrace(); + fail("This query contains several geometries, and all are theoretically allowed: this test should have succeeded!"); + } + try{ + parser.parseQuery("SELECT * FROM foo WHERE CONTAINS(REGION('Position 12.3 45.6'), REGION('BOX 1.2 2.3 5 9')) = 1;"); + fail("This query contains a not-allowed geometry function (BOX): this test should have failed!"); + }catch(ParseException pe){ + assertTrue(pe instanceof UnresolvedIdentifiersException); + UnresolvedIdentifiersException ex = (UnresolvedIdentifiersException)pe; + assertEquals(1, ex.getNbErrors()); + assertEquals("The geometrical function \"BOX\" is not available in this implementation!", ex.getErrors().next().getMessage()); + } + + // Test with several geometries while none geometry is allowed: + try{ + parser = new ADQLParser(new DBChecker(tables, new ArrayList<FunctionDef>(0), new ArrayList<String>(0), null)); + parser.parseQuery("SELECT * FROM foo WHERE CONTAINS(POINT('', 12.3, 45.6), CIRCLE('', 1.2, 2.3, 5)) = 1;"); + fail("This query contains geometries while they are all forbidden: this test should have failed!"); + }catch(ParseException pe){ + assertTrue(pe instanceof UnresolvedIdentifiersException); + UnresolvedIdentifiersException ex = (UnresolvedIdentifiersException)pe; + assertEquals(3, ex.getNbErrors()); + Iterator<ParseException> itErrors = ex.getErrors(); + assertEquals("The geometrical function \"CONTAINS\" is not available in this implementation!", itErrors.next().getMessage()); + assertEquals("The geometrical function \"POINT\" is not available in this implementation!", itErrors.next().getMessage()); + assertEquals("The geometrical function \"CIRCLE\" is not available in this implementation!", itErrors.next().getMessage()); + } + } + + @Test + public void testCoordSys(){ + // DECLARE A SIMPLE PARSER where all coordinate systems are allowed by default: + ADQLParser parser = new ADQLParser(new DBChecker(tables)); + + // Test with several coordinate systems while all are allowed: + try{ + assertNotNull(parser.parseQuery("SELECT * FROM foo WHERE CONTAINS(POINT('', 12.3, 45.6), CIRCLE('', 1.2, 2.3, 5)) = 1;")); + assertNotNull(parser.parseQuery("SELECT * FROM foo WHERE CONTAINS(POINT('icrs', 12.3, 45.6), CIRCLE('cartesian2', 1.2, 2.3, 5)) = 1;")); + assertNotNull(parser.parseQuery("SELECT * FROM foo WHERE CONTAINS(POINT('lsr', 12.3, 45.6), CIRCLE('galactic heliocenter', 1.2, 2.3, 5)) = 1;")); + assertNotNull(parser.parseQuery("SELECT * FROM foo WHERE CONTAINS(POINT('unknownframe', 12.3, 45.6), CIRCLE('galactic unknownrefpos spherical2', 1.2, 2.3, 5)) = 1;")); + assertNotNull(parser.parseQuery("SELECT * FROM foo WHERE CONTAINS(REGION('position icrs lsr 12.3 45.6'), REGION('circle fk5 1.2 2.3 5')) = 1;")); + assertNotNull(parser.parseQuery("SELECT Region('not(position 1 2)') FROM foo;")); + }catch(ParseException pe){ + pe.printStackTrace(); + fail("This query contains several valid coordinate systems, and all are theoretically allowed: this test should have succeeded!"); + } + + // Concatenation as coordinate systems not checked: + try{ + assertNotNull(parser.parseQuery("SELECT * FROM foo WHERE CONTAINS(POINT('From ' || 'here', 12.3, 45.6), CIRCLE('', 1.2, 2.3, 5)) = 1;")); + }catch(ParseException pe){ + pe.printStackTrace(); + fail("This query contains a concatenation as coordinate systems (but only string constants are checked): this test should have succeeded!"); + } + + // Test with several coordinate systems while only some allowed: + try{ + parser = new ADQLParser(new DBChecker(tables, new ArrayList<FunctionDef>(0), null, Arrays.asList(new String[]{"icrs * *","fk4 geocenter *","galactic * spherical2"}))); + assertNotNull(parser.parseQuery("SELECT * FROM foo WHERE CONTAINS(POINT('', 12.3, 45.6), CIRCLE('', 1.2, 2.3, 5)) = 1;")); + assertNotNull(parser.parseQuery("SELECT * FROM foo WHERE CONTAINS(POINT('icrs', 12.3, 45.6), CIRCLE('cartesian3', 1.2, 2.3, 5)) = 1;")); + assertNotNull(parser.parseQuery("SELECT POINT('fk4', 12.3, 45.6) FROM foo;")); + assertNotNull(parser.parseQuery("SELECT * FROM foo WHERE CONTAINS(POINT('fk4 geocenter', 12.3, 45.6), CIRCLE('cartesian2', 1.2, 2.3, 5)) = 1;")); + assertNotNull(parser.parseQuery("SELECT * FROM foo WHERE CONTAINS(POINT('galactic', 12.3, 45.6), CIRCLE('galactic spherical2', 1.2, 2.3, 5)) = 1;")); + assertNotNull(parser.parseQuery("SELECT * FROM foo WHERE CONTAINS(POINT('galactic geocenter', 12.3, 45.6), CIRCLE('galactic lsr spherical2', 1.2, 2.3, 5)) = 1;")); + assertNotNull(parser.parseQuery("SELECT * FROM foo WHERE CONTAINS(REGION('position galactic lsr 12.3 45.6'), REGION('circle icrs 1.2 2.3 5')) = 1;")); + assertNotNull(parser.parseQuery("SELECT Region('not(position 1 2)') FROM foo;")); + }catch(ParseException pe){ + pe.printStackTrace(); + fail("This query contains several valid coordinate systems, and all are theoretically allowed: this test should have succeeded!"); + } + try{ + parser.parseQuery("SELECT POINT('fk5 geocenter', 12.3, 45.6) FROM foo;"); + fail("This query contains a not-allowed coordinate system ('fk5' is not allowed): this test should have failed!"); + }catch(ParseException pe){ + assertTrue(pe instanceof UnresolvedIdentifiersException); + UnresolvedIdentifiersException ex = (UnresolvedIdentifiersException)pe; + assertEquals(1, ex.getNbErrors()); + assertEquals("Coordinate system \"fk5 geocenter\" (= \"FK5 GEOCENTER SPHERICAL2\") not allowed in this implementation.", ex.getErrors().next().getMessage()); + } + try{ + parser.parseQuery("SELECT Region('not(position fk5 heliocenter 1 2)') FROM foo;"); + fail("This query contains a not-allowed coordinate system ('fk5' is not allowed): this test should have failed!"); + }catch(ParseException pe){ + assertTrue(pe instanceof UnresolvedIdentifiersException); + UnresolvedIdentifiersException ex = (UnresolvedIdentifiersException)pe; + assertEquals(1, ex.getNbErrors()); + assertEquals("Coordinate system \"FK5 HELIOCENTER\" (= \"FK5 HELIOCENTER SPHERICAL2\") not allowed in this implementation.", ex.getErrors().next().getMessage()); + } + + // Test with a coordinate system while none is allowed: + try{ + parser = new ADQLParser(new DBChecker(tables, new ArrayList<FunctionDef>(0), null, new ArrayList<String>(0))); + assertNotNull(parser.parseQuery("SELECT * FROM foo WHERE CONTAINS(POINT('', 12.3, 45.6), CIRCLE('', 1.2, 2.3, 5)) = 1;")); + assertNotNull(parser.parseQuery("SELECT * FROM foo WHERE CONTAINS(REGION('position 12.3 45.6'), REGION('circle 1.2 2.3 5')) = 1;")); + assertNotNull(parser.parseQuery("SELECT Region('not(position 1 2)') FROM foo;")); + }catch(ParseException pe){ + pe.printStackTrace(); + fail("This query specifies none coordinate system: this test should have succeeded!"); + } + try{ + parser.parseQuery("SELECT * FROM foo WHERE CONTAINS(POINT('ICRS SPHERICAL2', 12.3, 45.6), CIRCLE('icrs', 1.2, 2.3, 5)) = 1;"); + fail("This query specifies coordinate systems while they are all forbidden: this test should have failed!"); + }catch(ParseException pe){ + assertTrue(pe instanceof UnresolvedIdentifiersException); + UnresolvedIdentifiersException ex = (UnresolvedIdentifiersException)pe; + assertEquals(2, ex.getNbErrors()); + Iterator<ParseException> itErrors = ex.getErrors(); + assertEquals("Coordinate system \"ICRS SPHERICAL2\" (= \"ICRS UNKNOWNREFPOS SPHERICAL2\") not allowed in this implementation.", itErrors.next().getMessage()); + assertEquals("Coordinate system \"icrs\" (= \"ICRS UNKNOWNREFPOS SPHERICAL2\") not allowed in this implementation.", itErrors.next().getMessage()); + } + try{ + parser.parseQuery("SELECT Region('not(position fk4 1 2)') FROM foo;"); + fail("This query specifies coordinate systems while they are all forbidden: this test should have failed!"); + }catch(ParseException pe){ + assertTrue(pe instanceof UnresolvedIdentifiersException); + UnresolvedIdentifiersException ex = (UnresolvedIdentifiersException)pe; + assertEquals(1, ex.getNbErrors()); + assertEquals("Coordinate system \"FK4\" (= \"FK4 UNKNOWNREFPOS SPHERICAL2\") not allowed in this implementation.", ex.getErrors().next().getMessage()); + } + } + + @Test + public void testTypesChecking(){ + // DECLARE A SIMPLE PARSER: + ADQLParser parser = new ADQLParser(new DBChecker(tables)); + + // Test the type of columns generated by the parser: + try{ + ADQLQuery query = parser.parseQuery("SELECT colS, colI, colG FROM foo;"); + ADQLOperand colS = query.getSelect().get(0).getOperand(); + ADQLOperand colI = query.getSelect().get(1).getOperand(); + ADQLOperand colG = query.getSelect().get(2).getOperand(); + // test string column: + assertTrue(colS instanceof ADQLColumn); + assertTrue(colS.isString()); + assertFalse(colS.isNumeric()); + assertFalse(colS.isGeometry()); + // test integer column: + assertTrue(colI instanceof ADQLColumn); + assertFalse(colI.isString()); + assertTrue(colI.isNumeric()); + assertFalse(colI.isGeometry()); + // test geometry column: + assertTrue(colG instanceof ADQLColumn); + assertFalse(colG.isString()); + assertFalse(colG.isNumeric()); + assertTrue(colG.isGeometry()); + }catch(ParseException e1){ + if (e1 instanceof UnresolvedIdentifiersException) + ((UnresolvedIdentifiersException)e1).getErrors().next().printStackTrace(); + else + e1.printStackTrace(); + fail("This query contains known columns: this test should have succeeded!"); + } + + // Test the expected type - NUMERIC - generated by the parser: + try{ + assertNotNull(parser.parseQuery("SELECT colI * 3 FROM foo;")); + }catch(ParseException e){ + e.printStackTrace(); + fail("This query contains a product between 2 numerics: this test should have succeeded!"); + } + try{ + parser.parseQuery("SELECT colS * 3 FROM foo;"); + fail("This query contains a product between a string and an integer: this test should have failed!"); + }catch(ParseException e){ + assertTrue(e instanceof UnresolvedIdentifiersException); + UnresolvedIdentifiersException ex = (UnresolvedIdentifiersException)e; + assertEquals(1, ex.getNbErrors()); + assertEquals("Type mismatch! A numeric value was expected instead of \"colS\".", ex.getErrors().next().getMessage()); + } + try{ + parser.parseQuery("SELECT colG * 3 FROM foo;"); + fail("This query contains a product between a geometry and an integer: this test should have failed!"); + }catch(ParseException e){ + assertTrue(e instanceof UnresolvedIdentifiersException); + UnresolvedIdentifiersException ex = (UnresolvedIdentifiersException)e; + assertEquals(1, ex.getNbErrors()); + assertEquals("Type mismatch! A numeric value was expected instead of \"colG\".", ex.getErrors().next().getMessage()); + } + + // Test the expected type - STRING - generated by the parser: + try{ + assertNotNull(parser.parseQuery("SELECT colS || 'blabla' FROM foo;")); + }catch(ParseException e){ + e.printStackTrace(); + fail("This query contains a concatenation between 2 strings: this test should have succeeded!"); + } + try{ + parser.parseQuery("SELECT colI || 'blabla' FROM foo;"); + fail("This query contains a concatenation between an integer and a string: this test should have failed!"); + }catch(ParseException e){ + assertTrue(e instanceof UnresolvedIdentifiersException); + UnresolvedIdentifiersException ex = (UnresolvedIdentifiersException)e; + assertEquals(1, ex.getNbErrors()); + assertEquals("Type mismatch! A string value was expected instead of \"colI\".", ex.getErrors().next().getMessage()); + } + try{ + parser.parseQuery("SELECT colG || 'blabla' FROM foo;"); + fail("This query contains a concatenation between a geometry and a string: this test should have failed!"); + }catch(ParseException e){ + assertTrue(e instanceof UnresolvedIdentifiersException); + UnresolvedIdentifiersException ex = (UnresolvedIdentifiersException)e; + assertEquals(1, ex.getNbErrors()); + assertEquals("Type mismatch! A string value was expected instead of \"colG\".", ex.getErrors().next().getMessage()); + } + + // Test the expected type - GEOMETRY - generated by the parser: + try{ + assertNotNull(parser.parseQuery("SELECT CONTAINS(colG, CIRCLE('', 1, 2, 5)) FROM foo;")); + }catch(ParseException e){ + e.printStackTrace(); + fail("This query contains a geometrical predicate between 2 geometries: this test should have succeeded!"); + } + try{ + parser.parseQuery("SELECT CONTAINS(colI, CIRCLE('', 1, 2, 5)) FROM foo;"); + fail("This query contains a geometrical predicate between an integer and a geometry: this test should have failed!"); + }catch(ParseException e){ + assertTrue(e instanceof UnresolvedIdentifiersException); + UnresolvedIdentifiersException ex = (UnresolvedIdentifiersException)e; + assertEquals(1, ex.getNbErrors()); + assertEquals("Type mismatch! A geometry was expected instead of \"colI\".", ex.getErrors().next().getMessage()); + } + try{ + parser.parseQuery("SELECT CONTAINS(colS, CIRCLE('', 1, 2, 5)) FROM foo;"); + fail("This query contains a geometrical predicate between a string and a geometry: this test should have failed!"); + }catch(ParseException e){ + assertTrue(e instanceof UnresolvedIdentifiersException); + UnresolvedIdentifiersException ex = (UnresolvedIdentifiersException)e; + assertEquals(1, ex.getNbErrors()); + assertEquals("Type mismatch! A geometry was expected instead of \"colS\".", ex.getErrors().next().getMessage()); + } + + // DECLARE SOME UDFs: + FunctionDef[] udfs = new FunctionDef[]{new FunctionDef("toto", new DBType(DBDatatype.VARCHAR)),new FunctionDef("tata", new DBType(DBDatatype.INTEGER)),new FunctionDef("titi", new DBType(DBDatatype.REGION))}; + parser = new ADQLParser(new DBChecker(tables, Arrays.asList(udfs))); + + // Test the return type of the function TOTO generated by the parser: + try{ + ADQLQuery query = parser.parseQuery("SELECT toto() FROM foo;"); + ADQLOperand fct = query.getSelect().get(0).getOperand(); + assertTrue(fct instanceof DefaultUDF); + assertNotNull(((DefaultUDF)fct).getDefinition()); + assertTrue(fct.isString()); + assertFalse(fct.isNumeric()); + assertFalse(fct.isGeometry()); + }catch(ParseException e1){ + e1.printStackTrace(); + fail("This query contains a DECLARED UDF: this test should have succeeded!"); + } + + // Test the return type checking inside a whole query: + try{ + assertNotNull(parser.parseQuery("SELECT toto() || 'Blabla ' AS \"SuperText\" FROM foo;")); + }catch(ParseException e1){ + e1.printStackTrace(); + fail("This query contains a DECLARED UDF concatenated to a String: this test should have succeeded!"); + } + try{ + parser.parseQuery("SELECT toto()*3 AS \"SuperError\" FROM foo;"); + fail("This query contains a DECLARED UDF BUT used as numeric...which is here not possible: this test should have failed!"); + }catch(ParseException e1){ + assertTrue(e1 instanceof UnresolvedIdentifiersException); + UnresolvedIdentifiersException ex = (UnresolvedIdentifiersException)e1; + assertEquals(1, ex.getNbErrors()); + assertEquals("Type mismatch! A numeric value was expected instead of \"toto()\".", ex.getErrors().next().getMessage()); + } + + // Test the return type of the function TATA generated by the parser: + try{ + ADQLQuery query = parser.parseQuery("SELECT tata() FROM foo;"); + ADQLOperand fct = query.getSelect().get(0).getOperand(); + assertTrue(fct instanceof DefaultUDF); + assertNotNull(((DefaultUDF)fct).getDefinition()); + assertFalse(fct.isString()); + assertTrue(fct.isNumeric()); + assertFalse(fct.isGeometry()); + }catch(ParseException e1){ + e1.printStackTrace(); + fail("This query contains a DECLARED UDF: this test should have succeeded!"); + } + + // Test the return type checking inside a whole query: + try{ + assertNotNull(parser.parseQuery("SELECT tata()*3 AS \"aNumeric\" FROM foo;")); + }catch(ParseException e1){ + e1.printStackTrace(); + fail("This query contains a DECLARED UDF multiplicated by 3: this test should have succeeded!"); + } + try{ + parser.parseQuery("SELECT 'Blabla ' || tata() AS \"SuperError\" FROM foo;"); + fail("This query contains a DECLARED UDF BUT used as string...which is here not possible: this test should have failed!"); + }catch(ParseException e1){ + assertTrue(e1 instanceof UnresolvedIdentifiersException); + UnresolvedIdentifiersException ex = (UnresolvedIdentifiersException)e1; + assertEquals(1, ex.getNbErrors()); + assertEquals("Type mismatch! A string value was expected instead of \"tata()\".", ex.getErrors().next().getMessage()); + } + try{ + parser.parseQuery("SELECT tata() || 'Blabla ' AS \"SuperError\" FROM foo;"); + fail("This query contains a DECLARED UDF BUT used as string...which is here not possible: this test should have failed!"); + }catch(ParseException e1){ + assertTrue(e1 instanceof UnresolvedIdentifiersException); + UnresolvedIdentifiersException ex = (UnresolvedIdentifiersException)e1; + assertEquals(1, ex.getNbErrors()); + assertEquals("Type mismatch! A string value was expected instead of \"tata()\".", ex.getErrors().next().getMessage()); + } + + // Test the return type of the function TITI generated by the parser: + try{ + ADQLQuery query = parser.parseQuery("SELECT titi() FROM foo;"); + ADQLOperand fct = query.getSelect().get(0).getOperand(); + assertTrue(fct instanceof DefaultUDF); + assertNotNull(((DefaultUDF)fct).getDefinition()); + assertFalse(fct.isString()); + assertFalse(fct.isNumeric()); + assertTrue(fct.isGeometry()); + }catch(ParseException e1){ + e1.printStackTrace(); + fail("This query contains a DECLARED UDF: this test should have succeeded!"); + } + + // Test the return type checking inside a whole query: + try{ + parser.parseQuery("SELECT CONTAINS(colG, titi()) ' AS \"Super\" FROM foo;"); + fail("Geometrical UDFs are not allowed for the moment in the ADQL language: this test should have failed!"); + }catch(ParseException e1){ + assertTrue(e1 instanceof ParseException); + assertEquals(" Encountered \"(\". Was expecting one of: \")\" \".\" \".\" \")\" ", e1.getMessage()); + } + try{ + parser.parseQuery("SELECT titi()*3 AS \"SuperError\" FROM foo;"); + fail("This query contains a DECLARED UDF BUT used as numeric...which is here not possible: this test should have failed!"); + }catch(ParseException e1){ + assertTrue(e1 instanceof UnresolvedIdentifiersException); + UnresolvedIdentifiersException ex = (UnresolvedIdentifiersException)e1; + assertEquals(1, ex.getNbErrors()); + assertEquals("Type mismatch! A numeric value was expected instead of \"titi()\".", ex.getErrors().next().getMessage()); + } + + // CLEAR ALL UDFs AND ALLOW UNKNOWN FUNCTION: + parser = new ADQLParser(new DBChecker(tables, null)); + + // Test again: + try{ + assertNotNull(parser.parseQuery("SELECT toto() FROM foo;")); + }catch(ParseException e){ + e.printStackTrace(); + fail("The parser allow ANY unknown function: this test should have succeeded!"); + } + + // Test the return type of the function generated by the parser: + try{ + ADQLQuery query = parser.parseQuery("SELECT toto() FROM foo;"); + ADQLOperand fct = query.getSelect().get(0).getOperand(); + assertTrue(fct instanceof DefaultUDF); + assertNull(((DefaultUDF)fct).getDefinition()); + assertTrue(fct.isString()); + assertTrue(fct.isNumeric()); + }catch(ParseException e1){ + e1.printStackTrace(); + fail("The parser allow ANY unknown function: this test should have succeeded!"); + } + + // DECLARE THE UDF (while unknown functions are allowed): + parser = new ADQLParser(new DBChecker(tables, Arrays.asList(new FunctionDef[]{new FunctionDef("toto", new DBType(DBDatatype.VARCHAR))}))); + + // Test the return type of the function generated by the parser: + try{ + ADQLQuery query = parser.parseQuery("SELECT toto() FROM foo;"); + ADQLOperand fct = query.getSelect().get(0).getOperand(); + assertTrue(fct instanceof DefaultUDF); + assertNotNull(((DefaultUDF)fct).getDefinition()); + assertTrue(fct.isString()); + assertFalse(fct.isNumeric()); + }catch(ParseException e1){ + e1.printStackTrace(); + fail("The parser allow ANY unknown function: this test should have succeeded!"); + } + + // DECLARE UDFs WITH SAME NAMES BUT DIFFERENT TYPE OF ARGUMENT: + udfs = new FunctionDef[]{new FunctionDef("toto", new DBType(DBDatatype.VARCHAR), new FunctionParam[]{new FunctionParam("attr", new DBType(DBDatatype.VARCHAR))}),new FunctionDef("toto", new DBType(DBDatatype.INTEGER), new FunctionParam[]{new FunctionParam("attr", new DBType(DBDatatype.INTEGER))}),new FunctionDef("toto", new DBType(DBDatatype.INTEGER), new FunctionParam[]{new FunctionParam("attr", new DBType(DBDatatype.POINT))})}; + parser = new ADQLParser(new DBChecker(tables, Arrays.asList(udfs))); + + // Test the return type in function of the parameter: + try{ + assertNotNull(parser.parseQuery("SELECT toto('blabla') AS toto1, toto(123) AS toto2, toto(POINT('', 1, 2)) AS toto3 FROM foo;")); + }catch(ParseException e1){ + e1.printStackTrace(); + fail("This query contains two DECLARED UDFs used here: this test should have succeeded!"); + } + try{ + parser.parseQuery("SELECT toto('blabla') * 123 AS \"SuperError\" FROM foo;"); + fail("This query contains a DECLARED UDF BUT used as numeric...which is here not possible: this test should have failed!"); + }catch(ParseException e){ + assertTrue(e instanceof UnresolvedIdentifiersException); + UnresolvedIdentifiersException ex = (UnresolvedIdentifiersException)e; + assertEquals(1, ex.getNbErrors()); + assertEquals("Type mismatch! A numeric value was expected instead of \"toto('blabla')\".", ex.getErrors().next().getMessage()); + } + try{ + parser.parseQuery("SELECT toto(123) || 'blabla' AS \"SuperError\" FROM foo;"); + fail("This query contains a DECLARED UDF BUT used as string...which is here not possible: this test should have failed!"); + }catch(ParseException e){ + assertTrue(e instanceof UnresolvedIdentifiersException); + UnresolvedIdentifiersException ex = (UnresolvedIdentifiersException)e; + assertEquals(1, ex.getNbErrors()); + assertEquals("Type mismatch! A string value was expected instead of \"toto(123)\".", ex.getErrors().next().getMessage()); + } + try{ + parser.parseQuery("SELECT toto(POINT('', 1, 2)) || 'blabla' AS \"SuperError\" FROM foo;"); + fail("This query contains a DECLARED UDF BUT used as string...which is here not possible: this test should have failed!"); + }catch(ParseException e){ + assertTrue(e instanceof UnresolvedIdentifiersException); + UnresolvedIdentifiersException ex = (UnresolvedIdentifiersException)e; + assertEquals(1, ex.getNbErrors()); + assertEquals("Type mismatch! A string value was expected instead of \"toto(POINT('', 1, 2))\".", ex.getErrors().next().getMessage()); + } + } + +} diff --git a/test/adql/db/TestFunctionDef.java b/test/adql/db/TestFunctionDef.java new file mode 100644 index 0000000000000000000000000000000000000000..c3d738a07aa0185136ab5199b98c915ec51ae1ed --- /dev/null +++ b/test/adql/db/TestFunctionDef.java @@ -0,0 +1,312 @@ +package adql.db; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import org.junit.Test; + +import adql.db.DBType.DBDatatype; +import adql.db.FunctionDef.FunctionParam; +import adql.parser.ParseException; +import adql.query.operand.ADQLOperand; +import adql.query.operand.NumericConstant; +import adql.query.operand.StringConstant; +import adql.query.operand.function.ADQLFunction; +import adql.query.operand.function.DefaultUDF; +import adql.query.operand.function.geometry.PointFunction; + +public class TestFunctionDef { + + @Test + public void testIsString(){ + for(DBDatatype type : DBDatatype.values()){ + switch(type){ + case CHAR: + case VARCHAR: + case TIMESTAMP: + case CLOB: + assertTrue(new FunctionDef("foo", new DBType(type)).isString); + break; + default: + assertFalse(new FunctionDef("foo", new DBType(type)).isString); + } + } + } + + @Test + public void testIsGeometry(){ + for(DBDatatype type : DBDatatype.values()){ + switch(type){ + case POINT: + case REGION: + assertTrue(new FunctionDef("foo", new DBType(type)).isGeometry); + break; + default: + assertFalse(new FunctionDef("foo", new DBType(type)).isGeometry); + } + } + } + + @Test + public void testIsNumeric(){ + for(DBDatatype type : DBDatatype.values()){ + switch(type){ + case CHAR: + case VARCHAR: + case TIMESTAMP: + case POINT: + case REGION: + case CLOB: + assertFalse(new FunctionDef("foo", new DBType(type)).isNumeric); + break; + default: + assertTrue(new FunctionDef("foo", new DBType(type)).isNumeric); + } + } + } + + @Test + public void testToString(){ + assertEquals("fct1()", new FunctionDef("fct1").toString()); + assertEquals("fct1() -> VARCHAR", new FunctionDef("fct1", new DBType(DBDatatype.VARCHAR)).toString()); + assertEquals("fct1(foo DOUBLE) -> VARCHAR", new FunctionDef("fct1", new DBType(DBDatatype.VARCHAR), new FunctionParam[]{new FunctionParam("foo", new DBType(DBDatatype.DOUBLE))}).toString()); + assertEquals("fct1(foo DOUBLE)", new FunctionDef("fct1", new FunctionParam[]{new FunctionParam("foo", new DBType(DBDatatype.DOUBLE))}).toString()); + assertEquals("fct1(foo DOUBLE, pt POINT) -> VARCHAR", new FunctionDef("fct1", new DBType(DBDatatype.VARCHAR), new FunctionParam[]{new FunctionParam("foo", new DBType(DBDatatype.DOUBLE)),new FunctionParam("pt", new DBType(DBDatatype.POINT))}).toString()); + assertEquals("fct1(foo DOUBLE, pt POINT)", new FunctionDef("fct1", null, new FunctionParam[]{new FunctionParam("foo", new DBType(DBDatatype.DOUBLE)),new FunctionParam("pt", new DBType(DBDatatype.POINT))}).toString()); + } + + @Test + public void testParse(){ + final String WRONG_FULL_SYNTAX = "Wrong function definition syntax! Expected syntax: \"<regular_identifier>(<parameters>?) <return_type>?\", where <regular_identifier>=\"[a-zA-Z]+[a-zA-Z0-9_]*\", <return_type>=\" -> <type_name>\", <parameters>=\"(<regular_identifier> <type_name> (, <regular_identifier> <type_name>)*)\", <type_name> should be one of the types described in the UPLOAD section of the TAP documentation. Examples of good syntax: \"foo()\", \"foo() -> VARCHAR\", \"foo(param INTEGER)\", \"foo(param1 INTEGER, param2 DOUBLE) -> DOUBLE\""; + final String WRONG_PARAM_SYNTAX = "Wrong parameters syntax! Expected syntax: \"(<regular_identifier> <type_name> (, <regular_identifier> <type_name>)*)\", where <regular_identifier>=\"[a-zA-Z]+[a-zA-Z0-9_]*\", <type_name> should be one of the types described in the UPLOAD section of the TAP documentation. Examples of good syntax: \"()\", \"(param INTEGER)\", \"(param1 INTEGER, param2 DOUBLE)\""; + + // NULL test: + try{ + FunctionDef.parse(null); + fail("A NULL string is not valide!"); + }catch(Exception ex){ + assertTrue(ex instanceof NullPointerException); + assertEquals("Missing string definition to build a FunctionDef!", ex.getMessage()); + } + + // EMPTY STRING test: + try{ + FunctionDef.parse(""); + fail("An empty string is not valide!"); + }catch(Exception ex){ + assertTrue(ex instanceof ParseException); + assertEquals(WRONG_FULL_SYNTAX, ex.getMessage()); + } + + // CORRECT string definitions: + try{ + assertEquals("foo()", FunctionDef.parse("foo()").toString()); + assertEquals("foo() -> VARCHAR", FunctionDef.parse("foo() -> string").toString()); + assertEquals("foo() -> VARCHAR", FunctionDef.parse("foo()->string").toString()); + assertEquals("foo(toto VARCHAR) -> SMALLINT", FunctionDef.parse("foo(toto varchar) -> boolean").toString()); + assertEquals("foo(param1 DOUBLE, param2 INTEGER) -> DOUBLE", FunctionDef.parse(" foo ( param1 numeric, param2 int ) -> DOUBLE ").toString()); + assertEquals("foo_ALTernative2first(p POINT, d TIMESTAMP) -> TIMESTAMP", FunctionDef.parse("foo_ALTernative2first (p POINT,d date) -> time").toString()); + assertEquals("blabla_123(toto INTEGER, bla SMALLINT, truc CLOB, bidule CHAR, smurph POINT, date TIMESTAMP) -> SMALLINT", FunctionDef.parse("blabla_123(toto int4, bla bool, truc text, bidule character, smurph point, date timestamp) -> BOOLEAN").toString()); + }catch(Exception ex){ + ex.printStackTrace(System.err); + fail("All this string definitions are correct."); + } + + // TYPE PARAMETER test: + try{ + for(DBDatatype t : DBDatatype.values()){ + switch(t){ + case CHAR: + case VARCHAR: + case BINARY: + case VARBINARY: + assertEquals("foo() -> " + t.toString() + "(10)", FunctionDef.parse("foo() -> " + t.toString() + "(10)").toString()); + break; + default: + assertEquals("foo() -> " + t.toString(), FunctionDef.parse("foo() -> " + t.toString() + "(10)").toString()); + } + } + }catch(Exception ex){ + ex.printStackTrace(System.err); + fail("Wrong type parsing!"); + } + + // WRONG string definitions: + try{ + FunctionDef.parse("123()"); + fail("No number is allowed as first character of a function name!"); + }catch(Exception ex){ + assertTrue(ex instanceof ParseException); + assertEquals(WRONG_FULL_SYNTAX, ex.getMessage()); + } + try{ + FunctionDef.parse("1foo()"); + fail("No number is allowed as first character of a function name!"); + }catch(Exception ex){ + assertTrue(ex instanceof ParseException); + assertEquals(WRONG_FULL_SYNTAX, ex.getMessage()); + } + try{ + FunctionDef.parse("foo,truc()"); + fail("No other character than [a-zA-Z0-9_] is allowed after a first character [a-zA-Z] in a function name!"); + }catch(Exception ex){ + assertTrue(ex instanceof ParseException); + assertEquals(WRONG_FULL_SYNTAX, ex.getMessage()); + } + try{ + FunctionDef.parse("foo"); + fail("A function definition must contain at list parenthesis even if there is no parameter."); + }catch(Exception ex){ + assertTrue(ex instanceof ParseException); + assertEquals(WRONG_FULL_SYNTAX, ex.getMessage()); + } + try{ + FunctionDef.parse("foo(param)"); + fail("A parameter must always have a type!"); + }catch(Exception ex){ + assertTrue(ex instanceof ParseException); + assertEquals("Wrong syntax for the 1-th parameter: \"param\"! Expected syntax: \"(<regular_identifier> <type_name> (, <regular_identifier> <type_name>)*)\", where <regular_identifier>=\"[a-zA-Z]+[a-zA-Z0-9_]*\", <type_name> should be one of the types described in the UPLOAD section of the TAP documentation. Examples of good syntax: \"()\", \"(param INTEGER)\", \"(param1 INTEGER, param2 DOUBLE)\"", ex.getMessage()); + } + try{ + FunctionDef.parse("foo()->aType"); + fail("Wrong (return) type!"); + }catch(Exception ex){ + assertTrue(ex instanceof ParseException); + assertEquals("Unknown return type: \"aType\"!", ex.getMessage()); + } + try{ + FunctionDef.parse("foo()->aType(10)"); + fail("Wrong (return) type!"); + }catch(Exception ex){ + assertTrue(ex instanceof ParseException); + assertEquals("Unknown return type: \"aType(10)\"!", ex.getMessage()); + } + try{ + FunctionDef.parse("foo() -> "); + fail("The return type is missing!"); + }catch(Exception ex){ + assertTrue(ex instanceof ParseException); + assertEquals(WRONG_FULL_SYNTAX, ex.getMessage()); + } + try{ + FunctionDef.parse("foo(,)"); + fail("Missing parameter definition!"); + }catch(Exception ex){ + assertTrue(ex instanceof ParseException); + assertEquals(WRONG_PARAM_SYNTAX, ex.getMessage()); + } + try{ + FunctionDef.parse("foo(param1 int,)"); + fail("Missing parameter definition!"); + }catch(Exception ex){ + assertTrue(ex instanceof ParseException); + assertEquals(WRONG_PARAM_SYNTAX, ex.getMessage()); + } + try{ + FunctionDef.parse("foo(param1 aType)"); + fail("Wrong parameter type!"); + }catch(Exception ex){ + assertTrue(ex instanceof ParseException); + assertEquals("Unknown type for the parameter \"param1\": \"aType\"!", ex.getMessage()); + } + try{ + FunctionDef.parse("foo(param1 aType(10))"); + fail("Wrong parameter type!"); + }catch(Exception ex){ + assertTrue(ex instanceof ParseException); + assertEquals("Unknown type for the parameter \"param1\": \"aType(10)\"!", ex.getMessage()); + } + } + + @Test + public void testCompareToFunctionDef(){ + // DEFINITION 1 :: fct1() -> VARCHAR + FunctionDef def1 = new FunctionDef("fct1", new DBType(DBDatatype.VARCHAR)); + + // TEST :: Identity test (def1 with def1): [EQUAL] + assertEquals(0, def1.compareTo(def1)); + + // TEST :: With a function having a different name and also no parameter: [GREATER] + assertEquals(1, def1.compareTo(new FunctionDef("fct0", new DBType(DBDatatype.VARCHAR)))); + + // TEST :: With a function having the same name, but a different return type: [EQUAL} + assertEquals(0, def1.compareTo(new FunctionDef("fct1", new DBType(DBDatatype.INTEGER)))); + + // TEST :: With a function having the same name, but 2 parameters: [LESS (4 characters: ø against 1010)] + assertEquals(-6, def1.compareTo(new FunctionDef("fct1", new DBType(DBDatatype.INTEGER), new FunctionParam[]{new FunctionParam("foo", new DBType(DBDatatype.INTEGER)),new FunctionParam("foo", new DBType(DBDatatype.INTEGER))}))); + + // DEFINITION 1 :: fct1(foo1 CHAR(12), foo2 DOUBLE) -> VARCHAR + def1 = new FunctionDef("fct1", new DBType(DBDatatype.VARCHAR), new FunctionParam[]{new FunctionParam("foo1", new DBType(DBDatatype.CHAR, 12)),new FunctionParam("foo2", new DBType(DBDatatype.DOUBLE))}); + + // TEST :: Identity test (def1 with def1): [EQUAL] + assertEquals(0, def1.compareTo(def1)); + + // DEFINITION 2 :: fct1(foo1 CHAR(12), foo2 VARCHAR) -> VARCHAR + FunctionDef def2 = new FunctionDef("fct1", new DBType(DBDatatype.VARCHAR), new FunctionParam[]{new FunctionParam("foo1", new DBType(DBDatatype.CHAR, 12)),new FunctionParam("foo2", new DBType(DBDatatype.VARCHAR))}); + + // TEST :: Identity test (def2 with def2): [EQUAL] + assertEquals(0, def2.compareTo(def2)); + + // TEST :: Same name, but different type for the last parameter only: [GREATER (because Numeric = 10 > String = 01)] + assertEquals(1, def1.compareTo(def2)); + + // DEFINITION 2 :: fct2(foo1 CHAR(12), foo2 DOUBLE) -> VARCHAR + def2 = new FunctionDef("fct2", new DBType(DBDatatype.VARCHAR), new FunctionParam[]{new FunctionParam("foo1", new DBType(DBDatatype.CHAR, 12)),new FunctionParam("foo2", new DBType(DBDatatype.DOUBLE))}); + + // TEST :: Identity test (def2 with def2): [EQUAL] + assertEquals(0, def2.compareTo(def2)); + + // TEST :: Different name but same parameters: [LESS] + assertEquals(-1, def1.compareTo(def2)); + + // DEFINITION 2 :: fct1(foo1 CHAR(12), foo2 POINT) -> VARCHAR + def2 = new FunctionDef("fct1", new DBType(DBDatatype.VARCHAR), new FunctionParam[]{new FunctionParam("foo1", new DBType(DBDatatype.CHAR, 12)),new FunctionParam("foo2", new DBType(DBDatatype.POINT))}); + + // TEST :: Identity test (def2 with def2): [EQUAL] + assertEquals(0, def2.compareTo(def2)); + + // TEST :: Same name, but different type for the last parameter only: [GREATER] + assertEquals(1, def1.compareTo(def2)); + } + + @Test + public void testCompareToADQLFunction(){ + // DEFINITION :: fct1() -> VARCHAR + FunctionDef def = new FunctionDef("fct1", new DBType(DBDatatype.VARCHAR)); + + // TEST :: NULL: + try{ + def.compareTo((ADQLFunction)null); + fail("Missing ADQL function for comparison with FunctionDef!"); + }catch(Exception e){ + assertTrue(e instanceof NullPointerException); + assertEquals("Missing ADQL function with which comparing this function definition!", e.getMessage()); + } + + // TEST :: "fct1()": [EQUAL] + assertEquals(0, def.compareTo(new DefaultUDF("fct1", null))); + + // TEST :: "fct0()": [GREATER] + assertEquals(1, def.compareTo(new DefaultUDF("fct0", null))); + + // TEST :: "fct1(12.3, 3.14)": [LESS (of 2 params)] + assertEquals(-2, def.compareTo(new DefaultUDF("fct1", new ADQLOperand[]{new NumericConstant(12.3),new NumericConstant(3.14)}))); + + // DEFINITION :: fct1(foo1 CHAR(12), foo2 DOUBLE) -> VARCHAR + def = new FunctionDef("fct1", new DBType(DBDatatype.VARCHAR), new FunctionParam[]{new FunctionParam("foo1", new DBType(DBDatatype.CHAR, 12)),new FunctionParam("foo2", new DBType(DBDatatype.DOUBLE))}); + + // TEST :: "fct1('blabla', 'blabla2')": [GREATER (because the second param is numeric and Numeric = 10 > String = 01)] + assertEquals(1, def.compareTo(new DefaultUDF("fct1", new ADQLOperand[]{new StringConstant("blabla"),new StringConstant("blabla2")}))); + + // TEST :: "fct1('blabla', POINT('COORDSYS', 1.2, 3.4))": [GREATER (same reason ; POINT is considered as a String)] + try{ + assertEquals(1, def.compareTo(new DefaultUDF("fct1", new ADQLOperand[]{new StringConstant("blabla"),new PointFunction(new StringConstant("COORDSYS"), new NumericConstant(1.2), new NumericConstant(3.4))}))); + }catch(Exception e){ + e.printStackTrace(); + fail(); + } + } + +} diff --git a/test/adql/db/TestSTCS.java b/test/adql/db/TestSTCS.java new file mode 100644 index 0000000000000000000000000000000000000000..8ff76460c076c73b611c4e8cf1e564b55aa6c91b --- /dev/null +++ b/test/adql/db/TestSTCS.java @@ -0,0 +1,536 @@ +package adql.db; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.StringBufferInputStream; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import adql.db.STCS.CoordSys; +import adql.db.STCS.Flavor; +import adql.db.STCS.Frame; +import adql.db.STCS.RefPos; +import adql.db.STCS.Region; +import adql.db.STCS.RegionType; +import adql.parser.ADQLParser; +import adql.parser.ParseException; +import adql.query.operand.ADQLColumn; +import adql.query.operand.ADQLOperand; +import adql.query.operand.NegativeOperand; +import adql.query.operand.NumericConstant; +import adql.query.operand.Operation; +import adql.query.operand.OperationType; +import adql.query.operand.StringConstant; +import adql.query.operand.function.geometry.BoxFunction; +import adql.query.operand.function.geometry.CircleFunction; +import adql.query.operand.function.geometry.ContainsFunction; +import adql.query.operand.function.geometry.GeometryFunction; +import adql.query.operand.function.geometry.GeometryFunction.GeometryValue; +import adql.query.operand.function.geometry.PointFunction; +import adql.query.operand.function.geometry.PolygonFunction; +import adql.query.operand.function.geometry.RegionFunction; + +@SuppressWarnings("deprecation") +public class TestSTCS { + + @BeforeClass + public static void setUpBeforeClass() throws Exception{} + + @AfterClass + public static void tearDownAfterClass() throws Exception{} + + @Before + public void setUp() throws Exception{} + + @After + public void tearDown() throws Exception{} + + @Test + public void buildRegion(){ + // Special values: + try{ + new Region((GeometryFunction)null); + fail(); + }catch(Exception e){ + assertTrue(e instanceof NullPointerException); + assertEquals("Missing geometry to convert into STCS.Region!", e.getMessage()); + } + + try{ + new Region((Region)null); + fail(); + }catch(Exception e){ + assertTrue(e instanceof NullPointerException); + assertEquals("Missing region to NOT select!", e.getMessage()); + } + + try{ + new Region(new ContainsFunction(new GeometryValue<GeometryFunction>(new RegionFunction(new StringConstant("position 1 2"))), new GeometryValue<GeometryFunction>(new RegionFunction(new StringConstant("circle 0 1 4"))))); + fail(); + }catch(Exception e){ + assertTrue(e instanceof IllegalArgumentException); + assertEquals("Unknown region type! Only geometrical function PointFunction, CircleFunction, BoxFunction, PolygonFunction and RegionFunction are allowed.", e.getMessage()); + } + + // Allowed values (1 test for each type of region): + try{ + Region r = new Region(new PointFunction(new StringConstant(""), new NumericConstant(1.2), new NegativeOperand(new NumericConstant(2.3)))); + assertEquals(RegionType.POSITION, r.type); + assertEquals("", r.coordSys.toSTCS()); + assertEquals(1, r.coordinates.length); + assertEquals(2, r.coordinates[0].length); + assertEquals(1.2, r.coordinates[0][0], 0); + assertEquals(-2.3, r.coordinates[0][1], 0); + assertEquals(Double.NaN, r.radius, 0); + assertEquals(Double.NaN, r.width, 0); + assertEquals(Double.NaN, r.height, 0); + assertNull(r.regions); + assertEquals("POSITION 1.2 -2.3", r.toSTCS()); + + r = new Region(new CircleFunction(new StringConstant("ICRS"), new NumericConstant(1.2), new NegativeOperand(new NumericConstant(2.3)), new NumericConstant(5))); + assertEquals(RegionType.CIRCLE, r.type); + assertEquals("ICRS", r.coordSys.toSTCS()); + assertEquals(1, r.coordinates.length); + assertEquals(2, r.coordinates[0].length); + assertEquals(1.2, r.coordinates[0][0], 0); + assertEquals(-2.3, r.coordinates[0][1], 0); + assertEquals(5, r.radius, 0); + assertEquals(Double.NaN, r.width, 0); + assertEquals(Double.NaN, r.height, 0); + assertNull(r.regions); + assertEquals("CIRCLE ICRS 1.2 -2.3 5.0", r.toSTCS()); + + r = new Region(new BoxFunction(new StringConstant("ICRS heliocenter"), new NumericConstant(1.2), new NegativeOperand(new NumericConstant(2.3)), new NumericConstant(5), new NumericConstant(4.6))); + assertEquals(RegionType.BOX, r.type); + assertEquals("ICRS HELIOCENTER", r.coordSys.toSTCS()); + assertEquals(1, r.coordinates.length); + assertEquals(2, r.coordinates[0].length); + assertEquals(1.2, r.coordinates[0][0], 0); + assertEquals(-2.3, r.coordinates[0][1], 0); + assertEquals(Double.NaN, r.radius, 0); + assertEquals(5, r.width, 0); + assertEquals(4.6, r.height, 0); + assertNull(r.regions); + assertEquals("BOX ICRS HELIOCENTER 1.2 -2.3 5.0 4.6", r.toSTCS()); + + r = new Region(new PolygonFunction(new StringConstant("cartesian2"), new ADQLOperand[]{new NumericConstant(1.2),new NegativeOperand(new NumericConstant(2.3)),new NumericConstant(5),new NumericConstant(4.6),new NegativeOperand(new NumericConstant(.89)),new NumericConstant(1)})); + assertEquals(RegionType.POLYGON, r.type); + assertEquals("CARTESIAN2", r.coordSys.toSTCS()); + assertEquals(3, r.coordinates.length); + assertEquals(2, r.coordinates[0].length); + assertEquals(1.2, r.coordinates[0][0], 0); + assertEquals(-2.3, r.coordinates[0][1], 0); + assertEquals(5, r.coordinates[1][0], 0); + assertEquals(4.6, r.coordinates[1][1], 0); + assertEquals(-0.89, r.coordinates[2][0], 0); + assertEquals(1, r.coordinates[2][1], 0); + assertEquals(Double.NaN, r.radius, 0); + assertEquals(Double.NaN, r.width, 0); + assertEquals(Double.NaN, r.height, 0); + assertNull(r.regions); + assertEquals("POLYGON CARTESIAN2 1.2 -2.3 5.0 4.6 -0.89 1.0", r.toSTCS()); + + r = new Region(new RegionFunction(new StringConstant("position ICrs 1.2 -2.3"))); + assertEquals(RegionType.POSITION, r.type); + assertEquals("ICRS", r.coordSys.toSTCS()); + assertEquals(1, r.coordinates.length); + assertEquals(2, r.coordinates[0].length); + assertEquals(1.2, r.coordinates[0][0], 0); + assertEquals(-2.3, r.coordinates[0][1], 0); + assertEquals(Double.NaN, r.radius, 0); + assertEquals(Double.NaN, r.width, 0); + assertEquals(Double.NaN, r.height, 0); + assertNull(r.regions); + assertEquals("POSITION ICRS 1.2 -2.3", r.toSTCS()); + + r = new Region(new RegionFunction(new StringConstant("Union ICRS (Polygon 1 4 2 4 2 5 1 5 Polygon 3 4 4 4 4 5 3 5)"))); + assertEquals(RegionType.UNION, r.type); + assertEquals("ICRS", r.coordSys.toSTCS()); + assertNull(r.coordinates); + assertEquals(Double.NaN, r.radius, 0); + assertEquals(Double.NaN, r.width, 0); + assertEquals(Double.NaN, r.height, 0); + assertEquals(2, r.regions.length); + assertEquals("UNION ICRS (POLYGON 1.0 4.0 2.0 4.0 2.0 5.0 1.0 5.0 POLYGON 3.0 4.0 4.0 4.0 4.0 5.0 3.0 5.0)", r.toString()); + // inner region 1 + Region innerR = r.regions[0]; + assertEquals(RegionType.POLYGON, innerR.type); + assertEquals("", innerR.coordSys.toSTCS()); + assertEquals(4, innerR.coordinates.length); + assertEquals(2, innerR.coordinates[0].length); + assertEquals(1, innerR.coordinates[0][0], 0); + assertEquals(4, innerR.coordinates[0][1], 0); + assertEquals(2, innerR.coordinates[1][0], 0); + assertEquals(4, innerR.coordinates[1][1], 0); + assertEquals(2, innerR.coordinates[2][0], 0); + assertEquals(5, innerR.coordinates[2][1], 0); + assertEquals(1, innerR.coordinates[3][0], 0); + assertEquals(5, innerR.coordinates[3][1], 0); + assertEquals(Double.NaN, innerR.radius, 0); + assertEquals(Double.NaN, innerR.width, 0); + assertEquals(Double.NaN, innerR.height, 0); + assertNull(innerR.regions); + assertEquals("POLYGON 1.0 4.0 2.0 4.0 2.0 5.0 1.0 5.0", innerR.toSTCS()); + // inner region 2 + innerR = r.regions[1]; + assertEquals(RegionType.POLYGON, innerR.type); + assertEquals("", innerR.coordSys.toSTCS()); + assertEquals(4, innerR.coordinates.length); + assertEquals(2, innerR.coordinates[0].length); + assertEquals(3, innerR.coordinates[0][0], 0); + assertEquals(4, innerR.coordinates[0][1], 0); + assertEquals(4, innerR.coordinates[1][0], 0); + assertEquals(4, innerR.coordinates[1][1], 0); + assertEquals(4, innerR.coordinates[2][0], 0); + assertEquals(5, innerR.coordinates[2][1], 0); + assertEquals(3, innerR.coordinates[3][0], 0); + assertEquals(5, innerR.coordinates[3][1], 0); + assertEquals(Double.NaN, innerR.radius, 0); + assertEquals(Double.NaN, innerR.width, 0); + assertEquals(Double.NaN, innerR.height, 0); + assertNull(innerR.regions); + assertEquals("POLYGON 3.0 4.0 4.0 4.0 4.0 5.0 3.0 5.0", innerR.toSTCS()); + + r = new Region(new RegionFunction(new StringConstant("NOT(CIRCLE ICRS 1.2 -2.3 5)"))); + assertEquals(RegionType.NOT, r.type); + assertNull(r.coordSys); + assertNull(r.coordinates); + assertEquals(Double.NaN, r.radius, 0); + assertEquals(Double.NaN, r.width, 0); + assertEquals(Double.NaN, r.height, 0); + assertEquals(1, r.regions.length); + assertEquals("NOT(CIRCLE ICRS 1.2 -2.3 5.0)", r.toSTCS()); + // inner region + innerR = r.regions[0]; + assertEquals(RegionType.CIRCLE, innerR.type); + assertEquals("ICRS", innerR.coordSys.toSTCS()); + assertEquals(1, innerR.coordinates.length); + assertEquals(2, innerR.coordinates[0].length); + assertEquals(1.2, innerR.coordinates[0][0], 0); + assertEquals(-2.3, innerR.coordinates[0][1], 0); + assertEquals(5, innerR.radius, 0); + assertEquals(Double.NaN, innerR.width, 0); + assertEquals(Double.NaN, innerR.height, 0); + assertNull(innerR.regions); + assertEquals("CIRCLE ICRS 1.2 -2.3 5.0", innerR.toSTCS()); + }catch(Exception e){ + e.printStackTrace(System.err); + fail(); + } + + // Test with incorrect syntaxes: + try{ + new Region(new PointFunction(new StringConstant(""), new StringConstant("1.2"), new NegativeOperand(new NumericConstant(2.3)))); + fail("The first coordinate is a StringConstant rather than a NumericConstant!"); + }catch(Exception e){ + assertTrue(e instanceof ParseException); + assertEquals("Can not convert into STC-S a non numeric argument (including ADQLColumn and Operation)!", e.getMessage()); + } + try{ + new Region(new PointFunction(new NumericConstant(.65), new NumericConstant(1.2), new NegativeOperand(new NumericConstant(2.3)))); + fail("The coordinate system is a NumericConstant rather than a StringConstant!"); + }catch(Exception e){ + assertTrue(e instanceof ParseException); + assertEquals("A coordinate system must be a string literal: \"0.65\" is not a string operand!", e.getMessage()); + } + try{ + new Region(new PointFunction(new StringConstant(""), null, new NegativeOperand(new NumericConstant(2.3)))); + fail("The first coordinate is missing!"); + }catch(Exception e){ + assertTrue(e instanceof NullPointerException); + assertEquals("The POINT function must have non-null coordinates!", e.getMessage()); + } + try{ + new Region(new RegionFunction(new StringConstant(""))); + fail("Missing STC-S expression!"); + }catch(Exception e){ + assertTrue(e instanceof ParseException); + assertEquals("Missing STC-S expression to parse!", e.getMessage()); + } + try{ + new Region(new RegionFunction(new StringConstant("MyRegion HERE 1.2"))); + fail("Totally incorrect region type!"); + }catch(Exception e){ + assertTrue(e instanceof ParseException); + assertEquals("Unknown STC region type: \"MYREGION\"!", e.getMessage()); + } + try{ + new Region(new RegionFunction((new ADQLParser(new StringBufferInputStream("'POSITION ' || coordinateSys || ' ' || ra || ' ' || dec"))).StringExpression())); + fail("String concatenation can not be managed!"); + }catch(Exception e){ + assertTrue(e instanceof ParseException); + assertEquals("Can not convert into STC-S a non string argument (including ADQLColumn and Concatenation)!", e.getMessage()); + } + try{ + new Region(new PointFunction(new ADQLColumn("coordSys"), new NumericConstant(1), new NumericConstant(2))); + fail("Columns can not be managed!"); + }catch(Exception e){ + assertTrue(e instanceof ParseException); + assertEquals("Can not convert into STC-S a non string argument (including ADQLColumn and Concatenation)!", e.getMessage()); + } + try{ + new Region(new PointFunction(new StringConstant("ICRS"), new Operation(new NumericConstant(2), OperationType.MULT, new NumericConstant(5)), new NumericConstant(2))); + fail("Operations can not be managed!"); + }catch(Exception e){ + assertTrue(e instanceof ParseException); + assertEquals("Can not convert into STC-S a non numeric argument (including ADQLColumn and Operation)!", e.getMessage()); + } + } + + @Test + public void parseCoordSys(){ + // GOOD SYNTAXES: + try{ + CoordSys p; + + // Default coordinate system (should be then interpreted as local coordinate system): + for(String s : new String[]{null,""," "}){ + p = STCS.parseCoordSys(s); + assertEquals(Frame.UNKNOWNFRAME, p.frame); + assertEquals(RefPos.UNKNOWNREFPOS, p.refpos); + assertEquals(Flavor.SPHERICAL2, p.flavor); + assertTrue(p.isDefault()); + } + + // Just a frame: + p = STCS.parseCoordSys("ICRS"); + assertEquals(Frame.ICRS, p.frame); + assertEquals(RefPos.UNKNOWNREFPOS, p.refpos); + assertEquals(Flavor.SPHERICAL2, p.flavor); + assertFalse(p.isDefault()); + + // Just a reference position: + p = STCS.parseCoordSys("LSR"); + assertEquals(Frame.UNKNOWNFRAME, p.frame); + assertEquals(RefPos.LSR, p.refpos); + assertEquals(Flavor.SPHERICAL2, p.flavor); + assertFalse(p.isDefault()); + + // Just a flavor: + p = STCS.parseCoordSys("CARTESIAN2"); + assertEquals(Frame.UNKNOWNFRAME, p.frame); + assertEquals(RefPos.UNKNOWNREFPOS, p.refpos); + assertEquals(Flavor.CARTESIAN2, p.flavor); + assertFalse(p.isDefault()); + + // Frame + RefPos: + p = STCS.parseCoordSys("ICRS LSR"); + assertEquals(Frame.ICRS, p.frame); + assertEquals(RefPos.LSR, p.refpos); + assertEquals(Flavor.SPHERICAL2, p.flavor); + assertFalse(p.isDefault()); + + // Frame + Flavor: + p = STCS.parseCoordSys("ICRS SPHERICAL2"); + assertEquals(Frame.ICRS, p.frame); + assertEquals(RefPos.UNKNOWNREFPOS, p.refpos); + assertEquals(Flavor.SPHERICAL2, p.flavor); + assertFalse(p.isDefault()); + + // RefPos + Flavor: + p = STCS.parseCoordSys("HELIOCENTER SPHERICAL2"); + assertEquals(Frame.UNKNOWNFRAME, p.frame); + assertEquals(RefPos.HELIOCENTER, p.refpos); + assertEquals(Flavor.SPHERICAL2, p.flavor); + assertFalse(p.isDefault()); + + // Frame + RefPos + Flavor + p = STCS.parseCoordSys("ICRS GEOCENTER SPHERICAL2"); + assertEquals(Frame.ICRS, p.frame); + assertEquals(RefPos.GEOCENTER, p.refpos); + assertEquals(Flavor.SPHERICAL2, p.flavor); + assertFalse(p.isDefault()); + + // Lets try in a different case: + p = STCS.parseCoordSys("icrs Geocenter SpheriCAL2"); + assertEquals(Frame.ICRS, p.frame); + assertEquals(RefPos.GEOCENTER, p.refpos); + assertEquals(Flavor.SPHERICAL2, p.flavor); + assertFalse(p.isDefault()); + }catch(Exception e){ + e.printStackTrace(System.err); + fail(); + } + + // WRONG SYNTAXES: + try{ + STCS.parseCoordSys("HOME"); + fail(); + }catch(Exception e){ + assertTrue(e instanceof ParseException); + assertEquals("Incorrect syntax: \"HOME\" was unexpected! Expected syntax: \"[(ECLIPTIC|FK4|FK5|GALACTIC|ICRS|UNKNOWNFRAME)] [(BARYCENTER|GEOCENTER|HELIOCENTER|LSR|TOPOCENTER|RELOCATABLE|UNKNOWNREFPOS)] [(CARTESIAN2|CARTESIAN3|SPHERICAL2)]\" ; an empty string is also allowed and will be interpreted as the coordinate system locally used.", e.getMessage()); + } + + // With wrong reference position: + try{ + STCS.parseCoordSys("ICRS HOME SPHERICAL2"); + fail(); + }catch(Exception e){ + assertTrue(e instanceof ParseException); + assertEquals("Incorrect syntax: \"HOME SPHERICAL2\" was unexpected! Expected syntax: \"[(ECLIPTIC|FK4|FK5|GALACTIC|ICRS|UNKNOWNFRAME)] [(BARYCENTER|GEOCENTER|HELIOCENTER|LSR|TOPOCENTER|RELOCATABLE|UNKNOWNREFPOS)] [(CARTESIAN2|CARTESIAN3|SPHERICAL2)]\" ; an empty string is also allowed and will be interpreted as the coordinate system locally used.", e.getMessage()); + } + + // With a cartesian flavor: + try{ + STCS.parseCoordSys("ICRS CARTESIAN2"); + fail(); + }catch(Exception e){ + assertTrue(e instanceof ParseException); + assertEquals("a coordinate system expressed with a cartesian flavor MUST have an UNKNOWNFRAME and UNKNOWNREFPOS!", e.getMessage()); + } + try{ + STCS.parseCoordSys("LSR CARTESIAN3"); + fail(); + }catch(Exception e){ + assertTrue(e instanceof ParseException); + assertEquals("a coordinate system expressed with a cartesian flavor MUST have an UNKNOWNFRAME and UNKNOWNREFPOS!", e.getMessage()); + } + try{ + CoordSys p = STCS.parseCoordSys("CARTESIAN2"); + assertEquals(Frame.UNKNOWNFRAME, p.frame); + assertEquals(RefPos.UNKNOWNREFPOS, p.refpos); + assertEquals(Flavor.CARTESIAN2, p.flavor); + + p = STCS.parseCoordSys("CARTESIAN3"); + assertEquals(Frame.UNKNOWNFRAME, p.frame); + assertEquals(RefPos.UNKNOWNREFPOS, p.refpos); + assertEquals(Flavor.CARTESIAN3, p.flavor); + }catch(Exception e){ + e.printStackTrace(System.err); + fail(); + } + + // Without spaces: + try{ + STCS.parseCoordSys("icrsGeocentercarteSIAN2"); + fail(); + }catch(Exception e){ + assertTrue(e instanceof ParseException); + assertEquals("Incorrect syntax: \"icrsGeocentercarteSIAN2\" was unexpected! Expected syntax: \"[(ECLIPTIC|FK4|FK5|GALACTIC|ICRS|UNKNOWNFRAME)] [(BARYCENTER|GEOCENTER|HELIOCENTER|LSR|TOPOCENTER|RELOCATABLE|UNKNOWNREFPOS)] [(CARTESIAN2|CARTESIAN3|SPHERICAL2)]\" ; an empty string is also allowed and will be interpreted as the coordinate system locally used.", e.getMessage()); + } + } + + @Test + public void serializeCoordSys(){ + try{ + assertEquals("", STCS.toSTCS((CoordSys)null)); + + assertEquals("", STCS.toSTCS(new CoordSys())); + + assertEquals("", STCS.toSTCS(new CoordSys(null, null, null))); + assertEquals("", STCS.toSTCS(new CoordSys(Frame.DEFAULT, RefPos.DEFAULT, Flavor.DEFAULT))); + assertEquals("", STCS.toSTCS(new CoordSys(Frame.UNKNOWNFRAME, RefPos.UNKNOWNREFPOS, Flavor.SPHERICAL2))); + + assertEquals("", STCS.toSTCS(new CoordSys(null))); + assertEquals("", STCS.toSTCS(new CoordSys(""))); + assertEquals("", STCS.toSTCS(new CoordSys(" \n\r"))); + + assertEquals("ICRS", STCS.toSTCS(new CoordSys(Frame.ICRS, null, null))); + assertEquals("ICRS", STCS.toSTCS(new CoordSys(Frame.ICRS, RefPos.DEFAULT, Flavor.DEFAULT))); + assertEquals("ICRS", STCS.toSTCS(new CoordSys(Frame.ICRS, RefPos.UNKNOWNREFPOS, Flavor.SPHERICAL2))); + + assertEquals("GEOCENTER", STCS.toSTCS(new CoordSys(null, RefPos.GEOCENTER, null))); + assertEquals("GEOCENTER", STCS.toSTCS(new CoordSys(Frame.DEFAULT, RefPos.GEOCENTER, Flavor.DEFAULT))); + assertEquals("GEOCENTER", STCS.toSTCS(new CoordSys(Frame.UNKNOWNFRAME, RefPos.GEOCENTER, Flavor.SPHERICAL2))); + + assertEquals("CARTESIAN3", STCS.toSTCS(new CoordSys(null, null, Flavor.CARTESIAN3))); + assertEquals("CARTESIAN3", STCS.toSTCS(new CoordSys(Frame.DEFAULT, RefPos.UNKNOWNREFPOS, Flavor.CARTESIAN3))); + assertEquals("CARTESIAN3", STCS.toSTCS(new CoordSys(Frame.UNKNOWNFRAME, RefPos.UNKNOWNREFPOS, Flavor.CARTESIAN3))); + + assertEquals("ICRS GEOCENTER", STCS.toSTCS(new CoordSys(Frame.ICRS, RefPos.GEOCENTER, null))); + assertEquals("ICRS GEOCENTER", STCS.toSTCS(new CoordSys(Frame.ICRS, RefPos.GEOCENTER, Flavor.DEFAULT))); + + assertEquals("UNKNOWNFRAME UNKNOWNREFPOS SPHERICAL2", new CoordSys().toFullSTCS()); + assertEquals("UNKNOWNFRAME UNKNOWNREFPOS SPHERICAL2", new CoordSys("").toFullSTCS()); + assertEquals("UNKNOWNFRAME UNKNOWNREFPOS SPHERICAL2", new CoordSys(null).toFullSTCS()); + assertEquals("UNKNOWNFRAME UNKNOWNREFPOS SPHERICAL2", new CoordSys(" \n\t").toFullSTCS()); + assertEquals("UNKNOWNFRAME UNKNOWNREFPOS SPHERICAL2", new CoordSys(null, null, null).toFullSTCS()); + assertEquals("UNKNOWNFRAME UNKNOWNREFPOS SPHERICAL2", new CoordSys(Frame.DEFAULT, RefPos.DEFAULT, Flavor.DEFAULT).toFullSTCS()); + assertEquals("ICRS UNKNOWNREFPOS SPHERICAL2", new CoordSys(Frame.ICRS, null, null).toFullSTCS()); + assertEquals("ICRS UNKNOWNREFPOS SPHERICAL2", new CoordSys(Frame.ICRS, RefPos.DEFAULT, Flavor.DEFAULT).toFullSTCS()); + assertEquals("UNKNOWNFRAME GEOCENTER SPHERICAL2", new CoordSys(Frame.UNKNOWNFRAME, RefPos.GEOCENTER, Flavor.DEFAULT).toFullSTCS()); + assertEquals("UNKNOWNFRAME UNKNOWNREFPOS CARTESIAN3", new CoordSys(Frame.DEFAULT, RefPos.DEFAULT, Flavor.CARTESIAN3).toFullSTCS()); + assertEquals("ICRS GEOCENTER SPHERICAL2", new CoordSys(Frame.ICRS, RefPos.GEOCENTER, Flavor.DEFAULT).toFullSTCS()); + }catch(ParseException pe){ + pe.printStackTrace(System.err); + fail(); + } + } + + @Test + public void parseRegion(){ + // TESTS WITH NO STC-S: + try{ + STCS.parseRegion(null); + fail(); + }catch(Exception e){ + assertTrue(e instanceof ParseException); + assertEquals("Missing STC-S expression to parse!", e.getMessage()); + } + try{ + STCS.parseRegion(""); + fail(); + }catch(Exception e){ + assertTrue(e instanceof ParseException); + assertEquals("Missing STC-S expression to parse!", e.getMessage()); + } + try{ + STCS.parseRegion(" \n\r"); + fail(); + }catch(Exception e){ + assertTrue(e instanceof ParseException); + assertEquals("Missing STC-S expression to parse!", e.getMessage()); + } + + // TESTS WITH A VALID EXPRESSION, EACH OF A DIFFERENT REGION TYPE: + String[] expressions = new String[]{" Position GALACTIC 10 20","Circle ICRS GEOCENTER 10 20 0.5 ","BOX cartesian2 3 3 2 2","Polygon 1 4 2 4 2 5 1 5","Union ICRS (Polygon 1 4 2 4 2 5 1 5 Polygon 3 4 4 4 4 5 3 5)","INTERSECTION ICRS (Polygon 1 4 2 4 2 5 1 5 Polygon 3 4 4 4 4 5 3 5)","NOT(Circle ICRS GEOCENTER 10 20 0.5)"}; + try{ + for(String e : expressions) + STCS.parseRegion(e); + }catch(Exception ex){ + ex.printStackTrace(System.err); + fail(); + } + + // TEST WITH A MISSING PARAMETER: + expressions = new String[]{" Position GALACTIC 10 ","BOX cartesian2 3 3 2","NOT()"}; + for(String e : expressions){ + try{ + STCS.parseRegion(e); + fail(); + }catch(Exception ex){ + assertTrue(ex instanceof ParseException); + assertTrue(ex.getMessage().startsWith("Unexpected End Of Expression! Expected syntax: \"")); + } + } + + // TEST WITH A WRONG COORDINATE SYSTEM (since it is optional in all these expressions, it will be considered as a coordinate...which is of course, not the case): + try{ + STCS.parseRegion("Circle HERE 10 20 0.5 "); + fail(); + }catch(Exception ex){ + assertTrue(ex instanceof ParseException); + assertTrue(ex.getMessage().startsWith("Incorrect syntax: a coordinates pair (2 numerics separated by one or more spaces) was expected! Expected syntax: \"CIRCLE <coordSys> <coordPair> <radius>\", where coordPair=\"<numeric> <numeric>\", radius=\"<numeric>\" and coordSys=\"[(ECLIPTIC|FK4|FK5|GALACTIC|ICRS|UNKNOWNFRAME)] [(BARYCENTER|GEOCENTER|HELIOCENTER|LSR|TOPOCENTER|RELOCATABLE|UNKNOWNREFPOS)] [(CARTESIAN2|CARTESIAN3|SPHERICAL2)]\" ; an empty string is also allowed and will be interpreted as the coordinate system locally used.")); + } + + // TEST WITH EITHER A WRONG NUMERIC (L in lower case instead of 1) OR A MISSING OPENING PARENTHESIS: + expressions = new String[]{"Polygon 1 4 2 4 2 5 l 5","Union ICRS Polygon 1 4 2 4 2 5 1 5 Polygon 3 4 4 4 4 5 3 5)"}; + for(String e : expressions){ + try{ + STCS.parseRegion(e); + fail(); + }catch(Exception ex){ + assertTrue(ex instanceof ParseException); + assertTrue(ex.getMessage().startsWith("Incorrect syntax: ")); + } + } + } +} diff --git a/test/adql/parser/TestADQLParser.java b/test/adql/parser/TestADQLParser.java new file mode 100644 index 0000000000000000000000000000000000000000..10837d51c98c84a26d562efc5d48ccd053c588b8 --- /dev/null +++ b/test/adql/parser/TestADQLParser.java @@ -0,0 +1,43 @@ +package adql.parser; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import adql.query.ADQLQuery; +import adql.query.operand.StringConstant; + +public class TestADQLParser { + + @BeforeClass + public static void setUpBeforeClass() throws Exception{} + + @AfterClass + public static void tearDownAfterClass() throws Exception{} + + @Before + public void setUp() throws Exception{} + + @After + public void tearDown() throws Exception{} + + @Test + public void test(){ + ADQLParser parser = new ADQLParser(); + try{ + ADQLQuery query = parser.parseQuery("SELECT 'truc''machin' 'bidule' -- why not a comment now ^^\n'FIN' FROM foo;"); + assertNotNull(query); + assertEquals("truc'machinbiduleFIN", ((StringConstant)(query.getSelect().get(0).getOperand())).getValue()); + assertEquals("'truc''machinbiduleFIN'", query.getSelect().get(0).getOperand().toADQL()); + }catch(Exception ex){ + fail("String litteral concatenation is perfectly legal according to the ADQL standard."); + } + } + +} diff --git a/test/tap/db/JDBCConnectionTest.java b/test/tap/db/JDBCConnectionTest.java index 2cd74577a3600b882ab920049134a8d5a83acf5e..b645e85800bee3eb0f71d0ad592bce7cec49df76 100644 --- a/test/tap/db/JDBCConnectionTest.java +++ b/test/tap/db/JDBCConnectionTest.java @@ -32,12 +32,12 @@ import tap.metadata.TAPMetadata.STDSchema; import tap.metadata.TAPMetadata.STDTable; import tap.metadata.TAPSchema; import tap.metadata.TAPTable; -import tap.metadata.TAPType; -import tap.metadata.TAPType.TAPDatatype; import testtools.DBTools; import adql.db.DBChecker; import adql.db.DBColumn; import adql.db.DBTable; +import adql.db.DBType; +import adql.db.DBType.DBDatatype; import adql.parser.ADQLParser; import adql.parser.ParseException; import adql.query.ADQLQuery; @@ -179,8 +179,8 @@ public class JDBCConnectionTest { assertEquals("VARCHAR", pgJDBCConnection.getDBMSDatatype(null)); assertEquals("TEXT", sqliteJDBCConnection.getDBMSDatatype(null)); - assertEquals("bytea", pgJDBCConnection.getDBMSDatatype(new TAPType(TAPDatatype.VARBINARY))); - assertEquals("BLOB", sqliteJDBCConnection.getDBMSDatatype(new TAPType(TAPDatatype.VARBINARY))); + assertEquals("bytea", pgJDBCConnection.getDBMSDatatype(new DBType(DBDatatype.VARBINARY))); + assertEquals("BLOB", sqliteJDBCConnection.getDBMSDatatype(new DBType(DBDatatype.VARBINARY))); } @Test @@ -854,7 +854,7 @@ public class JDBCConnectionTest { return true; } - private static boolean equals(final TAPType type1, final TAPType type2){ + private static boolean equals(final DBType type1, final DBType type2){ return type1 != null && type2 != null && type1.type == type2.type && type1.length == type2.length; } @@ -862,7 +862,7 @@ public class JDBCConnectionTest { TAPMetadata tapMeta = new TAPMetadata(); TAPSchema tapSchema = new TAPSchema(STDSchema.TAPSCHEMA.toString()); TAPTable customColumns = (TAPTable)TAPMetadata.getStdTable(STDTable.COLUMNS).copy("Columns", STDTable.COLUMNS.label); - customColumns.addColumn("TestNewColumn", new TAPType(TAPDatatype.VARCHAR), "This is a fake column, just for test purpose.", null, null, null); + customColumns.addColumn("TestNewColumn", new DBType(DBDatatype.VARCHAR), "This is a fake column, just for test purpose.", null, null, null); tapSchema.addTable(customColumns); TAPTable addTable = new TAPTable("AdditionalTable"); addTable.addColumn("Blabla"); diff --git a/test/tap/formatter/JSONFormatTest.java b/test/tap/formatter/JSONFormatTest.java index 527d7e2cfda74d37bc49f4e2b247de4345083370..3e6a84522088cea570b458db650900e7ce0ced9d 100644 --- a/test/tap/formatter/JSONFormatTest.java +++ b/test/tap/formatter/JSONFormatTest.java @@ -31,11 +31,12 @@ import tap.file.TAPFileManager; import tap.log.TAPLog; import tap.metadata.TAPColumn; import tap.metadata.TAPMetadata; -import tap.metadata.TAPType; -import tap.metadata.TAPType.TAPDatatype; import tap.parameters.TAPParameters; import testtools.DBTools; import uws.service.UserIdentifier; +import adql.db.DBType; +import adql.db.DBType.DBDatatype; +import adql.db.FunctionDef; /** * <p>Test the JSONFormat function {@link JSONFormat#writeResult(TableIterator, OutputStream, TAPExecutionReport, Thread)}.</p> @@ -58,10 +59,10 @@ public class JSONFormatTest { serviceConn = new ServiceConnectionTest(); resultingColumns = new TAPColumn[4]; - resultingColumns[0] = new TAPColumn("ID", new TAPType(TAPDatatype.VARCHAR)); - resultingColumns[1] = new TAPColumn("ra", new TAPType(TAPDatatype.DOUBLE), "Right ascension", "deg", "pos.eq.ra", null); - resultingColumns[2] = new TAPColumn("deg", new TAPType(TAPDatatype.DOUBLE), "Declination", "deg", "pos.eq.dec", null); - resultingColumns[3] = new TAPColumn("gmag", new TAPType(TAPDatatype.DOUBLE), "G magnitude", "mag", "phot.mag;em.opt.B", null); + resultingColumns[0] = new TAPColumn("ID", new DBType(DBDatatype.VARCHAR)); + resultingColumns[1] = new TAPColumn("ra", new DBType(DBDatatype.DOUBLE), "Right ascension", "deg", "pos.eq.ra", null); + resultingColumns[2] = new TAPColumn("deg", new DBType(DBDatatype.DOUBLE), "Declination", "deg", "pos.eq.dec", null); + resultingColumns[3] = new TAPColumn("gmag", new DBType(DBDatatype.DOUBLE), "G magnitude", "mag", "phot.mag;em.opt.B", null); if (!jsonFile.exists()) jsonFile.createNewFile(); @@ -223,6 +224,16 @@ public class JSONFormatTest { return null; } + @Override + public Collection<String> getGeometries(){ + return null; + } + + @Override + public Collection<FunctionDef> getUDFs(){ + return null; + } + @Override public TAPLog getLogger(){ return null; diff --git a/test/tap/formatter/SVFormatTest.java b/test/tap/formatter/SVFormatTest.java index d71c6accf79a64cf5343209af274af62265663ad..d50f0fecae68fc6f5c282b144d98ed17851161c5 100644 --- a/test/tap/formatter/SVFormatTest.java +++ b/test/tap/formatter/SVFormatTest.java @@ -28,12 +28,13 @@ import tap.file.TAPFileManager; import tap.log.TAPLog; import tap.metadata.TAPColumn; import tap.metadata.TAPMetadata; -import tap.metadata.TAPType; -import tap.metadata.TAPType.TAPDatatype; import tap.parameters.TAPParameters; import testtools.CommandExecute; import testtools.DBTools; import uws.service.UserIdentifier; +import adql.db.DBType; +import adql.db.DBType.DBDatatype; +import adql.db.FunctionDef; /** * <p>Test the SVFormat function {@link SVFormat#writeResult(TableIterator, OutputStream, TAPExecutionReport, Thread)}.</p> @@ -56,10 +57,10 @@ public class SVFormatTest { serviceConn = new ServiceConnectionTest(); resultingColumns = new TAPColumn[4]; - resultingColumns[0] = new TAPColumn("ID", new TAPType(TAPDatatype.VARCHAR)); - resultingColumns[1] = new TAPColumn("ra", new TAPType(TAPDatatype.DOUBLE), "Right ascension", "deg", "pos.eq.ra", null); - resultingColumns[2] = new TAPColumn("deg", new TAPType(TAPDatatype.DOUBLE), "Declination", "deg", "pos.eq.dec", null); - resultingColumns[3] = new TAPColumn("gmag", new TAPType(TAPDatatype.DOUBLE), "G magnitude", "mag", "phot.mag;em.opt.B", null); + resultingColumns[0] = new TAPColumn("ID", new DBType(DBDatatype.VARCHAR)); + resultingColumns[1] = new TAPColumn("ra", new DBType(DBDatatype.DOUBLE), "Right ascension", "deg", "pos.eq.ra", null); + resultingColumns[2] = new TAPColumn("deg", new DBType(DBDatatype.DOUBLE), "Declination", "deg", "pos.eq.dec", null); + resultingColumns[3] = new TAPColumn("gmag", new DBType(DBDatatype.DOUBLE), "G magnitude", "mag", "phot.mag;em.opt.B", null); if (!svFile.exists()) svFile.createNewFile(); @@ -217,6 +218,16 @@ public class SVFormatTest { return null; } + @Override + public Collection<String> getGeometries(){ + return null; + } + + @Override + public Collection<FunctionDef> getUDFs(){ + return null; + } + @Override public TAPLog getLogger(){ return null; diff --git a/test/tap/formatter/TextFormatTest.java b/test/tap/formatter/TextFormatTest.java index 959475b608ac2425a9297e0c6f2972723e224719..b763a29cc669f0580784a0c33c2499ceae68b19d 100644 --- a/test/tap/formatter/TextFormatTest.java +++ b/test/tap/formatter/TextFormatTest.java @@ -28,12 +28,13 @@ import tap.file.TAPFileManager; import tap.log.TAPLog; import tap.metadata.TAPColumn; import tap.metadata.TAPMetadata; -import tap.metadata.TAPType; -import tap.metadata.TAPType.TAPDatatype; import tap.parameters.TAPParameters; import testtools.CommandExecute; import testtools.DBTools; import uws.service.UserIdentifier; +import adql.db.DBType; +import adql.db.DBType.DBDatatype; +import adql.db.FunctionDef; /** * <p>Test the TestFormat function {@link TestFormat#writeResult(TableIterator, OutputStream, TAPExecutionReport, Thread)}.</p> @@ -56,10 +57,10 @@ public class TextFormatTest { serviceConn = new ServiceConnectionTest(); resultingColumns = new TAPColumn[4]; - resultingColumns[0] = new TAPColumn("ID", new TAPType(TAPDatatype.VARCHAR)); - resultingColumns[1] = new TAPColumn("ra", new TAPType(TAPDatatype.DOUBLE), "Right ascension", "deg", "pos.eq.ra", null); - resultingColumns[2] = new TAPColumn("deg", new TAPType(TAPDatatype.DOUBLE), "Declination", "deg", "pos.eq.dec", null); - resultingColumns[3] = new TAPColumn("gmag", new TAPType(TAPDatatype.DOUBLE), "G magnitude", "mag", "phot.mag;em.opt.B", null); + resultingColumns[0] = new TAPColumn("ID", new DBType(DBDatatype.VARCHAR)); + resultingColumns[1] = new TAPColumn("ra", new DBType(DBDatatype.DOUBLE), "Right ascension", "deg", "pos.eq.ra", null); + resultingColumns[2] = new TAPColumn("deg", new DBType(DBDatatype.DOUBLE), "Declination", "deg", "pos.eq.dec", null); + resultingColumns[3] = new TAPColumn("gmag", new DBType(DBDatatype.DOUBLE), "G magnitude", "mag", "phot.mag;em.opt.B", null); if (!textFile.exists()) textFile.createNewFile(); @@ -217,6 +218,16 @@ public class TextFormatTest { return null; } + @Override + public Collection<String> getGeometries(){ + return null; + } + + @Override + public Collection<FunctionDef> getUDFs(){ + return null; + } + @Override public TAPLog getLogger(){ return null; diff --git a/test/tap/formatter/VOTableFormatTest.java b/test/tap/formatter/VOTableFormatTest.java index 51e9dc8ab47732d008335527eba3564dd03488cc..5812072dc47999bffa5d98e75886da7b6c893b7f 100644 --- a/test/tap/formatter/VOTableFormatTest.java +++ b/test/tap/formatter/VOTableFormatTest.java @@ -28,13 +28,14 @@ import tap.file.TAPFileManager; import tap.log.TAPLog; import tap.metadata.TAPColumn; import tap.metadata.TAPMetadata; -import tap.metadata.TAPType; -import tap.metadata.TAPType.TAPDatatype; import tap.parameters.TAPParameters; import testtools.CommandExecute; import testtools.DBTools; import uk.ac.starlink.votable.DataFormat; import uws.service.UserIdentifier; +import adql.db.DBType; +import adql.db.DBType.DBDatatype; +import adql.db.FunctionDef; /** * <p>Test the VOTableFormat function {@link VOTableFormat#writeResult(TableIterator, OutputStream, TAPExecutionReport, Thread)}.</p> @@ -57,10 +58,10 @@ public class VOTableFormatTest { serviceConn = new ServiceConnectionTest(); resultingColumns = new TAPColumn[4]; - resultingColumns[0] = new TAPColumn("ID", new TAPType(TAPDatatype.VARCHAR)); - resultingColumns[1] = new TAPColumn("ra", new TAPType(TAPDatatype.DOUBLE), "Right ascension", "deg", "pos.eq.ra", null); - resultingColumns[2] = new TAPColumn("deg", new TAPType(TAPDatatype.DOUBLE), "Declination", "deg", "pos.eq.dec", null); - resultingColumns[3] = new TAPColumn("gmag", new TAPType(TAPDatatype.DOUBLE), "G magnitude", "mag", "phot.mag;em.opt.B", null); + resultingColumns[0] = new TAPColumn("ID", new DBType(DBDatatype.VARCHAR)); + resultingColumns[1] = new TAPColumn("ra", new DBType(DBDatatype.DOUBLE), "Right ascension", "deg", "pos.eq.ra", null); + resultingColumns[2] = new TAPColumn("deg", new DBType(DBDatatype.DOUBLE), "Declination", "deg", "pos.eq.dec", null); + resultingColumns[3] = new TAPColumn("gmag", new DBType(DBDatatype.DOUBLE), "G magnitude", "mag", "phot.mag;em.opt.B", null); if (!votableFile.exists()) votableFile.createNewFile(); @@ -222,6 +223,16 @@ public class VOTableFormatTest { return null; } + @Override + public Collection<String> getGeometries(){ + return null; + } + + @Override + public Collection<FunctionDef> getUDFs(){ + return null; + } + @Override public TAPLog getLogger(){ return null; diff --git a/test/uws/service/UWSUrlTest.java b/test/uws/service/UWSUrlTest.java index 673365076427418810a9b270f20168e44d216636..a61db70f0032176b4f983aa3c915dcbf9be21d0d 100644 --- a/test/uws/service/UWSUrlTest.java +++ b/test/uws/service/UWSUrlTest.java @@ -2,6 +2,7 @@ package uws.service; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.io.BufferedReader; @@ -406,39 +407,53 @@ public class UWSUrlTest { // CASE 1: http://localhost:8080/tapTest/path with url-pattern = /path/* try{ UWSUrl uu = new UWSUrl(requestFromPath2root); - assertEquals(uu.getBaseURI(), "/path"); - }catch(NullPointerException e){ + assertEquals("/path", uu.getBaseURI()); + assertEquals("", uu.getUwsURI()); + assertEquals("http://localhost:8080/tapTest/path/", uu.toString()); + }catch(Exception e){ + e.printStackTrace(System.err); fail("This HTTP request is perfectly correct: " + requestFromPath2root.getRequestURL()); } // CASE 2: http://localhost:8080/tapTest/path/async with url-pattern = /path/* try{ UWSUrl uu = new UWSUrl(requestFromPath2async); - assertEquals(uu.getBaseURI(), "/path"); - }catch(NullPointerException e){ + assertEquals("/path", uu.getBaseURI()); + assertEquals("/async", uu.getUwsURI()); + assertEquals("http://localhost:8080/tapTest/path/async", uu.toString()); + }catch(Exception e){ + e.printStackTrace(System.err); fail("This HTTP request is perfectly correct: " + requestFromPath2async.getRequestURL()); } - // CASE 3: http://localhost:8080/tapTest/async with url-pattern = /* + // CASE 3: http://localhost:8080/tapTest with url-pattern = /* try{ UWSUrl uu = new UWSUrl(requestFromRoot2root); - assertEquals(uu.getBaseURI(), ""); - }catch(NullPointerException e){ + assertEquals("", uu.getBaseURI()); + assertEquals("", uu.getUwsURI()); + assertEquals("http://localhost:8080/tapTest/", uu.toString()); + }catch(Exception e){ + e.printStackTrace(System.err); fail("This HTTP request is perfectly correct: " + requestFromRoot2root.getRequestURL()); } // CASE 4: http://localhost:8080/tapTest/async with url-pattern = /* try{ UWSUrl uu = new UWSUrl(requestFromRoot2async); - assertEquals(uu.getBaseURI(), ""); - }catch(NullPointerException e){ + assertEquals("", uu.getBaseURI()); + assertEquals("/async", uu.getUwsURI()); + assertEquals("http://localhost:8080/tapTest/async", uu.toString()); + }catch(Exception e){ + e.printStackTrace(System.err); fail("This HTTP request is perfectly correct: " + requestFromRoot2async.getRequestURL()); } // CASE 5: http://localhost:8080/tapTest/path/async with url-pattern = /path/* try{ new UWSUrl(requestWithServletPathNull); - }catch(NullPointerException e){ + fail("RequestURL with no servlet path: this test should have failed!"); + }catch(Exception e){ + assertTrue(e instanceof NullPointerException); assertEquals(e.getMessage(), "The extracted base UWS URI is NULL!"); } } @@ -449,18 +464,20 @@ public class UWSUrlTest { try{ UWSUrl uu = new UWSUrl(requestFromPath2root); uu.load(requestFromPath2root); - assertEquals(uu.getUwsURI(), ""); - assertEquals(uu.jobSummary("async", "123456A").toString(), "http://localhost:8080/tapTest/path/async/123456A"); - }catch(NullPointerException e){ + assertEquals("", uu.getUwsURI()); + assertEquals("http://localhost:8080/tapTest/path/async/123456A", uu.jobSummary("async", "123456A").toString()); + }catch(Exception e){ + e.printStackTrace(System.err); fail("This HTTP request is perfectly correct: " + requestFromPath2root.getRequestURL()); } // CASE 1b: Idem while loading http://localhost:8080/tapTest/path/async try{ UWSUrl uu = new UWSUrl(requestFromPath2root); uu.load(requestFromPath2async); - assertEquals(uu.getUwsURI(), "/async"); - assertEquals(uu.jobSummary("async", "123456A").toString(), "http://localhost:8080/tapTest/path/async/123456A"); - }catch(NullPointerException e){ + assertEquals("/async", uu.getUwsURI()); + assertEquals("http://localhost:8080/tapTest/path/async/123456A", uu.jobSummary("async", "123456A").toString()); + }catch(Exception e){ + e.printStackTrace(System.err); fail("This HTTP request is perfectly correct: " + requestFromPath2async.getRequestURL()); } @@ -468,9 +485,10 @@ public class UWSUrlTest { try{ UWSUrl uu = new UWSUrl(requestFromPath2async); uu.load(requestFromPath2async); - assertEquals(uu.getUwsURI(), "/async"); - assertEquals(uu.jobSummary("async", "123456A").toString(), "http://localhost:8080/tapTest/path/async/123456A"); - }catch(NullPointerException e){ + assertEquals("/async", uu.getUwsURI()); + assertEquals("http://localhost:8080/tapTest/path/async/123456A", uu.jobSummary("async", "123456A").toString()); + }catch(Exception e){ + e.printStackTrace(System.err); fail("This HTTP request is perfectly correct: " + requestFromPath2async.getRequestURL()); } @@ -478,9 +496,10 @@ public class UWSUrlTest { try{ UWSUrl uu = new UWSUrl(requestFromPath2async); uu.load(requestFromPath2root); - assertEquals(uu.getUwsURI(), ""); - assertEquals(uu.jobSummary("async", "123456A").toString(), "http://localhost:8080/tapTest/path/async/123456A"); - }catch(NullPointerException e){ + assertEquals("", uu.getUwsURI()); + assertEquals("http://localhost:8080/tapTest/path/async/123456A", uu.jobSummary("async", "123456A").toString()); + }catch(Exception e){ + e.printStackTrace(System.err); fail("This HTTP request is perfectly correct: " + requestFromPath2root.getRequestURL()); } @@ -488,8 +507,8 @@ public class UWSUrlTest { try{ UWSUrl uu = new UWSUrl(requestFromRoot2root); uu.load(requestFromRoot2root); - assertEquals(uu.getUwsURI(), ""); - assertEquals(uu.jobSummary("async", "123456A").toString(), "http://localhost:8080/tapTest/async/123456A"); + assertEquals("", uu.getUwsURI()); + assertEquals("http://localhost:8080/tapTest/async/123456A", uu.jobSummary("async", "123456A").toString()); }catch(NullPointerException e){ fail("This HTTP request is perfectly correct: " + requestFromRoot2root.getRequestURL()); } @@ -498,9 +517,10 @@ public class UWSUrlTest { try{ UWSUrl uu = new UWSUrl(requestFromRoot2root); uu.load(requestFromRoot2async); - assertEquals(uu.getUwsURI(), "/async"); - assertEquals(uu.jobSummary("async", "123456A").toString(), "http://localhost:8080/tapTest/async/123456A"); - }catch(NullPointerException e){ + assertEquals("/async", uu.getUwsURI()); + assertEquals("http://localhost:8080/tapTest/async/123456A", uu.jobSummary("async", "123456A").toString()); + }catch(Exception e){ + e.printStackTrace(System.err); fail("This HTTP request is perfectly correct: " + requestFromRoot2async.getRequestURL()); } @@ -508,9 +528,10 @@ public class UWSUrlTest { try{ UWSUrl uu = new UWSUrl(requestFromRoot2async); uu.load(requestFromRoot2async); - assertEquals(uu.getUwsURI(), "/async"); - assertEquals(uu.jobSummary("async", "123456A").toString(), "http://localhost:8080/tapTest/async/123456A"); - }catch(NullPointerException e){ + assertEquals("/async", uu.getUwsURI()); + assertEquals("http://localhost:8080/tapTest/async/123456A", uu.jobSummary("async", "123456A").toString()); + }catch(Exception e){ + e.printStackTrace(System.err); fail("This HTTP request is perfectly correct: " + requestFromRoot2async.getRequestURL()); } @@ -518,9 +539,10 @@ public class UWSUrlTest { try{ UWSUrl uu = new UWSUrl(requestFromRoot2async); uu.load(requestFromRoot2root); - assertEquals(uu.getUwsURI(), ""); - assertEquals(uu.jobSummary("async", "123456A").toString(), "http://localhost:8080/tapTest/async/123456A"); - }catch(NullPointerException e){ + assertEquals("", uu.getUwsURI()); + assertEquals("http://localhost:8080/tapTest/async/123456A", uu.jobSummary("async", "123456A").toString()); + }catch(Exception e){ + e.printStackTrace(System.err); fail("This HTTP request is perfectly correct: " + requestFromRoot2root.getRequestURL()); } @@ -529,7 +551,8 @@ public class UWSUrlTest { UWSUrl uu = new UWSUrl(requestFromRoot2async); uu.load(requestFromPath2async); assertFalse(uu.getUwsURI().equals("")); - }catch(NullPointerException e){ + }catch(Exception e){ + e.printStackTrace(System.err); fail("This HTTP request is perfectly correct: " + requestFromRoot2root.getRequestURL()); } }