From cb6eff4e35a4efcc01fa45ebf03d007161ee0dd7 Mon Sep 17 00:00:00 2001 From: gmantele <gmantele@ari.uni-heidelberg.de> Date: Thu, 9 Apr 2015 12:54:41 +0200 Subject: [PATCH] [TAP] Add a creation function for ADQLParser in the TAP factory. --- src/tap/ADQLExecutor.java | 23 +++++++------ src/tap/AbstractTAPFactory.java | 13 +++++++- src/tap/TAPFactory.java | 38 +++++++++++++++++++++- src/tap/config/tap_configuration_file.html | 8 +++-- src/tap/config/tap_full.properties | 9 +++-- 5 files changed, 74 insertions(+), 17 deletions(-) diff --git a/src/tap/ADQLExecutor.java b/src/tap/ADQLExecutor.java index a0ffd3e..f467013 100644 --- a/src/tap/ADQLExecutor.java +++ b/src/tap/ADQLExecutor.java @@ -44,7 +44,6 @@ import uws.service.log.UWSLog.LogLevel; import adql.parser.ADQLParser; import adql.parser.ADQLQueryFactory; import adql.parser.ParseException; -import adql.parser.QueryChecker; import adql.query.ADQLQuery; /** @@ -508,18 +507,22 @@ public class ADQLExecutor { // Log the start of the parsing: logger.logTAP(LogLevel.INFO, report, "PARSING", "Parsing ADQL: " + tapParams.getQuery().replaceAll("(\t|\r?\n)+", " "), null); - // Get the ADQL factory: - ADQLQueryFactory queryFactory = service.getFactory().createQueryFactory(); + // Create the ADQL parser: + ADQLParser parser = service.getFactory().createADQLParser(); + if (parser == null){ + logger.logTAP(LogLevel.WARNING, null, "PARSING", "No ADQL parser returned by the TAPFactory! The default implementation is used instead.", null); + parser = new ADQLParser(); + } + + // Set the ADQL factory: + if (parser.getQueryFactory() == null || parser.getQueryFactory().getClass() == ADQLQueryFactory.class) + parser.setQueryFactory(service.getFactory().createQueryFactory()); - // Get the query checker: - QueryChecker queryChecker = service.getFactory().createQueryChecker(uploadSchema); + // Set the query checker: + if (parser.getQueryChecker() == null) + parser.setQueryChecker(service.getFactory().createQueryChecker(uploadSchema)); // Parse the ADQL query: - ADQLParser parser; - if (queryFactory == null) - parser = new ADQLParser(queryChecker); - else - parser = new ADQLParser(queryChecker, queryFactory); 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 7642a52..74ac601 100644 --- a/src/tap/AbstractTAPFactory.java +++ b/src/tap/AbstractTAPFactory.java @@ -43,6 +43,7 @@ import uws.service.UWSService; import uws.service.backup.UWSBackupManager; import uws.service.error.ServiceErrorWriter; import adql.db.DBChecker; +import adql.parser.ADQLParser; import adql.parser.ADQLQueryFactory; import adql.parser.ParseException; import adql.parser.QueryChecker; @@ -53,7 +54,7 @@ import adql.query.ADQLQuery; * Only the functions related with the database connection stay abstract. * * @author Grégory Mantelet (CDS;ARI) - * @version 2.0 (02/2015) + * @version 2.0 (04/2015) */ public abstract class AbstractTAPFactory extends TAPFactory { @@ -112,6 +113,16 @@ public abstract class AbstractTAPFactory extends TAPFactory { return new ADQLExecutor(service); } + /** + * <p><i>Note: + * This function should be extended if you want to customize the ADQL grammar. + * </i></p> + */ + @Override + public ADQLParser createADQLParser() throws TAPException{ + return new ADQLParser(); + } + /** * <p><i>Note: * This function should be extended if you have customized the creation of any diff --git a/src/tap/TAPFactory.java b/src/tap/TAPFactory.java index bea7ade..19624ff 100644 --- a/src/tap/TAPFactory.java +++ b/src/tap/TAPFactory.java @@ -42,6 +42,7 @@ import uws.service.backup.UWSBackupManager; import uws.service.error.ServiceErrorWriter; import uws.service.file.UWSFileManager; import uws.service.request.RequestParser; +import adql.parser.ADQLParser; import adql.parser.ADQLQueryFactory; import adql.parser.QueryChecker; import adql.query.ADQLQuery; @@ -56,11 +57,13 @@ import adql.query.ADQLQuery; * <li>whether and how UWS/asynchronous jobs must be backuped and restored? <i>({@link UWSBackupManager})</i></li> * <li>how to create asynchronous jobs? <i>({@link TAPJob})</i></li> * <li>whether and how tables must be updated? <i>({@link Uploader})</i></li> + * <li>how to execute an ADQL query? <i>({@link ADQLExecutor})</i> + * <li>how to parser an ADQL query? <i>({@link ADQLParser})</i></li> * <li>how to check ADQL queries? <i>({@link QueryChecker})</i></li> * </ul> * * @author Grégory Mantelet (CDS;ARI) - * @version 2.0 (02/2015) + * @version 2.0 (04/2015) */ public abstract class TAPFactory implements UWSFactory { @@ -177,9 +180,37 @@ public abstract class TAPFactory implements UWSFactory { */ public abstract ADQLExecutor createADQLExecutor() throws TAPException; + /** + * <p>Create a parser of ADQL query.</p> + * + * <p><i>Warning: + * This parser can be created with a query factory and/or a query checker. + * {@link #createQueryFactory()} will be used only if the default query factory (or none) is set + * in the ADQL parser returned by this function. + * Idem for {@link #createQueryChecker(TAPSchema)}: it will used only if no query checker is set + * in the returned ADQL parser. + * </i></p> + * + * <p><i>Note: + * A default implementation is provided by {@link AbstractTAPFactory}. + * </i></p> + * + * @return An ADQL query parser. + * + * @throws TAPException If any error occurs while creating an ADQL parser. + * + * @since 2.0 + */ + public abstract ADQLParser createADQLParser() throws TAPException; + /** * <p>Create a factory able to build every part of an {@link ADQLQuery} object.</p> * + * <p><i>Warning: + * This function is used only if the default query factory (or none) is set in the ADQL parser + * returned by {@link #createADQLParser()}. + * </i></p> + * * <p><i>Note: * A default implementation is provided by {@link AbstractTAPFactory} * </i></p> @@ -195,6 +226,11 @@ public abstract class TAPFactory implements UWSFactory { * That's to say, it checks whether the tables and columns used in the query really exist * in the database.</p> * + * <p><i>Warning: + * This function is used only if no query checker is set in the ADQL parser + * returned by {@link #createADQLParser()}. + * </i></p> + * * <p><i>Note: * A default implementation is provided by {@link AbstractTAPFactory} * </i></p> diff --git a/src/tap/config/tap_configuration_file.html b/src/tap/config/tap_configuration_file.html index 381d84e..57c6967 100644 --- a/src/tap/config/tap_configuration_file.html +++ b/src/tap/config/tap_configuration_file.html @@ -695,8 +695,12 @@ <td> <p>Class to use in replacement of the default TAPFactory.</p> <p> - This property must be a class name (given between {...}). It must reference an extension of the abstract TAPFactory. - This extension must have at least one constructor with exactly one parameter of type ServiceConnection. + This property must be a class name (given between {...}). It must reference an implementation of TAPFactory. + This implementation must have at least one constructor with exactly one parameter of type ServiceConnection. + </p> + <p> + It is recommended to extend an existing implementation such as: + tap.AbstractTAPFactory or tap.config.ConfigurableTAPFactory. </p> <p><em>By default, the default TAPFactory (tap.config.ConfigurableTAPFactory) is used and may use all properties related to the backup management, the database access and the ADQL translation.</em></p> diff --git a/src/tap/config/tap_full.properties b/src/tap/config/tap_full.properties index 04b6771..42d6144 100644 --- a/src/tap/config/tap_full.properties +++ b/src/tap/config/tap_full.properties @@ -2,7 +2,7 @@ # FULL TAP CONFIGURATION FILE # # # # TAP Version: 2.0 # -# Date: 8 April 2015 # +# Date: 9 April 2015 # # Author: Gregory Mantelet (ARI) # # # ########################################################## @@ -519,8 +519,11 @@ additional_resources = # [OPTIONAL] # Class to use in replacement of the default TAPFactory. # -# This property must be a class name (given between {...}). It must reference an extension of the abstract TAPFactory. -# This extension must have at least one constructor with exactly one parameter of type ServiceConnection. +# This property must be a class name (given between {...}). It must reference an implementation of TAPFactory. +# This implementation must have at least one constructor with exactly one parameter of type ServiceConnection. +# +# It is recommended to extend an existing implementation such as: +# tap.AbstractTAPFactory or tap.config.ConfigurableTAPFactory. # # By default, the default TAPFactory (tap.config.ConfigurableTAPFactory) is used and may use all properties related to the backup management, # the database access and the ADQL translation. -- GitLab