diff --git a/ProjectHome.md b/ProjectHome.md new file mode 100644 index 0000000..bdc3990 --- /dev/null +++ b/ProjectHome.md @@ -0,0 +1,10 @@ +This library makes it easy to implement a Visualization data source so that you can easily chart or visualize your data from any of your data stores. +The library implements the [Google Visualization API wire protocol](http://code.google.com/apis/visualization/documentation/dev/implementing_data_source.html) and [query language](http://code.google.com/apis/visualization/documentation/querylanguage.html). You therefore need write only the code required to make your data available to the library in the form of a data table. This task is made easier by the provision of abstract classes and helper functions. + +For developer documentation see the [Data Source Library Developer's Guide](http://code.google.com/apis/visualization/documentation/dev/dsl_about.html). + +For information on dependencies and set-up see [Installing the Data Source Java Library](http://code.google.com/apis/visualization/documentation/dev/dsl_install.html) + +To get, or browse, the source code click the Source tab. + +## [Download the latest stable release version 1.1.1](http://google-visualization-java.googlecode.com/files/visualization-datasource-1.1.1.zip) ## diff --git a/ReleaseNotes.md b/ReleaseNotes.md new file mode 100644 index 0000000..237ac4e --- /dev/null +++ b/ReleaseNotes.md @@ -0,0 +1,25 @@ +# Version 1.1.1 # + * Move from google-collect-1.0 to guava-[r07](https://code.google.com/p/google-visualization-java/source/detail?r=07). + * Changed Json output to be valid Json format: Added quotation marks around all keys and string values. Date values are formated as"Date(2011,1,1)". Note: for jsonp dates remain as they were before and the Date object is returned in the json string, e.g., new Date(2011,1,1). + * Added setCell method to DataTable class. + * Added support for SKIPPING clause in the query language. + * Added support for MODULO operator in the query language. + * Fixed bug: Response content type for JSON/P is not valid. + * Fixed bug: java.util.TreeMap initialization in QueryEngine causes compilation error. + * Fixed bug: Where clause with column names that contain spaces does not work for SQL datasources ([Issue 16](https://code.google.com/p/google-visualization-java/issues/detail?id=16)). + * Fixed bug: SQL data source dates are shifted ([Issue 11](https://code.google.com/p/google-visualization-java/issues/detail?id=11)). + * Changed initialization of Timestamp in SQLDataSourceHelperTest. + * Add a message to the IllegalArgumentException thrown when a DateValue/DateTimeValue/TimeOfDayValue is created with a GregorianCalendar that is not GMT. + * Externalized error messages. + * Removed unnecessary servlet from web.xml. + + +# Version 1.0.2 # + * Added maven build (pom.xml). + * Starting with this version this library is available in a maven web repository. + * Added tests. + * Added support for LIKE operator in the query language. + * Fixed bug: Export to HTML double escapes   ([Issue 2](https://code.google.com/p/google-visualization-java/issues/detail?id=2)). + * Fixed bug: Format and label clauses do not work for queries that contain scalar functions ([Issue 3](https://code.google.com/p/google-visualization-java/issues/detail?id=3)). + * Fixed bug: "is null" in the where clause of a query does not work for SQL datasources ([Issue 4](https://code.google.com/p/google-visualization-java/issues/detail?id=4)). + * Fixed bug: CSV output does not escape non text values with commas ([Issue 5](https://code.google.com/p/google-visualization-java/issues/detail?id=5)). \ No newline at end of file diff --git a/ReleaseNotes.txt b/ReleaseNotes.txt deleted file mode 100644 index 923b310..0000000 --- a/ReleaseNotes.txt +++ /dev/null @@ -1,39 +0,0 @@ -Version 1.1.2 ------------------------------------------ -- Fix security threat of swf injection in jsonp. - -Version 1.1.1 ------------------------------------------ -- Move from google-collect-1.0 to guava-r07. -- Changed Json output to be valid Json format: Added quotation marks around - all keys and string values. Date values are formated as"Date(2011,1,1)". - Note: for jsonp dates remain as they were before and the Date object is - returned in the json string, e.g., new Date(2011,1,1). -- Added setCell method to DataTable class. -- Added support for SKIPPING clause in the query language. -- Added support for MODULO operator in the query language. -- Fixed bug: Response content type for JSON/P is not valid. -- Fixed bug: java.util.TreeMap initialization in QueryEngine causes - compilation error. -- Fixed bug: Where clause with column names that contain spaces does not work - for SQL datasources (Issue 16). -- Fixed bug: SQL data source dates are shifted (Issue 11). -- Changed initialization of Timestamp in SQLDataSourceHelperTest. -- Add a message to the IllegalArgumentException thrown when a - DateValue/DateTimeValue/TimeOfDayValue is created with a GregorianCalendar - that is not GMT. -- Externalized error messages. -- Removed unnecessary servlet from web.xml. - -Version 1.0.2 ------------------------------------------ -- Added maven build (pom.xml). -- Starting with this version this library is available in a maven web repository. -- Added tests. -- Added support for LIKE operator in the query language. -- Fixed bug: Export to HTML double escapes   (Issue 2). -- Fixed bug: Format and label clauses do not work for queries that contain - scalar functions (Issue 3). -- Fixed bug: "is null" in the where clause of a query does not work for SQL - datasources (Issue 4). -- Fixed bug: CSV output does not escape non text values with commas (Issue 5). diff --git a/build-src/build.properties b/build-src/build.properties deleted file mode 100644 index 80f49e1..0000000 --- a/build-src/build.properties +++ /dev/null @@ -1,19 +0,0 @@ -# Pointers to external library dependencies. - -# EDIT THIS to point to Sun's Servlet API jar provided with your servlet container. -# For example, if you use tomcat you will find it under /lib/servlet-api.jar -servlet-api.jar=../lib/servlet-api.jar - -# You may want to edit the following dependencies if you wish to use your own copy of them. -guava.jar=../lib/guava-r07.jar -icu4j.jar=../lib/icu4j-4_0_1.jar -jakarta-commons-lang.jar=../lib/commons-lang-2.4.jar -opencsv.jar=../lib/opencsv-1.8.jar -jakarta-commons-logging.jar=../lib/commons-logging-1.1.1.jar - -# This dependency is only needed for compilation, it is not needed in runtime. -javacc.zip=../lib/javacc.jar - -# The following dependencies are only needed for running the tests. -junit.jar=../lib/junit-4.6.jar -easymock.jar=../lib/easymock-2.5.jar diff --git a/build-src/build.xml b/build-src/build.xml deleted file mode 100644 index 0fd3af0..0000000 --- a/build-src/build.xml +++ /dev/null @@ -1,135 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/src/html/all_examples.html b/examples/src/html/all_examples.html deleted file mode 100755 index 642df80..0000000 --- a/examples/src/html/all_examples.html +++ /dev/null @@ -1,98 +0,0 @@ - - - - All Examples - - - - - -

Hello! Data Source!

- A pie chart to show the population of a group of animals. - The data is taken from the simple data source. -
- Use this toolbar to get the data in CSV/HTML. -
- -

CSV Data Source

- An organization chart. - The data is taken from the csv data source. -
- -

Advanced Data Source

- A bar chart to show planetary masses. - The data is taken from the advanced data source. -
- - - diff --git a/examples/src/html/csv_example.csv b/examples/src/html/csv_example.csv deleted file mode 100644 index 89ee3bb..0000000 --- a/examples/src/html/csv_example.csv +++ /dev/null @@ -1,6 +0,0 @@ -Employee,Manager -Roger,John -Robert,John -Jane,Roger -Jack,Jane -Bob,Jane diff --git a/examples/src/html/getting_started.html b/examples/src/html/getting_started.html deleted file mode 100755 index a3abf5c..0000000 --- a/examples/src/html/getting_started.html +++ /dev/null @@ -1,45 +0,0 @@ - - - - Getting Started Example - - - - - -

Hello! Data Source!

- A table chart that shows data taken from the simple data source. - -
- - diff --git a/examples/src/html/web.xml b/examples/src/html/web.xml deleted file mode 100644 index 5dfe414..0000000 --- a/examples/src/html/web.xml +++ /dev/null @@ -1,173 +0,0 @@ - - - - - - - - - - My Web Application - - This is version X.X of an application to perform - a wild and wonderful task, based on servlets and - JSP pages. It was written by Dave Developer - (dave@mycompany.com), who should be contacted for - more information. - - - - - - - webmaster - myaddress@mycompany.com - - The EMAIL address of the administrator to whom questions - and comments about this application should be addressed. - - - - - - - - controller - - This servlet plays the "controller" role in the MVC architecture - used in this application. It is generally mapped to the ".do" - filename extension with a servlet-mapping element, and all form - submits in the app will be submitted to a request URI like - "saveCustomer.do", which will therefore be mapped to this servlet. - - The initialization parameter namess for this servlet are the - "servlet path" that will be received by this servlet (after the - filename extension is removed). The corresponding value is the - name of the action class that will be used to process this request. - - com.mycompany.mypackage.ControllerServlet - - listOrders - com.mycompany.myactions.ListOrdersAction - - - saveCustomer - com.mycompany.myactions.SaveCustomerAction - - - 5 - - - - My Servlet - My servlet description. - SimpleExampleServlet - - - - CSV Example - CsvDataSourceServlet - CsvDataSourceServlet - - - - AdvancedExampleServlet2 - AdvancedExampleServlet2 - AdvancedExampleServlet2 - - - - - - controller - *.do - - - - graph - /graph - - - - - My Servlet - /simpleexample - - - - CSV Example - /csv - - - - AdvancedExampleServlet2 - /advanced - - - - - - 30 - - - - diff --git a/examples/src/java/AdvancedExampleServlet.java b/examples/src/java/AdvancedExampleServlet.java deleted file mode 100755 index e05d2ea..0000000 --- a/examples/src/java/AdvancedExampleServlet.java +++ /dev/null @@ -1,270 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import com.google.common.collect.Lists; -import com.google.visualization.datasource.Capabilities; -import com.google.visualization.datasource.DataSourceServlet; -import com.google.visualization.datasource.base.TypeMismatchException; -import com.google.visualization.datasource.datatable.ColumnDescription; -import com.google.visualization.datasource.datatable.DataTable; -import com.google.visualization.datasource.datatable.TableRow; -import com.google.visualization.datasource.datatable.value.ValueType; -import com.google.visualization.datasource.query.AbstractColumn; -import com.google.visualization.datasource.query.Query; - -import java.util.List; -import java.util.Map; -import java.util.TreeMap; - -import javax.servlet.http.HttpServletRequest; - - -/** - * An example servlet for serving a data table from a data source that has query capabilities. - * This data source has native 'select' capability. - * Other parts of the query are handled by the completion query. - * - * The data source can return two different data tables, depending on the - * tableId parameter. By default it returns the 'animals' data table, unless the - * tableId parameter is set to 'planets'. - */ -public class AdvancedExampleServlet extends DataSourceServlet { - - /** - * A map of animal names to links in wikipedia describing them. - */ - private static Map animalLinksByName = new TreeMap(); - static { - animalLinksByName.put("Fish", "http://en.wikipedia.org/wiki/Fish"); - animalLinksByName.put("Dog", "http://en.wikipedia.org/wiki/Dog"); - animalLinksByName.put("Cat", "http://en.wikipedia.org/wiki/Cat"); - animalLinksByName.put("Cow", "http://en.wikipedia.org/wiki/Cow"); - animalLinksByName.put("Tiger", "http://en.wikipedia.org/wiki/Tiger"); - animalLinksByName.put("Elephant", "http://en.wikipedia.org/wiki/Elephant"); - animalLinksByName.put("Goat", "http://en.wikipedia.org/wiki/Goat"); - animalLinksByName.put("Aye-aye", "http://en.wikipedia.org/wiki/Aye-aye"); - animalLinksByName.put("Sloth", "http://en.wikipedia.org/wiki/Sloth"); - } - - private static final String ANIMAL_COLUMN = "animal"; - private static final String ARTICLE_COLUMN = "article"; - - private static final ColumnDescription[] ANIMAL_TABLE_COLUMNS = - new ColumnDescription[] { - new ColumnDescription(ANIMAL_COLUMN, ValueType.TEXT, "Animal"), - new ColumnDescription(ARTICLE_COLUMN, ValueType.TEXT, "Link to wikipedia") - }; - - /** - * An enum of planets. Each planet has a name, surface gravity and - * number of moons. - */ - private enum Planet { - JUPITER (317.8, 11.2, 63), - SATURN (95.2, 9.4, 60), - URANUS (14.5, 4, 27), - NEPTUNE (17.2, 3.9, 13); - - private final double mass; - private final double surfaceGravity; - private final int numberOfMoons; - - private Planet(double mass, double surfaceGravity, int numberOfMoons) { - this.mass = mass; - this.surfaceGravity = surfaceGravity; - this.numberOfMoons = numberOfMoons; - } - - public double getMass() { - return mass; - } - - public double getSurfaceGravity() { - return surfaceGravity; - } - - public int getNumberOfMoons() { - return numberOfMoons; - } - } - - private static final String PLANET_COLUMN = "planet"; - private static final String MASS_COLUMN = "mass"; - private static final String GRAVITY_COLUMN = "gravity"; - private static final String MOONS_COLUMN = "moons"; - - private static final ColumnDescription[] planetTableColumns = - new ColumnDescription[] { - new ColumnDescription(PLANET_COLUMN, ValueType.TEXT, "Planet"), - new ColumnDescription(MASS_COLUMN, ValueType.NUMBER, "Mass"), - new ColumnDescription(GRAVITY_COLUMN, ValueType.NUMBER, "Surface Gravity"), - new ColumnDescription(MOONS_COLUMN, ValueType.NUMBER, "Number of Moons") - }; - - /** - * Specifies that this data source can select and return specified columns instead of passing - * all the columns and leaving the library's query engine to select the columns. - * If the number of columns is large, and a query specifies only a few of them, this can - * significantly improve performance. - * - * - * @return The "Select" capability in this case. - */ - @Override - public Capabilities getCapabilities() { - return Capabilities.SELECT; - } - - /** - * NOTE: By default, this function returns true, which means that cross - * domain requests are rejected. - * This check is disabled here so that this example can be used directly from the - * address bar of the browser. Bear in mind that this exposes your - * data source to xsrf attacks. - * If the only use of the data source url is from your application, - * that runs on the same domain, it is better to remain in restricted mode. - */ - @Override - protected boolean isRestrictedAccessMode() { - return false; - } - - /** - * Returns true if the given column name is requested in the given query. - * If the query is empty, all columnNames returns true. - * - * @param query The given query. - * @param columnName The requested column name. - * - * @return True if the given column name is requested in the given query. - */ - private boolean isColumnRequested(Query query, String columnName) { - - // If the query is empty returns true, as if all columns were specified. - if (query.isEmpty()) { - return true; - } - - // Returns true if the requested column id was specified (not case sensitive). - List columns = query.getSelection().getColumns(); - for (AbstractColumn column : columns) { - if (column.getId().equalsIgnoreCase(columnName)) { - return true; - } - } - - return false; - } - - /** - * Generates a data table - according to the provided tableId url parameter. - * - * @param query The query to operate on the underlying data. - * @param req The HttpServeltRequest. - * - * @return The generated data table. - */ - @Override - public DataTable generateDataTable(Query query, HttpServletRequest req) - throws TypeMismatchException { - String tableID = req.getParameter("tableId"); - if ((tableID != null) && (tableID.equalsIgnoreCase("planets"))) { - return generatePlanetsTable(query); - } - return generateAnimalsTable(query); - } - - /** - * Returns an animals data table. The table contains a list of animals and - * links to wikipedia pages. - * - * @param query The selection query. - * - * @return A data table of animals. - */ - private DataTable generateAnimalsTable(Query query) throws TypeMismatchException { - DataTable data = new DataTable(); - List requiredColumns = getRequiredColumns(query, - ANIMAL_TABLE_COLUMNS); - data.addColumns(requiredColumns); - - // Populate the data table - for (String key : animalLinksByName.keySet()) { - TableRow row = new TableRow(); - for (ColumnDescription selectionColumn : requiredColumns) { - String columnName = selectionColumn.getId(); - if (columnName.equals(ANIMAL_COLUMN)) { - row.addCell(key); - } else if (columnName.equals(ARTICLE_COLUMN)) { - row.addCell(animalLinksByName.get(key)); - } - } - data.addRow(row); - } - return data; - } - - /** - * Returns the planets data table. - * - * @param query The selection query. - * - * @return planets data table. - */ - private DataTable generatePlanetsTable(Query query) throws TypeMismatchException { - DataTable data = new DataTable(); - List requiredColumns = getRequiredColumns( - query, planetTableColumns); - data.addColumns(requiredColumns); - - // Populate the planets data table - for (Planet planet : Planet.values()) { - TableRow row = new TableRow(); - for (ColumnDescription selectionColumn : requiredColumns) { - String columnName = selectionColumn.getId(); - if (columnName.equals(PLANET_COLUMN)) { - row.addCell(planet.name()); - } else if (columnName.equals(MASS_COLUMN)) { - row.addCell(planet.getMass()); - } else if (columnName.equals(GRAVITY_COLUMN)) { - row.addCell(planet.getSurfaceGravity()); - } else if (columnName.equals(MOONS_COLUMN)) { - row.addCell(planet.getNumberOfMoons()); - } - } - data.addRow(row); - } - return data; - } - - /** - * Returns a list of required columns based on the query and the actual - * columns. - * - * @param query The user selection query. - * @param availableColumns The list of possible columns. - * - * @return A List of required columns for the requested data table. - */ - private List getRequiredColumns(Query query, - ColumnDescription[] availableColumns) { - List requiredColumns = Lists.newArrayList(); - for (ColumnDescription column : availableColumns) { - if (isColumnRequested(query, column.getId())) { - requiredColumns.add(column); - } - } - return requiredColumns; - } -} diff --git a/examples/src/java/AdvancedExampleServlet2.java b/examples/src/java/AdvancedExampleServlet2.java deleted file mode 100755 index 0ea8b07..0000000 --- a/examples/src/java/AdvancedExampleServlet2.java +++ /dev/null @@ -1,309 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import com.google.common.collect.Lists; -import com.google.visualization.datasource.Capabilities; -import com.google.visualization.datasource.DataSourceHelper; -import com.google.visualization.datasource.DataSourceRequest; -import com.google.visualization.datasource.QueryPair; -import com.google.visualization.datasource.base.DataSourceException; -import com.google.visualization.datasource.base.ReasonType; -import com.google.visualization.datasource.base.ResponseStatus; -import com.google.visualization.datasource.base.StatusType; -import com.google.visualization.datasource.base.TypeMismatchException; -import com.google.visualization.datasource.datatable.ColumnDescription; -import com.google.visualization.datasource.datatable.DataTable; -import com.google.visualization.datasource.datatable.TableRow; -import com.google.visualization.datasource.datatable.value.ValueType; -import com.google.visualization.datasource.query.AbstractColumn; -import com.google.visualization.datasource.query.Query; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.io.IOException; -import java.util.List; -import java.util.Map; -import java.util.TreeMap; - -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - - -/** - * A demo servlet for serving a data table from a data source that has query capabilities. - * This data source has a native 'select' capability. - * Other parts of the query are handled by the completion query. - * - * The data source can return two different data tables, depending on the - * tableId parameter. By default the data source returns the 'animals' data table, unless the - * tableId parameter is set to 'planets' in which case the data source returns the 'planets' data - * table. - * - * For the sake of a complete example this servlet extends HttpServlet. - * DataSourceServlet is an abstract class that provides a template behavior for - * serving data source requests. Consider extending DataSourceServlet for - * easier implementation. - * - * @see com.google.visualization.datasource.DataSourceServlet - * @see com.google.visualization.datasource.example.AdvancedExampleServlet - * - * @author Eran W. - */ -public class AdvancedExampleServlet2 extends HttpServlet { - - /** - * The log used throughout the data source library. - */ - private static final Log log = LogFactory.getLog(AdvancedExampleServlet2.class.getName()); - - /** - * A Map of animal names to link in wikipedia describing them. - */ - private static Map animalLinksByName = new TreeMap(); - static { - animalLinksByName.put("Fish", "http://en.wikipedia.org/wiki/Fish"); - animalLinksByName.put("Dog", "http://en.wikipedia.org/wiki/Dog"); - animalLinksByName.put("Cat", "http://en.wikipedia.org/wiki/Cat"); - animalLinksByName.put("Cow", "http://en.wikipedia.org/wiki/Cow"); - animalLinksByName.put("Tiger", "http://en.wikipedia.org/wiki/Tiger"); - animalLinksByName.put("Elephant", "http://en.wikipedia.org/wiki/Elephant"); - animalLinksByName.put("Goat", "http://en.wikipedia.org/wiki/Goat"); - animalLinksByName.put("Aye-aye", "http://en.wikipedia.org/wiki/Aye-aye"); - animalLinksByName.put("Sloth", "http://en.wikipedia.org/wiki/Sloth"); - } - - private static final String ANIMAL_COLUMN = "animal"; - private static final String ARTICLE_COLUMN = "article"; - - private static final ColumnDescription[] ANIMAL_TABLE_COLUMNS = - new ColumnDescription[] { - new ColumnDescription(ANIMAL_COLUMN, ValueType.TEXT, "Animal"), - new ColumnDescription(ARTICLE_COLUMN, ValueType.TEXT, "Link to wikipedia") - }; - - /** - * An enum of planets. Each planet has a name, surface gravity and - * number of moons. - */ - private enum Planet { - JUPITER (317.8, 11.2, 63), - SATURN (95.2, 9.4, 60), - URANUS (14.5, 4, 27), - NEPTUNE (17.2, 3.9, 13); - - private final double mass; - private final double surfaceGravity; - private final int numberOfMoons; - - private Planet(double mass, double surfaceGravity, int numberOfMoons) { - this.mass = mass; - this.surfaceGravity = surfaceGravity; - this.numberOfMoons = numberOfMoons; - } - - public double getMass() { - return mass; - } - - public double getSurfaceGravity() { - return surfaceGravity; - } - - public int getNumberOfMoons() { - return numberOfMoons; - } - } - - private static final String PLANET_COLUMN = "planet"; - private static final String MASS_COLUMN = "mass"; - private static final String GRAVITY_COLUMN = "gravity"; - private static final String MOONS_COLUMN = "moons"; - - private static final ColumnDescription[] planetTableColumns = - new ColumnDescription[] { - new ColumnDescription(PLANET_COLUMN, ValueType.TEXT, "Planet"), - new ColumnDescription(MASS_COLUMN, ValueType.NUMBER, "Mass"), - new ColumnDescription(GRAVITY_COLUMN, ValueType.NUMBER, "Surface Gravity"), - new ColumnDescription(MOONS_COLUMN, ValueType.NUMBER, "Number of Moons") - }; - - @Override - protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { - DataSourceRequest dsRequest = null; - - try { - // Extract the request parameters. - dsRequest = new DataSourceRequest(req); - - // NOTE: If you want to work in restricted mode, which means that only - // requests from the same domain can access the data source, you should - // uncomment the following call. - // - // DataSourceHelper.verifyAccessApproved(dsRequest); - - // Split the query. - QueryPair query = DataSourceHelper.splitQuery(dsRequest.getQuery(), Capabilities.SELECT); - - // Generate the data table. - DataTable data = generateMyDataTable(query.getDataSourceQuery(), req); - - // Apply the completion query to the data table. - DataTable newData = DataSourceHelper.applyQuery(query.getCompletionQuery(), data, - dsRequest.getUserLocale()); - - DataSourceHelper.setServletResponse(newData, dsRequest, resp); - } catch (RuntimeException rte) { - log.error("A runtime exception has occured", rte); - ResponseStatus status = new ResponseStatus(StatusType.ERROR, ReasonType.INTERNAL_ERROR, - rte.getMessage()); - if (dsRequest == null) { - dsRequest = DataSourceRequest.getDefaultDataSourceRequest(req); - } - DataSourceHelper.setServletErrorResponse(status, dsRequest, resp); - } catch (DataSourceException e) { - if (dsRequest != null) { - DataSourceHelper.setServletErrorResponse(e, dsRequest, resp); - } else { - DataSourceHelper.setServletErrorResponse(e, req, resp); - } - } - } - - /** - * Returns true if the given column name is requested in the given query. - * If the query is empty, all columnNames returns true. - * - * @param query The given query. - * @param columnName The requested column name. - * - * @return True if the given column name is requested in the given query. - */ - private boolean isColumnRequested(Query query, String columnName) { - // If the query is empty return true. - if (query.isEmpty()) { - return true; - } - - List columns = query.getSelection().getColumns(); - for (AbstractColumn column : columns) { - if (column.getId().equalsIgnoreCase(columnName)) { - return true; - } - } - return false; - } - - /** - * Generates a data table - according to the provided tableId url parameter. - * - * @param query The query to operate on the underlying data. - * @param req The HttpServeltRequest. - * - * @return The generated data table. - */ - private DataTable generateMyDataTable(Query query, HttpServletRequest req) - throws TypeMismatchException { - String tableID = req.getParameter("tableId"); - if ((tableID != null) && (tableID.equalsIgnoreCase("planets"))) { - return generatePlanetsTable(query); - } - return generateAnimalsTable(query); - } - - /** - * Returns an animals data table. The table contains a list of animals and - * links to wikipedia pages. - * - * @param query The selection query. - * - * @return A data table of animals. - */ - private DataTable generateAnimalsTable(Query query) throws TypeMismatchException { - DataTable data = new DataTable(); - List requiredColumns = getRequiredColumns(query, - ANIMAL_TABLE_COLUMNS); - data.addColumns(requiredColumns); - - // Populate the data table - for (String key : animalLinksByName.keySet()) { - TableRow row = new TableRow(); - for (ColumnDescription selectionColumn : requiredColumns) { - String columnName = selectionColumn.getId(); - if (columnName.equals(ANIMAL_COLUMN)) { - row.addCell(key); - } else if (columnName.equals(ARTICLE_COLUMN)) { - row.addCell(animalLinksByName.get(key)); - } - } - data.addRow(row); - } - return data; - } - - /** - * Returns the planets data table. - * - * @param query The selection query. - * - * @return planets data table. - */ - private DataTable generatePlanetsTable(Query query) throws TypeMismatchException { - DataTable data = new DataTable(); - List requiredColumns = getRequiredColumns( - query, planetTableColumns); - data.addColumns(requiredColumns); - - // Populate data table - for (Planet planet : Planet.values()) { - TableRow row = new TableRow(); - for (ColumnDescription selectionColumn : requiredColumns) { - String columnName = selectionColumn.getId(); - if (columnName.equals(PLANET_COLUMN)) { - row.addCell(planet.name()); - } else if (columnName.equals(MASS_COLUMN)) { - row.addCell(planet.getMass()); - } else if (columnName.equals(GRAVITY_COLUMN)) { - row.addCell(planet.getSurfaceGravity()); - } else if (columnName.equals(MOONS_COLUMN)) { - row.addCell(planet.getNumberOfMoons()); - } - } - data.addRow(row); - } - return data; - } - - /** - * Returns a list of required columns based on the query and the actual - * columns. - * - * @param query The user selection query. - * @param availableColumns The list of possible columns. - * - * @return A List of required columns for the requested data table. - */ - private List getRequiredColumns(Query query, - ColumnDescription[] availableColumns) { - // Required columns - List requiredColumns = Lists.newArrayList(); - for (ColumnDescription column : availableColumns) { - if (isColumnRequested(query, column.getId())) { - requiredColumns.add(column); - } - } - return requiredColumns; - } -} diff --git a/examples/src/java/CsvDataSourceServlet.java b/examples/src/java/CsvDataSourceServlet.java deleted file mode 100755 index 8e5b2f3..0000000 --- a/examples/src/java/CsvDataSourceServlet.java +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import com.google.visualization.datasource.DataSourceHelper; -import com.google.visualization.datasource.DataSourceServlet; -import com.google.visualization.datasource.base.DataSourceException; -import com.google.visualization.datasource.base.ReasonType; -import com.google.visualization.datasource.datatable.DataTable; -import com.google.visualization.datasource.query.Query; -import com.google.visualization.datasource.util.CsvDataSourceHelper; - -import com.ibm.icu.util.ULocale; - -import org.apache.commons.lang.StringUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.Reader; -import java.net.MalformedURLException; -import java.net.URL; - -import javax.servlet.http.HttpServletRequest; - -/** - * A demo servlet for serving a simple, constant data table. - * This servlet extends DataSourceServlet, but does not override the default - * empty implementation of method getCapabilities(). This servlet therefore ignores the - * user query (as passed in the 'tq' url parameter), leaving the - * query engine to apply it to the data table created here. - * - * @author Nimrod T. - */ -public class CsvDataSourceServlet extends DataSourceServlet { - - /** - * Log. - */ - private static final Log log = LogFactory.getLog(CsvDataSourceServlet.class.getName()); - - /** - * The name of the parameter that contains the url of the CSV to load. - */ - private static final String URL_PARAM_NAME = "url"; - - /** - * Generates the data table. - * This servlet assumes a special parameter that contains the CSV URL from which to load - * the data. - */ - @Override - public DataTable generateDataTable(Query query, HttpServletRequest request) - throws DataSourceException { - String url = request.getParameter(URL_PARAM_NAME); - if (StringUtils.isEmpty(url)) { - log.error("url parameter not provided."); - throw new DataSourceException(ReasonType.INVALID_REQUEST, "url parameter not provided"); - } - - Reader reader; - try { - reader = new BufferedReader(new InputStreamReader(new URL(url).openStream())); - } catch (MalformedURLException e) { - log.error("url is malformed: " + url); - throw new DataSourceException(ReasonType.INVALID_REQUEST, "url is malformed: " + url); - } catch (IOException e) { - log.error("Couldn't read from url: " + url, e); - throw new DataSourceException(ReasonType.INVALID_REQUEST, "Couldn't read from url: " + url); - } - DataTable dataTable = null; - ULocale requestLocale = DataSourceHelper.getLocaleFromRequest(request); - try { - // Note: We assume that all the columns in the CSV file are text columns. In cases where the - // column types are known in advance, this behavior can be overridden by passing a list of - // ColumnDescription objects specifying the column types. See CsvDataSourceHelper.read() for - // more details. - dataTable = CsvDataSourceHelper.read(reader, null, true, requestLocale); - } catch (IOException e) { - log.error("Couldn't read from url: " + url, e); - throw new DataSourceException(ReasonType.INVALID_REQUEST, "Couldn't read from url: " + url); - } - return dataTable; - } - - /** - * NOTE: By default, this function returns true, which means that cross - * domain requests are rejected. - * This check is disabled here so examples can be used directly from the - * address bar of the browser. Bear in mind that this exposes your - * data source to xsrf attacks. - * If the only use of the data source url is from your application, - * that runs on the same domain, it is better to remain in restricted mode. - */ - @Override - protected boolean isRestrictedAccessMode() { - return false; - } -} diff --git a/examples/src/java/SimpleExampleServlet.java b/examples/src/java/SimpleExampleServlet.java deleted file mode 100755 index c99367e..0000000 --- a/examples/src/java/SimpleExampleServlet.java +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import com.google.visualization.datasource.DataSourceServlet; -import com.google.visualization.datasource.base.TypeMismatchException; -import com.google.visualization.datasource.datatable.ColumnDescription; -import com.google.visualization.datasource.datatable.DataTable; -import com.google.visualization.datasource.datatable.value.ValueType; -import com.google.visualization.datasource.query.Query; - -import java.util.ArrayList; - -import javax.servlet.http.HttpServletRequest; - -/** - * A demo servlet for serving a simple, constant data table. - * This servlet extends DataSourceServlet. - * - * @author Nimrod T. - */ -public class SimpleExampleServlet extends DataSourceServlet { - - @Override - public DataTable generateDataTable(Query query, HttpServletRequest request) { - // Create a data table. - DataTable data = new DataTable(); - ArrayList cd = new ArrayList(); - cd.add(new ColumnDescription("name", ValueType.TEXT, "Animal name")); - cd.add(new ColumnDescription("link", ValueType.TEXT, "Link to wikipedia")); - cd.add(new ColumnDescription("population", ValueType.NUMBER, "Population size")); - cd.add(new ColumnDescription("vegeterian", ValueType.BOOLEAN, "Vegetarian?")); - - data.addColumns(cd); - - // Fill the data table. - try { - data.addRowFromValues("Aye-aye", "http://en.wikipedia.org/wiki/Aye-aye", 100, true); - data.addRowFromValues("Sloth", "http://en.wikipedia.org/wiki/Sloth", 300, true); - data.addRowFromValues("Leopard", "http://en.wikipedia.org/wiki/Leopard", 50, false); - data.addRowFromValues("Tiger", "http://en.wikipedia.org/wiki/Tiger", 80, false); - } catch (TypeMismatchException e) { - System.out.println("Invalid type!"); - } - return data; - } - - /** - * NOTE: By default, this function returns true, which means that cross - * domain requests are rejected. - * This check is disabled here so examples can be used directly from the - * address bar of the browser. Bear in mind that this exposes your - * data source to xsrf attacks. - * If the only use of the data source url is from your application, - * that runs on the same domain, it is better to remain in restricted mode. - */ - @Override - protected boolean isRestrictedAccessMode() { - return false; - } -} diff --git a/examples/src/java/SimpleExampleServlet2.java b/examples/src/java/SimpleExampleServlet2.java deleted file mode 100755 index 9f488a5..0000000 --- a/examples/src/java/SimpleExampleServlet2.java +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import com.google.visualization.datasource.DataSourceHelper; -import com.google.visualization.datasource.DataSourceRequest; -import com.google.visualization.datasource.base.DataSourceException; -import com.google.visualization.datasource.base.ReasonType; -import com.google.visualization.datasource.base.ResponseStatus; -import com.google.visualization.datasource.base.StatusType; -import com.google.visualization.datasource.base.TypeMismatchException; -import com.google.visualization.datasource.datatable.ColumnDescription; -import com.google.visualization.datasource.datatable.DataTable; -import com.google.visualization.datasource.datatable.value.ValueType; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.io.IOException; -import java.util.ArrayList; - -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - - -/** - * A demo servlet for serving a simple, constant data-table. - * - * For the sake of a complete example this servlet extends HttpServlet. - * DataSourceServlet is an abstract class that provides a template behavior for - * serving data source requests. Consider extending DataSourceServlet for - * easier implementation. - * - * @see com.google.visualization.datasource.DataSourceServlet - * @see com.google.visualization.datasource.example.SimpleExampleServlet - */ -public class SimpleExampleServlet2 extends HttpServlet { - - /** - * The log used throughout the data source library. - */ - private static final Log log = LogFactory.getLog(SimpleExampleServlet2.class.getName()); - - @Override - protected void doGet(HttpServletRequest req, HttpServletResponse resp) - throws IOException { - DataTable data = generateMyDataTable(); - DataSourceRequest dsRequest = null; - - try { - // Extract the datasource request parameters. - dsRequest = new DataSourceRequest(req); - - // NOTE: If you want to work in restricted mode, which means that only - // requests from the same domain can access the data source, uncomment the following call. - // - // DataSourceHelper.verifyAccessApproved(dsRequest); - - // Apply the query to the data table. - DataTable newData = DataSourceHelper.applyQuery(dsRequest.getQuery(), data, - dsRequest.getUserLocale()); - - // Set the response. - DataSourceHelper.setServletResponse(newData, dsRequest, resp); - } catch (RuntimeException rte) { - log.error("A runtime exception has occured", rte); - ResponseStatus status = new ResponseStatus(StatusType.ERROR, ReasonType.INTERNAL_ERROR, - rte.getMessage()); - if (dsRequest == null) { - dsRequest = DataSourceRequest.getDefaultDataSourceRequest(req); - } - DataSourceHelper.setServletErrorResponse(status, dsRequest, resp); - } catch (DataSourceException e) { - if (dsRequest != null) { - DataSourceHelper.setServletErrorResponse(e, dsRequest, resp); - } else { - DataSourceHelper.setServletErrorResponse(e, req, resp); - } - } - } - - private DataTable generateMyDataTable() { - // Create a data table, - DataTable data = new DataTable(); - ArrayList cd = new ArrayList(); - cd.add(new ColumnDescription("name", ValueType.TEXT, "Animal name")); - cd.add(new ColumnDescription("link", ValueType.TEXT, "Link to wikipedia")); - cd.add(new ColumnDescription("population", ValueType.NUMBER, "Population size")); - cd.add(new ColumnDescription("vegeterian", ValueType.BOOLEAN, "Vegetarian?")); - - data.addColumns(cd); - - // Fill the data table. - try { - data.addRowFromValues("Aye-aye", "http://en.wikipedia.org/wiki/Aye-aye", 100, true); - data.addRowFromValues("Sloth", "http://en.wikipedia.org/wiki/Sloth", 300, true); - data.addRowFromValues("Leopard", "http://en.wikipedia.org/wiki/Leopard", 50, false); - data.addRowFromValues("Tiger", "http://en.wikipedia.org/wiki/Tiger", 80, false); - } catch (TypeMismatchException e) { - System.out.println("Invalid type!"); - } - return data; - - } -} diff --git a/examples/src/java/SqlDataSourceServlet.java b/examples/src/java/SqlDataSourceServlet.java deleted file mode 100755 index 5b20beb..0000000 --- a/examples/src/java/SqlDataSourceServlet.java +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import com.google.visualization.datasource.Capabilities; -import com.google.visualization.datasource.DataSourceServlet; -import com.google.visualization.datasource.base.DataSourceException; -import com.google.visualization.datasource.datatable.DataTable; -import com.google.visualization.datasource.query.Query; -import com.google.visualization.datasource.util.SqlDataSourceHelper; -import com.google.visualization.datasource.util.SqlDatabaseDescription; - -import javax.servlet.http.HttpServletRequest; - -/** - * An example data source servlet that can query an SQL database. - * This makes use of the SqlDataSourceHelper class that is part of this library. - * - * Query language operations affect the result. This includes operations - * that are not part of SQL itself, such as pivoting, which is executed by - * the query engine. - * - * Four URL parameters must be specified, these are then passed to - * the underlying SQL DB. The parameters are as follows: - * url - The url of the sql DB. - * user - The username to use when accessing the DB. - * password - The password to use when accessing the DB. - * table - The SQL table name. - * - * @author Yaniv S. - */ -public class SqlDataSourceServlet extends DataSourceServlet { - - /** - * The SQL predefined capabilities set is a special custom set for SQL - * databases. This implements most of the data source capabilities more - * efficiently. - */ - @Override - public Capabilities getCapabilities() { - return Capabilities.SQL; - } - - @Override - public DataTable generateDataTable(Query query, HttpServletRequest request) - throws DataSourceException { - SqlDatabaseDescription dbDescription = new SqlDatabaseDescription( - request.getParameter("url"), - request.getParameter("user"), - request.getParameter("password"), - request.getParameter("table")); - return SqlDataSourceHelper.executeQuery(query, dbDescription); - } - - /** - * NOTE: By default, this function returns true, which means that cross - * domain requests are rejected. - * This check is disabled here so examples can be used directly from the - * address bar of the browser. Bear in mind that this exposes your - * data source to xsrf attacks. - * If the only use of the data source url is from your application, - * that runs on the same domain, it is better to remain in restricted mode. - */ - @Override - protected boolean isRestrictedAccessMode() { - return false; - } -} diff --git a/lib/commons-lang-2.4.jar b/lib/commons-lang-2.4.jar deleted file mode 100644 index 532939e..0000000 Binary files a/lib/commons-lang-2.4.jar and /dev/null differ diff --git a/lib/commons-logging-1.1.1.jar b/lib/commons-logging-1.1.1.jar deleted file mode 100644 index 8758a96..0000000 Binary files a/lib/commons-logging-1.1.1.jar and /dev/null differ diff --git a/lib/easymock-2.5.jar b/lib/easymock-2.5.jar deleted file mode 100644 index 5ee30f6..0000000 Binary files a/lib/easymock-2.5.jar and /dev/null differ diff --git a/lib/guava-r07.jar b/lib/guava-r07.jar deleted file mode 100644 index a6c9ce0..0000000 Binary files a/lib/guava-r07.jar and /dev/null differ diff --git a/lib/icu4j-4_0_1.jar b/lib/icu4j-4_0_1.jar deleted file mode 100644 index b88299e..0000000 Binary files a/lib/icu4j-4_0_1.jar and /dev/null differ diff --git a/lib/javacc.jar b/lib/javacc.jar deleted file mode 100644 index 03e54cd..0000000 Binary files a/lib/javacc.jar and /dev/null differ diff --git a/lib/junit-4.6.jar b/lib/junit-4.6.jar deleted file mode 100644 index 00770a4..0000000 Binary files a/lib/junit-4.6.jar and /dev/null differ diff --git a/lib/opencsv-1.8.jar b/lib/opencsv-1.8.jar deleted file mode 100644 index cc8200b..0000000 Binary files a/lib/opencsv-1.8.jar and /dev/null differ diff --git a/pom.xml b/pom.xml deleted file mode 100644 index 4546464..0000000 --- a/pom.xml +++ /dev/null @@ -1,101 +0,0 @@ - - 4.0.0 - - com.google - google - 1 - - com.google.visualization - visualization-datasource - Google Visualization Data Source Library - 1.1.2 - This library makes it easy to implement a Visualization data source so that you can - easily chart or visualize your data from any of your data stores. - The library implements the Google Visualization API wire protocol and query language. - You therefore need write only the code required to make your data available to the library in - the form of a data table. - This task is made easier by the provision of abstract classes and helper - functions. - - UTF-8 - - - - commons-lang - commons-lang - 2.4 - - - commons-logging - commons-logging - 1.1.1 - - - com.google.guava - guava - r07 - - - com.ibm.icu - icu4j - 4.0.1 - - - net.sf.opencsv - opencsv - 1.8 - - - javax.servlet - servlet-api - 2.5 - provided - - - junit - junit - 4.6 - test - - - org.easymock - easymock - 2.5 - test - - - - ${basedir}/build - ${basedir}/build/class/main - ${basedir}/build/class/test - - - - org.apache.maven.plugins - maven-compiler-plugin - - 1.6 - 1.6 - - - - org.codehaus.mojo - javacc-maven-plugin - 2.5 - - - javacc - - javacc - - - ${basedir}/src/main/java - - - - - - - diff --git a/src/main/java/com/google/visualization/datasource/Capabilities.java b/src/main/java/com/google/visualization/datasource/Capabilities.java deleted file mode 100755 index a14a773..0000000 --- a/src/main/java/com/google/visualization/datasource/Capabilities.java +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource; - -/** - * An enumeration of the capabilities provided by a data source. A data source declares the - * capabilities it supports and this information determines how a query is split. - * For example if a data source declares Capibilities.SELECT then the following - * query select A,B sort A limit 20 - * will be split as follows: - * query for data source - 'select A,B' - * completion query - 'sort A limit 20' - * - * @author Yonatan B.Y. - */ -public enum Capabilities { - - /** - * Supports: filter, sort, group, limit, and offset. - * Does not support: pivot, options, labels, format or scalar functions. - */ - SQL, - - /** - * Supports: sort, limit, and offset over simple columns. - * Simple columns are those that are not aggregation columns (such as max(a), - * count(b), avg(c)) or scalar function columns (like a+b, c*2, year(d)). - * If calculated columns are created, through scalar functions or aggregation for example, - * the completion query handles the SORT_AND_PAGINATION over the newly created columns. - */ - SORT_AND_PAGINATION, - - /** - * Supports: select over simple columns. - * - * If calculated columns are created, through scalar functions or aggregation for example, - * the completion query handles the SELECT over the newly created columns. - */ - SELECT, - - /** - * Supports all the above capabilities: SQL. SORT_AND_PAGINATION, and SELECT. - */ - ALL, - - /** - * Supports no capabilities. - */ - NONE -} diff --git a/src/main/java/com/google/visualization/datasource/DataSourceHelper.java b/src/main/java/com/google/visualization/datasource/DataSourceHelper.java deleted file mode 100755 index 0914175..0000000 --- a/src/main/java/com/google/visualization/datasource/DataSourceHelper.java +++ /dev/null @@ -1,507 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource; - -import com.google.visualization.datasource.base.DataSourceException; -import com.google.visualization.datasource.base.DataSourceParameters; -import com.google.visualization.datasource.base.InvalidQueryException; -import com.google.visualization.datasource.base.LocaleUtil; -import com.google.visualization.datasource.base.MessagesEnum; -import com.google.visualization.datasource.base.OutputType; -import com.google.visualization.datasource.base.ReasonType; -import com.google.visualization.datasource.base.ResponseStatus; -import com.google.visualization.datasource.base.StatusType; -import com.google.visualization.datasource.datatable.DataTable; -import com.google.visualization.datasource.query.AggregationColumn; -import com.google.visualization.datasource.query.Query; -import com.google.visualization.datasource.query.ScalarFunctionColumn; -import com.google.visualization.datasource.query.engine.QueryEngine; -import com.google.visualization.datasource.query.parser.QueryBuilder; -import com.google.visualization.datasource.render.CsvRenderer; -import com.google.visualization.datasource.render.HtmlRenderer; -import com.google.visualization.datasource.render.JsonRenderer; - -import com.ibm.icu.util.ULocale; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.io.IOException; -import java.util.Locale; -import java.util.Set; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -/** - * A Helper class providing convenience functions for serving data source requests. - * - * The class enables replying to a data source request with a single method which encompasses - * all the request processing - executeDataSourceServletFlow. - * To enable users to change the default flow all the basic operations (such as: query parsing, - * data table creation, query execution, and response creation) are also exposed. - * - * @author Yaniv S. - */ -public class DataSourceHelper { - - /** - * The log used throughout the data source library. - */ - private static final Log log = LogFactory.getLog(DataSourceHelper.class.getName()); - - /** - * The name of the http request parameter that indicates the requested locale. - */ - /* package */ static final String LOCALE_REQUEST_PARAMETER = "hl"; - - /** - * A private constructor for this Singleton. - */ - private DataSourceHelper() {} - - /** - * Executes the default data source servlet flow. - * Assumes restricted access mode. - * @see executeDataSourceServletFlow(HttpServletRequest req, HttpServletResponse resp, - * DataTableGenerator dtGenerator, boolean isRestrictedAccessMode) - * - * @param req The HttpServletRequest. - * @param resp The HttpServletResponse. - * @param dtGenerator An implementation of {@link DataTableGenerator} interface. - * - * @throws IOException In case of I/O errors. - */ - public static void executeDataSourceServletFlow(HttpServletRequest req, HttpServletResponse resp, - DataTableGenerator dtGenerator) throws IOException { - executeDataSourceServletFlow(req, resp, dtGenerator, true); - } - - /** - * Executes the default data source servlet flow. - * - * The default flow is as follows: - * - Parse the request parameters. - * - Verify access is approved (for restricted access mode only). - * - Split the query. - * - Generate the data-table using the data-table generator. - * - Run the completion query. - * - Set the servlet response. - * - * Usage note : this function executes the same flow provided to Servlets that inherit - * DataSourceServlet. - * Use this function when the default flow is required but DataSourceServlet - * cannot be inherited (e.g., your servlet already inherits from anther class, or not in a - * servlet context). - * - * @param req The HttpServletRequest. - * @param resp The HttpServletResponse. - * @param dtGenerator An implementation of {@link DataTableGenerator} interface. - * @param isRestrictedAccessMode Indicates whether the server should serve trusted domains only. - * Currently this translates to serving only requests from the same domain. - * - * @throws IOException In case of I/O errors. - */ - public static void executeDataSourceServletFlow(HttpServletRequest req, HttpServletResponse resp, - DataTableGenerator dtGenerator, boolean isRestrictedAccessMode) throws IOException { - // Extract the data source request parameters. - DataSourceRequest dsRequest = null; - try { - dsRequest = new DataSourceRequest(req); - - if (isRestrictedAccessMode) { - // Verify that the request is approved for access. - DataSourceHelper.verifyAccessApproved(dsRequest); - } - - // Split the query. - QueryPair query = DataSourceHelper.splitQuery(dsRequest.getQuery(), - dtGenerator.getCapabilities()); - - // Generate the data table. - DataTable dataTable = dtGenerator.generateDataTable(query.getDataSourceQuery(), req); - - // Apply the completion query to the data table. - DataTable newDataTable = DataSourceHelper.applyQuery(query.getCompletionQuery(), dataTable, - dsRequest.getUserLocale()); - - // Set the response. - setServletResponse(newDataTable, dsRequest, resp); - } catch (DataSourceException e) { - if (dsRequest != null) { - setServletErrorResponse(e, dsRequest, resp); - } else { - DataSourceHelper.setServletErrorResponse(e, req, resp); - } - } catch (RuntimeException e) { - log.error("A runtime exception has occured", e); - ResponseStatus status = new ResponseStatus(StatusType.ERROR, ReasonType.INTERNAL_ERROR, - e.getMessage()); - if (dsRequest == null) { - dsRequest = DataSourceRequest.getDefaultDataSourceRequest(req); - } - DataSourceHelper.setServletErrorResponse(status, dsRequest, resp); - } - } - - /** - * Checks that the given request is sent from the same domain as that of the server. - * - * @param req The data source request. - * - * @throws DataSourceException If the access for this request is denied. - */ - public static void verifyAccessApproved(DataSourceRequest req) throws DataSourceException { - // The library requires the request to be same origin for JSON and JSONP. - // Check for (!csv && !html && !tsv-excel) to make sure any output type - // added in the future will be restricted to the same domain by default. - OutputType outType = req.getDataSourceParameters().getOutputType(); - if (outType != OutputType.CSV && outType != OutputType.TSV_EXCEL - && outType != OutputType.HTML && !req.isSameOrigin()) { - throw new DataSourceException(ReasonType.ACCESS_DENIED, - "Unauthorized request. Cross domain requests are not supported."); - } - } - - // -------------------------- Servlet helper methods -------------------------------------------- - - /** - * Sets the response on the HttpServletResponse by creating a response message - * for the given DataTable and sets it on the HttpServletResponse. - * - * @param dataTable The data table. - * @param dataSourceRequest The data source request. - * @param res The http servlet response. - * - * @throws IOException In case an error happened trying to write the response to the servlet. - */ - public static void setServletResponse(DataTable dataTable, DataSourceRequest dataSourceRequest, - HttpServletResponse res) throws IOException { - String responseMessage = generateResponse(dataTable, dataSourceRequest); - setServletResponse(responseMessage, dataSourceRequest, res); - } - - /** - * Sets the given response string on the HttpServletResponse. - * - * @param responseMessage The response message. - * @param dataSourceRequest The data source request. - * @param res The HTTP response. - * - * @throws IOException In case an error happened trying to write to the servlet response. - */ - public static void setServletResponse(String responseMessage, - DataSourceRequest dataSourceRequest, HttpServletResponse res) throws IOException { - DataSourceParameters dataSourceParameters = dataSourceRequest.getDataSourceParameters(); - ResponseWriter.setServletResponse(responseMessage, dataSourceParameters, res); - } - - - /** - * Sets the HTTP servlet response in case of an error. - * - * @param dataSourceException The data source exception. - * @param dataSourceRequest The data source request. - * @param res The http servlet response. - * - * @throws IOException In case an error happened trying to write the response to the servlet. - */ - public static void setServletErrorResponse(DataSourceException dataSourceException, - DataSourceRequest dataSourceRequest, HttpServletResponse res) throws IOException { - String responseMessage = generateErrorResponse(dataSourceException, dataSourceRequest); - setServletResponse(responseMessage, dataSourceRequest, res); - } - - /** - * Sets the HTTP servlet response in case of an error. - * - * @param responseStatus The response status. - * @param dataSourceRequest The data source request. - * @param res The http servlet response. - * - * @throws IOException In case an error happened trying to write the response to the servlet. - */ - public static void setServletErrorResponse(ResponseStatus responseStatus, - DataSourceRequest dataSourceRequest, HttpServletResponse res) throws IOException { - String responseMessage = generateErrorResponse(responseStatus, dataSourceRequest); - setServletResponse(responseMessage, dataSourceRequest, res); - } - - /** - * Sets the HTTP servlet response in case of an error. - * - * Gets an HttpRequest parameter instead of a DataSourceRequest. - * Use this when DataSourceRequest is not available, for example, if - * DataSourceRequest constructor failed. - * - * @param dataSourceException The data source exception. - * @param req The http servlet request. - * @param res The http servlet response. - * - * @throws IOException In case an error happened trying to write the response to the servlet. - */ - public static void setServletErrorResponse(DataSourceException dataSourceException, - HttpServletRequest req, HttpServletResponse res) throws IOException { - DataSourceRequest dataSourceRequest = DataSourceRequest.getDefaultDataSourceRequest(req); - setServletErrorResponse(dataSourceException, dataSourceRequest, res); - } - - // -------------------- Response message helper methods. ---------------------------------------- - - /** - * Generates a string response for the given DataTable. - * - * @param dataTable The data table. - * @param dataSourceRequest The data source request. - * - * @return The response string. - */ - public static String generateResponse(DataTable dataTable, DataSourceRequest dataSourceRequest) { - CharSequence response; - ResponseStatus responseStatus = null; - if (!dataTable.getWarnings().isEmpty()) { - responseStatus = new ResponseStatus(StatusType.WARNING); - } - switch (dataSourceRequest.getDataSourceParameters().getOutputType()) { - case CSV: - response = CsvRenderer.renderDataTable(dataTable, dataSourceRequest.getUserLocale(), ","); - break; - case TSV_EXCEL: - response = CsvRenderer.renderDataTable(dataTable, dataSourceRequest.getUserLocale(), "\t"); - break; - case HTML: - response = HtmlRenderer.renderDataTable(dataTable, dataSourceRequest.getUserLocale()); - break; - case JSONP: - // Appending a comment to the response to prevent the first characters to be the - // response handler which is not controlled by the server. - response = "// Data table response\n" + JsonRenderer.renderJsonResponse( - dataSourceRequest.getDataSourceParameters(), responseStatus, dataTable); - break; - case JSON: - response = JsonRenderer.renderJsonResponse( - dataSourceRequest.getDataSourceParameters(), responseStatus, dataTable); - break; - default: - // This should never happen. - throw new RuntimeException("Unhandled output type."); - } - - return response.toString(); - } - - /** - * Generates an error response string for the given {@link DataSourceException}. - * Receives an exception, and renders it to an error response according to the - *{@link OutputType} specified in the {@link DataSourceRequest}. - * - * Note: modifies the response status to make links clickable in cases where the reason type is - * {@link ReasonType#USER_NOT_AUTHENTICATED}. If this is not required call generateErrorResponse - * directly with a {@link ResponseStatus}. - * - * @param dse The data source exception. - * @param dsRequest The DataSourceRequest. - * - * @return The error response string. - * - * @throws IOException In case if I/O errors. - */ - public static String generateErrorResponse(DataSourceException dse, DataSourceRequest dsRequest) - throws IOException { - ResponseStatus responseStatus = ResponseStatus.createResponseStatus(dse); - responseStatus = ResponseStatus.getModifiedResponseStatus(responseStatus); - return generateErrorResponse(responseStatus, dsRequest); - } - - /** - * Generates an error response string for the given ResponseStatus. - * Render the ResponseStatus to an error response according to the - * OutputType specified in the DataSourceRequest. - * - * @param responseStatus The response status. - * @param dsRequest The DataSourceRequest. - * - * @return The error response string. - * - * @throws IOException In case if I/O errors. - */ - public static String generateErrorResponse(ResponseStatus responseStatus, - DataSourceRequest dsRequest) throws IOException { - DataSourceParameters dsParameters = dsRequest.getDataSourceParameters(); - CharSequence response; - switch (dsParameters.getOutputType()) { - case CSV: - case TSV_EXCEL: - response = CsvRenderer.renderCsvError(responseStatus); - break; - case HTML: - response = HtmlRenderer.renderHtmlError(responseStatus); - break; - case JSONP: - response = JsonRenderer.renderJsonResponse(dsParameters, responseStatus, null); - break; - case JSON: - response = JsonRenderer.renderJsonResponse(dsParameters, responseStatus, null); - break; - default: - // This should never happen. - throw new RuntimeException("Unhandled output type."); - } - return response.toString(); - } - - // -------------------------- Query helper methods ---------------------------------------------- - - /** @see #parseQuery(String, ULocale)*/ - public static Query parseQuery(String queryString) throws InvalidQueryException { - return parseQuery(queryString, null); - } - - /** - * Parses a query string (e.g., 'select A,B pivot B') and creates a Query object. - * Throws an exception if the query is invalid. - * - * @param queryString The query string. - * @param locale The user locale. - * - * @return The parsed query object. - * - * @throws InvalidQueryException If the query is invalid. - */ - public static Query parseQuery(String queryString, ULocale userLocale) - throws InvalidQueryException { - QueryBuilder queryBuilder = QueryBuilder.getInstance(); - Query query = queryBuilder.parseQuery(queryString, userLocale); - - return query; - } - - /** - * Applies the given Query on the given DataTable and returns the - * resulting DataTable. This method may change the given DataTable. - * Error messages produced by this method will be localized according to the passed locale - * unless the specified {@code DataTable} has a non null locale. - * - * @param query The query object. - * @param dataTable The data table on which to apply the query. - * @param locale The user locale for the current request. - * - * @return The data table result of the query execution over the given data table. - * - * @throws InvalidQueryException If the query is invalid. - * @throws DataSourceException If the data source cannot execute the query. - */ - public static DataTable applyQuery(Query query, DataTable dataTable, ULocale locale) - throws InvalidQueryException, DataSourceException { - dataTable.setLocaleForUserMessages(locale); - validateQueryAgainstColumnStructure(query, dataTable); - dataTable = QueryEngine.executeQuery(query, dataTable, locale); - dataTable.setLocaleForUserMessages(locale); - return dataTable; - } - - /** - * Splits the Query object into two queries according to the declared data source - * capabilities: data source query and completion query. - * - * The data source query is executed first by the data source itself. Afterward, the - * QueryEngine executes the completion query over the resulting data table. - * - * @param query The query to split. - * @param capabilities The declared capabilities of the data source. - * - * @return A QueryPair object. - * - * @throws DataSourceException If the query cannot be split. - */ - public static QueryPair splitQuery(Query query, Capabilities capabilities) - throws DataSourceException { - return QuerySplitter.splitQuery(query, capabilities); - } - - /** - * Checks that the query is valid against the structure of the data table. - * A query is invalid if: - *
    - *
  1. The query references column ids that don't exist in the data table. - *
  2. The query contains calculated columns operations (i.e., scalar function, aggregations) - * that do not match the relevant columns type. - *
- * - * Note: does NOT validate the query itself, i.e. errors like "SELECT a, a" or - * "SELECT a GROUP BY a" will not be caught. These kind of errors should be checked elsewhere - * (preferably by the Query.validate() method). - * - * @param query The query to check for validity. - * @param dataTable The data table against which to validate. Only the columns are used. - * - * @throws InvalidQueryException Thrown if the query is found to be invalid - * against the given data table. - */ - public static void validateQueryAgainstColumnStructure(Query query, DataTable dataTable) - throws InvalidQueryException { - // Check that all the simple columns exist in the table (including the - // simple columns inside aggregation and scalar-function columns) - Set mentionedColumnIds = query.getAllColumnIds(); - for (String columnId : mentionedColumnIds) { - if (!dataTable.containsColumn(columnId)) { - String messageToLogAndUser = MessagesEnum.NO_COLUMN.getMessageWithArgs( - dataTable.getLocaleForUserMessages(), columnId); - log.error(messageToLogAndUser); - throw new InvalidQueryException(messageToLogAndUser); - } - } - - // Check that all aggregation columns are valid (i.e., the aggregation type - // matches the columns type). - Set mentionedAggregations = query.getAllAggregations(); - for (AggregationColumn agg : mentionedAggregations) { - try { - agg.validateColumn(dataTable); - } catch (RuntimeException e) { - log.error("A runtime exception has occured", e); - throw new InvalidQueryException(e.getMessage()); - } - } - - // Check that all scalar function columns are valid. (i.e., the scalar - // function matches the columns types). - Set mentionedScalarFunctionColumns = - query.getAllScalarFunctionsColumns(); - for (ScalarFunctionColumn col : mentionedScalarFunctionColumns) { - col.validateColumn(dataTable); - } - } - - /** - * Get the locale from the given request. - * - * @param req The http serlvet request - * - * @return The locale for the given request. - */ - public static ULocale getLocaleFromRequest(HttpServletRequest req) { - Locale locale; - String requestLocale = req.getParameter(LOCALE_REQUEST_PARAMETER); - if (requestLocale != null) { - // Try to take the locale from the 'hl' parameter in the request. - locale = LocaleUtil.getLocaleFromLocaleString(requestLocale); - } else { - // Else, take the browser locale. - locale = req.getLocale(); - } - return ULocale.forLocale(locale); - } -} diff --git a/src/main/java/com/google/visualization/datasource/DataSourceRequest.java b/src/main/java/com/google/visualization/datasource/DataSourceRequest.java deleted file mode 100755 index d1fdf51..0000000 --- a/src/main/java/com/google/visualization/datasource/DataSourceRequest.java +++ /dev/null @@ -1,241 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource; - -import com.google.visualization.datasource.base.DataSourceException; -import com.google.visualization.datasource.base.DataSourceParameters; -import com.google.visualization.datasource.base.InvalidQueryException; -import com.google.visualization.datasource.base.OutputType; -import com.google.visualization.datasource.query.Query; - -import com.ibm.icu.util.ULocale; - -import javax.servlet.http.HttpServletRequest; - -/** - * This class contains all information concerning a data source request. The information in this - * class is used to create a data table and return a corresponding response to the user. - * - * @author Yaniv S. - * - */ -public class DataSourceRequest { - - /** - * The query (based on the "tq" request parameter). - */ - private Query query; - - /** - * The data source parameters (based on the "tqx" request parameter). - */ - private DataSourceParameters dsParams; - - /** - * The user locale. - */ - private ULocale userLocale; - - /** - * Indicates whether the request is from the same origin. - */ - private boolean sameOrigin; - - /** - * A request header name. Used to determine if the request was sent from the same domain as the - * server. - */ - public static final String SAME_ORIGIN_HEADER = "X-DataSource-Auth"; - - /** - * The name of the request parameter that specifies the query to execute. - */ - public static final String QUERY_REQUEST_PARAMETER = "tq"; - - /** - * The name of the request parameter that specifies the data source parameters. - */ - public static final String DATASOURCE_REQUEST_PARAMETER = "tqx"; - - /** - * A private constructor. - */ - private DataSourceRequest() {} - - /** - * Constructor. - * Useful for debugging and testing. - * Do not use it for production. - * - * @param query The query. - * @param dsParams The data source parameters. - * @param userLocale The user locale. - */ - public DataSourceRequest(Query query, DataSourceParameters dsParams, ULocale userLocale) { - setUserLocale(userLocale); - this.dsParams = dsParams; - this.query = query; - } - - /** - * Builds a DataSource request from an HttpServletRequest. - * - * @param req The HttpServletRequest. - * - * @throws DataSourceException In case of an invalid 'tq' or 'tqx' parameter. - */ - public DataSourceRequest(HttpServletRequest req) throws DataSourceException { - inferLocaleFromRequest(req); - sameOrigin = determineSameOrigin(req); - createDataSourceParametersFromRequest(req); - createQueryFromRequest(req); - } - - /** - * Returns a default data source request. - * - * Used in case no data source request is available (i.e., because of invalid input). - * Parses the input 'tq' and 'tqx' strings and, if it fails, uses default values. - * - * @param req The http servlet request. - * - * @return A default data source request. - */ - public static DataSourceRequest getDefaultDataSourceRequest(HttpServletRequest req) { - DataSourceRequest dataSourceRequest = new DataSourceRequest(); - dataSourceRequest.inferLocaleFromRequest(req); - dataSourceRequest.sameOrigin = determineSameOrigin(req); - try { - dataSourceRequest.createDataSourceParametersFromRequest(req); - } catch (DataSourceException e) { - if (dataSourceRequest.dsParams == null) { - dataSourceRequest.dsParams = DataSourceParameters.getDefaultDataSourceParameters(); - } - if ((dataSourceRequest.dsParams.getOutputType() == OutputType.JSON) - && (!dataSourceRequest.sameOrigin)) { - dataSourceRequest.dsParams.setOutputType(OutputType.JSONP); - } - } - try { - dataSourceRequest.createQueryFromRequest(req); - } catch (InvalidQueryException e) { - // If we can't parse the 'tq' parameter, a null query is set. - } - return dataSourceRequest; - } - - /** - * Determines whether the given request is from the same origin (based on - * request headers set by the ). - * - * @param req The http servlet request. - * - * @return True if this is a same origin request false otherwise. - */ - public static boolean determineSameOrigin(HttpServletRequest req) { - // We conclude that the request is sent from the same origin if it contains a predefined - // header that the client application inserted. This is a known way of verifying that - // a request is xhr and hence was sent from the same domain. - return (req.getHeader(SAME_ORIGIN_HEADER) != null); - } - - /** - * Creates the Query based on the 'tq' parameter on the given request. - * - * @param req The http servlet request. - * - * @throws InvalidQueryException if the 'tq' string is invalid or missing on the request. - */ - private void createQueryFromRequest(HttpServletRequest req) throws InvalidQueryException { - String queryString = req.getParameter(QUERY_REQUEST_PARAMETER); - query = DataSourceHelper.parseQuery(queryString); - } - - /** - * Creates the DataSourceParameters based on the 'tqx' parameter on the given - * request. - * - * @param req The http servlet request. - * - * @throws DataSourceException Thrown if the data source parameters or query could not be parsed. - */ - private void createDataSourceParametersFromRequest(HttpServletRequest req) - throws DataSourceException { - // Set the data source parameters. - String dataSourceParamsString = req.getParameter(DATASOURCE_REQUEST_PARAMETER); - - dsParams = new DataSourceParameters(dataSourceParamsString); - // For backward compatibility, set the OutputType to be 'jsonp' in case the request is cross - // domain and the 'out' property in the 'tqx' parameter is 'json'. - if (dsParams.getOutputType() == OutputType.JSON && !sameOrigin) { - dsParams.setOutputType(OutputType.JSONP); - } - } - - - /** - * Infers the locale from the http servlet request. - * - * @param req The http servlet request. - */ - private void inferLocaleFromRequest(HttpServletRequest req) { - userLocale = DataSourceHelper.getLocaleFromRequest(req); - } - - /** - * Returns the query. - * - * @return The query. - */ - public Query getQuery() { - return query; - } - - /** - * Returns the data source parameters. - * - * @return The data source parameters. - */ - public DataSourceParameters getDataSourceParameters() { - return dsParams; - } - - /** - * Sets the user locale. - * - * @param userLocale The user locale. - */ - public void setUserLocale(ULocale userLocale) { - this.userLocale = userLocale; - } - - /** - * Returns the user locale. - * - * @return The user locale. - */ - public ULocale getUserLocale() { - return userLocale; - } - - /** - * Returns true if the request is same-origin. - * - * @return True if the request is same-origin. - */ - public boolean isSameOrigin() { - return sameOrigin; - } -} diff --git a/src/main/java/com/google/visualization/datasource/DataSourceServlet.java b/src/main/java/com/google/visualization/datasource/DataSourceServlet.java deleted file mode 100755 index a38ca51..0000000 --- a/src/main/java/com/google/visualization/datasource/DataSourceServlet.java +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource; - -import java.io.IOException; - -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -/** - * An abstract class for data source servlet implementations. - * - * @author Yaniv S. - */ -public abstract class DataSourceServlet extends HttpServlet implements DataTableGenerator { - - @Override - protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { - DataSourceHelper.executeDataSourceServletFlow(req, resp, this, isRestrictedAccessMode()); - } - - /** - * Returns a flag that indicates whether the servlet is in restricted-access mode. - * In restricted-access mode the server serves only requests coming from the same domain as the - * server domain (i.e., same origin policy). - * This protects the server from XSRF attacks while limiting the requests to which the server - * can respond. - * - * @return True if this servlet operates in restricted-access mode, false otherwise. - */ - protected boolean isRestrictedAccessMode() { - return true; - } - - @Override - protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException { - doGet(req, resp); - } - - @Override - public Capabilities getCapabilities() { - return Capabilities.NONE; - } -} diff --git a/src/main/java/com/google/visualization/datasource/DataTableGenerator.java b/src/main/java/com/google/visualization/datasource/DataTableGenerator.java deleted file mode 100755 index 4dd2e46..0000000 --- a/src/main/java/com/google/visualization/datasource/DataTableGenerator.java +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource; - -import com.google.visualization.datasource.base.DataSourceException; -import com.google.visualization.datasource.datatable.DataTable; -import com.google.visualization.datasource.query.Query; - -import javax.servlet.http.HttpServletRequest; - -/** - * An interface for a class that can generate a DataTable. - * - * @author Yaniv S. - */ -public interface DataTableGenerator { - - /** - * Generates the data table. - * - * @param query The query to execute on the underlying data. Ignore this parameter for - * a data source that does not support any capabilities. - * @param request The http request. May contain information that is relevant to generating - * the data table. - * - * @return The generated data table. - * - * @throws DataSourceException If the data could not be generated for any reason. - */ - public DataTable generateDataTable(Query query, HttpServletRequest request) - throws DataSourceException; - - /** - * Returns the capabilities supported by this data table generator. - * - * The query that generateDataTable accepts will only contain clauses - * corresponding to these capabilities. - * (see {@link com.google.visualization.datasource.Capabilities}). - * - * @return The capabilities supported by this datasource. - */ - public Capabilities getCapabilities(); -} diff --git a/src/main/java/com/google/visualization/datasource/QueryPair.java b/src/main/java/com/google/visualization/datasource/QueryPair.java deleted file mode 100755 index 1f2bf77..0000000 --- a/src/main/java/com/google/visualization/datasource/QueryPair.java +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource; - -import com.google.visualization.datasource.query.Query; - -/** - * A product of splitQuery() method, composed of a data source query to be executed first by - * the data source and a second completion query to be executed on the results of the - * first one by the query engine. - * The application of the first query and the second query is equivalent to the application of the - * original query. - * - * @author Yonatan B.Y. - */ -public class QueryPair { - - /** - * The data source query. - */ - private Query dataSourceQuery; - - /** - * The completion query. - */ - private Query completionQuery; - - /** - * Construct a new query pair. - * - * @param dataSourceQuery The data source query. - * @param completionQuery The completion query. - */ - public QueryPair(Query dataSourceQuery, Query completionQuery) { - this.dataSourceQuery = dataSourceQuery; - this.completionQuery = completionQuery; - } - - /** - * Returns the data source query. - * - * @return The data source query. - */ - public Query getDataSourceQuery() { - return dataSourceQuery; - } - - /** - * Returns the completion query. - * - * @return The completion query. - */ - public Query getCompletionQuery() { - return completionQuery; - } -} diff --git a/src/main/java/com/google/visualization/datasource/QuerySplitter.java b/src/main/java/com/google/visualization/datasource/QuerySplitter.java deleted file mode 100755 index 220fde4..0000000 --- a/src/main/java/com/google/visualization/datasource/QuerySplitter.java +++ /dev/null @@ -1,341 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource; - -import com.google.common.collect.Lists; -import com.google.visualization.datasource.base.DataSourceException; -import com.google.visualization.datasource.base.InvalidQueryException; -import com.google.visualization.datasource.base.ReasonType; -import com.google.visualization.datasource.query.AbstractColumn; -import com.google.visualization.datasource.query.AggregationColumn; -import com.google.visualization.datasource.query.AggregationType; -import com.google.visualization.datasource.query.Query; -import com.google.visualization.datasource.query.QueryFormat; -import com.google.visualization.datasource.query.QueryGroup; -import com.google.visualization.datasource.query.QueryLabels; -import com.google.visualization.datasource.query.QuerySelection; -import com.google.visualization.datasource.query.SimpleColumn; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.util.List; - -/** - * A utility class for splitting the user query into a data source query and a completion query. - * The data source query is executed by the data source, the completion query is then - * executed by the query engine. - * The splitting is performed based on the capabilities that the data source declares it can - * handle. - * - * @author Yonatan B.Y. - * - */ -public final class QuerySplitter { - - /** - * Log. - */ - private static final Log log = LogFactory.getLog(QuerySplitter.class.getName()); - - /** - * Private constructor. - */ - private QuerySplitter() {} - - /** - * Split the query into a data source query and completion query. The data source query runs - * first directly on the underlying data. The completion query is run by - * {@link com.google.visualization.datasource.query.engine.QueryEngine} engine on the result of - * the data source query. - * - * @param query The Query to split. - * @param capabilities The capabilities supported by the data source. - * - * @return A split query. - * - * @throws DataSourceException Thrown if the capabilities are not supported. - */ - public static QueryPair splitQuery(Query query, Capabilities capabilities) - throws DataSourceException { - switch (capabilities) { - case ALL: - return splitAll(query); - case NONE: - return splitNone(query); - case SQL: - return splitSQL(query); - case SORT_AND_PAGINATION: - return splitSortAndPagination(query); - case SELECT: - return splitSelect(query); - } - log.error("Capabilities not supported."); - throw new DataSourceException(ReasonType.NOT_SUPPORTED, "Capabilities not supported."); - } - - /** - * Splits the query for a data source with capabilities ALL. In this case, the original query is - * copied to the data source query and the original query is empty. - * - * @param query The query to split. - * - * @return The split query. - */ - private static QueryPair splitAll(Query query) { - Query dataSourceQuery = new Query(); - dataSourceQuery.copyFrom(query); - Query completionQuery = new Query(); - return new QueryPair(dataSourceQuery, completionQuery); - } - - /** - * Splits the query for a data source with capabilities NONE. In this case, the original query is - * copied to the completionQuery and the data source query is empty. Furthermore, the data source - * query is assigned null and shouldn't be used or referenced by the data source. - * - * @param query The query to split. - * - * @return The split query. - */ - private static QueryPair splitNone(Query query) { - Query completionQuery = new Query(); - completionQuery.copyFrom(query); - return new QueryPair(null, completionQuery); - } - - /** - * Splits the query for a data source with capabilities SQL. - * If the query contains scalar functions, then the query is split as if data source capabilities - * are NONE. If the query does not contain scalar functions, then the data source query contains - * most of the operations. - * Because SQL cannot handle pivoting, special care needs to be taken if the query includes a - * pivot operation. The aggregation operation required for pivoting is passed to the data source - * query. We make use of this, with some implementation tricks. See implementation comments. - * - * @param query The original query. - * - * @return The split query. - */ - private static QueryPair splitSQL(Query query) { - // Situations we currently do not support good splitting of: - // - Queries with scalar functions. - // - Queries with pivot that also contain labels or formatting on aggregation columns. - if (!query.getAllScalarFunctionsColumns().isEmpty() - || (query.hasPivot() - && ((query.hasUserFormatOptions() && - !query.getUserFormatOptions().getAggregationColumns().isEmpty()) - || (query.hasLabels() && !query.getLabels().getAggregationColumns().isEmpty())))) { - Query completionQuery = new Query(); - completionQuery.copyFrom(query); - return new QueryPair(new Query(), completionQuery); - } - - Query dataSourceQuery = new Query(); - Query completionQuery = new Query(); - - // sql supports select, where, sort, group, limit, offset. - // The library further supports pivot. - if (query.hasPivot()) { - // Make the pivot columns additional grouping columns, and handle the - // transformation later. - - List pivotColumns = query.getPivot().getColumns(); - - dataSourceQuery.copyFrom(query); - dataSourceQuery.setPivot(null); - dataSourceQuery.setSort(null); - dataSourceQuery.setOptions(null); - dataSourceQuery.setLabels(null); - dataSourceQuery.setUserFormatOptions(null); - - try { - dataSourceQuery.setRowSkipping(0); - dataSourceQuery.setRowLimit(-1); - dataSourceQuery.setRowOffset(0); - } catch (InvalidQueryException e) { - // Should not happen. - } - - // Let the data source group by all grouping/pivoting columns, and let it - // select all selection/pivoting columns, e.g., SELECT A, max(B) GROUP BY A PIVOT C turns - // into SELECT A, max(B), C GROUP BY A, C - - List newGroupColumns = Lists.newArrayList(); - List newSelectionColumns = Lists.newArrayList(); - if (dataSourceQuery.hasGroup()) { - // Same logic applies here, no calculated columns and no aggregations. - newGroupColumns.addAll(dataSourceQuery.getGroup().getColumns()); - } - newGroupColumns.addAll(pivotColumns); - if (dataSourceQuery.hasSelection()) { - newSelectionColumns.addAll(dataSourceQuery.getSelection().getColumns()); - } - newSelectionColumns.addAll(pivotColumns); - QueryGroup group = new QueryGroup(); - for (AbstractColumn col : newGroupColumns) { - group.addColumn(col); - } - dataSourceQuery.setGroup(group); - QuerySelection selection = new QuerySelection(); - for (AbstractColumn col : newSelectionColumns) { - selection.addColumn(col); - } - dataSourceQuery.setSelection(selection); - - // Build the completion query to group by the grouping columns. Because an aggregation is - // required, make a dummy aggregation on the original column by which the aggregation is - // required. - // This original column must be unique for a given set of values for the grouping/pivoting - // columns so any aggregation operation out of MIN, MAX, AVG will return the value - // itself and will not aggregate anything. The example from before, - // SELECT A, max(B) GROUP BY A PIVOT C turns into SELECT A, min(max-B) GROUP BY A PIVOT C - - completionQuery.copyFrom(query); - completionQuery.setFilter(null); - - QuerySelection completionSelection = new QuerySelection(); - List originalSelectedColumns = - query.getSelection().getColumns(); - for (int i = 0; i < originalSelectedColumns.size(); i++) { - AbstractColumn column = originalSelectedColumns.get(i); - if (query.getGroup().getColumns().contains(column)) { - completionSelection.addColumn(column); - } else { // Must be an aggregation column if doesn't appear in the grouping. - // The id here is the id generated by the data source for the column containing - // the aggregated data, e.g., max-B. - String id = column.getId(); - // MIN is chosen arbitrarily, because there will be exactly one. - completionSelection.addColumn( - new AggregationColumn(new SimpleColumn(id), AggregationType.MIN)); - } - } - - completionQuery.setSelection(completionSelection); - } else { - // When there is no pivoting, sql does everything (except skipping, options, labels, format). - dataSourceQuery.copyFrom(query); - dataSourceQuery.setOptions(null); - completionQuery.setOptions(query.getOptions()); - try { - // If there is skipping pagination should be done in the completion query - if (query.hasRowSkipping()) { - dataSourceQuery.setRowSkipping(0); - dataSourceQuery.setRowLimit(-1); - dataSourceQuery.setRowOffset(0); - - completionQuery.copyRowSkipping(query); - completionQuery.copyRowLimit(query); - completionQuery.copyRowOffset(query); - } - if (query.hasLabels()) { - dataSourceQuery.setLabels(null); - QueryLabels labels = query.getLabels(); - QueryLabels newLabels = new QueryLabels(); - for (AbstractColumn column : labels.getColumns()) { - newLabels.addLabel(new SimpleColumn(column.getId()), labels.getLabel(column)); - } - completionQuery.setLabels(newLabels); - } - if (query.hasUserFormatOptions()) { - dataSourceQuery.setUserFormatOptions(null); - QueryFormat formats = query.getUserFormatOptions(); - QueryFormat newFormats = new QueryFormat(); - for (AbstractColumn column : formats.getColumns()) { - newFormats.addPattern(new SimpleColumn(column.getId()), formats.getPattern(column)); - } - completionQuery.setUserFormatOptions(newFormats); - } - } catch (InvalidQueryException e) { - // Should not happen. - } - } - return new QueryPair(dataSourceQuery, completionQuery); - } - - /** - * Splits the query for a data source with capabilities SORT_AND_PAGINATION. - * Algorithm: if the query has filter, grouping, pivoting or skipping requirements the query is - * split as in the NONE case. - * If the query does not have filter, grouping, pivoting or skipping the data source query - * receives any sorting or pagination requirements and the completion query receives - * any selection requirements. - * - * @param query The query to split. - * - * @return The split query. - */ - private static QueryPair splitSortAndPagination(Query query) { - if (!query.getAllScalarFunctionsColumns().isEmpty()) { - Query completionQuery = new Query(); - completionQuery.copyFrom(query); - return new QueryPair(new Query(), completionQuery); - } - - Query dataSourceQuery = new Query(); - Query completionQuery = new Query(); - if (query.hasFilter() || query.hasGroup() || query.hasPivot()) { - // The query is copied to the completion query. - completionQuery.copyFrom(query); - } else { - // The execution order of the 3 relevant operators is: - // sort -> skip -> paginate (limit and offset). - // Skipping is not a possible data source capability, Therefore: - // 1. Sorting can be performed in the data source query. - // 2. Pagination should be performed in the data source query IFF skipping - // isn't stated in the original query. - dataSourceQuery.setSort(query.getSort()); - if (query.hasRowSkipping()) { - completionQuery.copyRowSkipping(query); - completionQuery.copyRowLimit(query); - completionQuery.copyRowOffset(query); - } else { - dataSourceQuery.copyRowLimit(query); - dataSourceQuery.copyRowOffset(query); - } - - completionQuery.setSelection(query.getSelection()); - completionQuery.setOptions(query.getOptions()); - completionQuery.setLabels(query.getLabels()); - completionQuery.setUserFormatOptions(query.getUserFormatOptions()); - } - return new QueryPair(dataSourceQuery, completionQuery); - } - - /** - * Splits the query for a data source with capabilities SELECT. - * Algorithm: the data source query receives any select operation from the query, however the - * completion query also receives selection to properly post-process the result. - * - * @param query The query to split. - * - * @return The split query. - */ - private static QueryPair splitSelect(Query query) { - Query dataSourceQuery = new Query(); - Query completionQuery = new Query(); - if (query.getSelection() != null) { - QuerySelection selection = new QuerySelection(); - for (String simpleColumnId : query.getAllColumnIds()) { - selection.addColumn(new SimpleColumn(simpleColumnId)); - } - // Column selection can be empty. For example, for query "SELECT 1". - dataSourceQuery.setSelection(selection); - } - - completionQuery.copyFrom(query); - return new QueryPair(dataSourceQuery, completionQuery); - } -} diff --git a/src/main/java/com/google/visualization/datasource/ResponseWriter.java b/src/main/java/com/google/visualization/datasource/ResponseWriter.java deleted file mode 100755 index 220c189..0000000 --- a/src/main/java/com/google/visualization/datasource/ResponseWriter.java +++ /dev/null @@ -1,198 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource; - -import com.google.visualization.datasource.base.DataSourceParameters; -import com.google.visualization.datasource.base.OutputType; - -import java.io.IOException; - -import javax.servlet.ServletOutputStream; -import javax.servlet.http.HttpServletResponse; - -/** - * A helper class responsible for writing a response message on a HttpServletResponse. - * - * @author Nimrod T. - */ -public class ResponseWriter { - - /** - * UTF-16LE byte-order mark required by TSV_EXCEL output type. - * @see OutputType#TSV_EXCEL - */ - private static final byte[] UTF_16LE_BOM = new byte[] {(byte) 0xff, (byte) 0xfe}; - - /** - * A private constructor. - */ - private ResponseWriter() {} - - /** - * Sets the specified responseMessage on the given HttpServletResponse. - * This method assumes the StatusType is 'OK'. - * - * @param responseMessage The response message. - * @param dataSourceParameters The datasource parameters. - * @param res The HTTP response. - * - * @throws IOException In case of a I/O error. - */ - public static void setServletResponse(String responseMessage, - DataSourceParameters dataSourceParameters, HttpServletResponse res) throws IOException { - OutputType type = dataSourceParameters.getOutputType(); - switch (type) { - case CSV: - setServletResponseCSV(dataSourceParameters, res); - writeServletResponse(responseMessage, res); - break; - case TSV_EXCEL: - setServletResponseTSVExcel(dataSourceParameters, res); - writeServletResponse(responseMessage, res, "UTF-16LE", UTF_16LE_BOM); - break; - case HTML: - setServletResponseHTML(res); - writeServletResponse(responseMessage, res); - break; - case JSONP: - setServletResponseJSONP(res); - writeServletResponse(responseMessage, res); - break; - case JSON: - setServletResponseJSON(res); - writeServletResponse(responseMessage, res); - break; - default: - // This should never happen. - throw new RuntimeException("Unhandled output type."); - } - } - - /** - * Sets the specified responseMessage on the given HttpServletResponse if - * the OutputType is CSV. - * This method assumes the StatusType is 'OK'. - * - * @param responseMessage The response message. - * @param dataSourceParameters The data source parameters. - * @param res The HTTP response. - * - * @throws IOException In case of a I/O error. - */ - static void setServletResponseCSV(DataSourceParameters dataSourceParameters, - HttpServletResponse res) { - res.setContentType("text/csv; charset=UTF-8"); - String outFileName = dataSourceParameters.getOutFileName(); - - // For security reasons, make sure the file extension is ".csv". - if (!outFileName.toLowerCase().endsWith(".csv")) { - outFileName = outFileName + ".csv"; - } - - res.setHeader("Content-Disposition", "attachment; filename=" + outFileName); - } - - /** - * Sets the HTTP servlet response for a TSV_EXCEL output type. - * This method assumes the StatusType is 'OK'. - * - * @param responseMessage The response message. - * @param dsParams The data source parameters. - * @param res The HTTP response. - * - * @throws IOException In case of a I/O error. - */ - static void setServletResponseTSVExcel(DataSourceParameters dsParams, - HttpServletResponse res) { - res.setContentType("text/csv; charset=UTF-16LE"); - String outFileName = dsParams.getOutFileName(); - res.setHeader("Content-Disposition", "attachment; filename=" + outFileName); - } - - /** - * Sets the HTTP servlet response for a HTML output type. - * This method assumes the StatusType is 'OK'. - * - * @param responseMessage The response message. - * @param res The HTTP response. - * - * @throws IOException In case of a I/O error. - */ - static void setServletResponseHTML(HttpServletResponse res) { - res.setContentType("text/html; charset=UTF-8"); - } - - /** - * Sets the HTTP servlet response for a JSONP output type. - * This method assumes the StatusType is 'OK'. - * - * @param responseMessage The response char sequence. - * @param res The HTTP response. - * - * @throws IOException In case of a I/O error. - */ - static void setServletResponseJSONP(HttpServletResponse res) { - res.setContentType("text/javascript; charset=UTF-8"); - } - - /** - * Sets the HTTP servlet response for a JSON output type. - * This method assumes the StatusType is 'OK'. - * - * @param responseMessage The response char sequence. - * @param res The HTTP response. - * - * @throws IOException In case of a I/O error. - */ - static void setServletResponseJSON(HttpServletResponse res) { - res.setContentType("application/json; charset=UTF-8"); - } - - /** - * Writes the response to the servlet response using UTF-8 charset without - * byte-order mark. - * - * @param responseMessage A charSequence to write to the servlet response. - * @param res The servlet response. - * - * @throws IOException In case of a I/O error. - */ - private static void writeServletResponse(CharSequence responseMessage, HttpServletResponse res) - throws IOException { - writeServletResponse(responseMessage, res, "UTF-8", null); - } - - /** - * Writes the response to the servlet response using specified charset and an - * optional byte-order mark. - * - * @param charSequence A charSequence to write to the servlet response. - * @param res The servlet response. - * @param charset A {@code String} specifying one of the character sets - * defined by IANA Character Sets - * (http://www.iana.org/assignments/character-sets). - * @param byteOrderMark An optional byte-order mark. - * - * @throws IOException In case of a I/O error. - */ - private static void writeServletResponse(CharSequence charSequence, HttpServletResponse res, - String charset, byte[] byteOrderMark) throws IOException { - ServletOutputStream outputStream = res.getOutputStream(); - if (byteOrderMark != null) { - outputStream.write(byteOrderMark); - } - outputStream.write(charSequence.toString().getBytes(charset)); - } -} diff --git a/src/main/java/com/google/visualization/datasource/base/BooleanFormat.java b/src/main/java/com/google/visualization/datasource/base/BooleanFormat.java deleted file mode 100755 index af631e7..0000000 --- a/src/main/java/com/google/visualization/datasource/base/BooleanFormat.java +++ /dev/null @@ -1,172 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.base; - -import com.ibm.icu.text.UFormat; - -import java.text.FieldPosition; -import java.text.ParseException; -import java.text.ParsePosition; - -/** - * A UFormat that performs formatting and parsing for boolean values. - * - * The string representation of boolean values is determined by two strings passed - * to the constructor of this class; a string for TRUE and a string for - * FALSE. - * - * Examples for text strings representing a BooleanValue that can be - * used in construction are: - * 1) true, false - * 2) TRUE, FALSE - * 2) t, f - * 3) yes, no - * 4) YES, NO - * 5) check, uncheck - * 6) Green, Red - * - * @author Hillel M. - */ - -public class BooleanFormat extends UFormat { - - /** - * A string representing the boolean value true. - */ - private String trueString; - - /** - * A string representing the boolean value false. - */ - private String falseString; - - /** - * Creates a BooleanFormat with default true/false formatting. - */ - public BooleanFormat() { - this("true", "false"); - } - - /** - * Creates a BooleanFormat. - * - * @param trueString A string representing true. - * @param falseString A string representing false. - */ - public BooleanFormat(String trueString, String falseString) { - if (trueString == null || falseString == null) { - throw new NullPointerException(); - } - this.trueString = trueString; - this.falseString = falseString; - } - - /** - * Constructs a boolean format from a pattern. The pattern must contain two - * strings separated by colon, for example: "true:false". - * - * @param pattern The pattern from which to construct. - */ - public BooleanFormat(String pattern) { - String[] valuePatterns = pattern.split(":"); - if (valuePatterns.length != 2) { - throw new IllegalArgumentException("Cannot construct a boolean format " - + "from " + pattern + ". The pattern must contain a single ':' " - + "character"); - } - this.trueString = valuePatterns[0]; - this.falseString = valuePatterns[1]; - } - - /** - * Formats a Boolean and appends the result to a StringBuffer. - * - * @param obj The object to format. - * @param appendTo The StringBuffer to which the formatted string will be appended. - * @param pos A FieldPosition param (not used in this class). - * - * @return A StringBuffer with the formatted string for this object. - */ - @Override - public StringBuffer format(Object obj, StringBuffer appendTo, FieldPosition pos) { - if ((null != obj) && !(obj instanceof Boolean)) { - throw new IllegalArgumentException(); - } - Boolean val = (Boolean) obj; - if (val == null) { - // nothing to append. - pos.setBeginIndex(0); - pos.setEndIndex(0); - } else if (val) { - appendTo.append(trueString); - pos.setBeginIndex(0); - pos.setEndIndex(trueString.length() - 1); - } else { - // val == false - appendTo.append(falseString); - pos.setBeginIndex(0); - pos.setEndIndex(falseString.length() - 1); - } - return appendTo; - } - - /** - * Parses a string into a {@code Boolean}. A string can be either a trueString - * or a falseString (non-case sensitive). - * - * @param source The string from which to parse. - * @param pos Marks the end of the parsing, or 0 if the parsing failed. - * - * @return A {@code Boolean} for the parsed string. - */ - @Override - public Boolean parseObject(String source, ParsePosition pos) { - if (source == null) { - throw new NullPointerException(); - } - Boolean value = null; - if (trueString.equalsIgnoreCase(source.trim())) { - value = Boolean.TRUE; - pos.setIndex(trueString.length()); - } else if (falseString.equalsIgnoreCase(source.trim())) { - value = Boolean.FALSE; - pos.setIndex(falseString.length()); - } - if (null == value) { - pos.setErrorIndex(0); - } - return value; - } - - /** - * Parses text from the beginning of the given string to produce a boolean. - * The method may not use the entire text of the given string. - * - * @param text A String that should be parsed from it's start. - * - * @return A {@code Boolean} parsed from the string. - * - * @exception ParseException If the string cannot be parsed. - */ - public Boolean parse(String text) throws ParseException { - ParsePosition parsePosition = new ParsePosition(0); - Boolean result = parseObject(text, parsePosition); - if (parsePosition.getIndex() == 0) { - throw new ParseException("Unparseable boolean: \"" + text + '"', - parsePosition.getErrorIndex()); - } - return result; - } -} diff --git a/src/main/java/com/google/visualization/datasource/base/DataSourceException.java b/src/main/java/com/google/visualization/datasource/base/DataSourceException.java deleted file mode 100755 index e668a4c..0000000 --- a/src/main/java/com/google/visualization/datasource/base/DataSourceException.java +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.base; - -/** - * An exception to be used by callers and callees of the library. - * Each exception has a type taken from ReasonType, and a - * message that can be used to output an appropriate message to the user. - * - * Example: - * new DataSourceException(ReasonType.InvalidQuery, "The query cannot be empty") - * - * @author Hillel M. - */ - -public class DataSourceException extends Exception { - - /** - * The reason for this exception. Used to set the reason type of this - * execution response by the thrower of this exception. - */ - private ReasonType reasonType; - - /** - * The error message to return to the user. - */ - private String messageToUser = null; - - /** - * A private constructor to prevent using this exception with no message. - */ - private DataSourceException() {} - - /** - * Constructs a new exception with a single message for the user. - * - * @param reasonType The reason type of the exception. - * @param messageToUser The message for the user. - */ - public DataSourceException(ReasonType reasonType, String messageToUser) { - super(messageToUser); - this.messageToUser = messageToUser; - this.reasonType = reasonType; - } - - /** - * Returns the message for the user. - * - * @return The message for the user. - */ - public String getMessageToUser() { - return messageToUser; - } - - /** - * Returns the reason type of this exception. - * - * @return The reason type of this exception. - */ - public ReasonType getReasonType() { - return reasonType; - } - - @Override @Deprecated - public String getMessage() { - return super.getMessage(); - } -} diff --git a/src/main/java/com/google/visualization/datasource/base/DataSourceParameters.java b/src/main/java/com/google/visualization/datasource/base/DataSourceParameters.java deleted file mode 100755 index bf24b75..0000000 --- a/src/main/java/com/google/visualization/datasource/base/DataSourceParameters.java +++ /dev/null @@ -1,247 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.base; - -import org.apache.commons.lang.StringUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -/** - * This class contains the data source parameters of the request. - * The data source parameters are extracted from the "tqx" URL parameter. - * - * @author Nimrod T. - */ -public class DataSourceParameters { - - /** - * Log. - */ - private static final Log log = LogFactory.getLog(DataSourceParameters.class.getName()); - - /** - * The name of the request id parameter as it appears in the "tqx" URL parameter. - */ - private static final String REQUEST_ID_PARAM_NAME = "reqId"; - - /** - * The name of the data signature parameter as it appears in the "tqx" URL parameter. - */ - private static final String SIGNATURE_PARAM_NAME = "sig"; - - /** - * The name of the output type parameter as it appears in the "tqx" URL parameter. - */ - private static final String OUTPUT_TYPE_PARAM_NAME = "out"; - - /** - * The name of the response handler parameter as it appears in the "tqx" URL parameter. - */ - private static final String RESPONSE_HANDLER_PARAM_NAME = "responseHandler"; - - /** - * The name of the filename parameter as it appears in the "tqx" URL parameter. - * This is relevant only if the "out" parameter is "csv". - * In that case, if the outFileName is given, - * this is the name of the csv that the datasource will output. - * Otherwise, if missing, the default filename (data.csv) is used. - */ - private static final String REQUEST_OUTFILENAME_PARAM_NAME = "outFileName"; - - /** - * A default error message. - */ - private static final String DEFAULT_ERROR_MSG = "Internal error"; - - /** - * The original string passed as the value of the "tqx" parameter. - */ - private String tqxValue = null; - - /** - * The request id. - */ - private String requestId = null; - - /** - * The signature. - */ - private String signature = null; - - /** - * The output type. - */ - private OutputType outputType = OutputType.defaultValue(); - - /** - * The response handler. - */ - private String responseHandler = "google.visualization.Query.setResponse"; - - /** - * The out filename. - */ - private String outFileName = "data.csv"; - - /** - * Returns a default DataSourceParameters object. - * - * @return A default DataSourceParameters object. - */ - public static DataSourceParameters getDefaultDataSourceParameters() { - DataSourceParameters dsParams = null; - try { - dsParams = new DataSourceParameters(null); - } catch (DataSourceException e) { - // Shouldn't be here. - } - return dsParams; - } - - /** - * Constructs a new instance of this class, with the given "tqx" string and parses it. - * - * Note: the "tqx" parameter is generated internally by the client side - * libraries. Thus, both the user and the developer will receive only short - * error messages regarding it. E.g., "Internal Error (code)". - * - * @param tqxValue The "tqx" string to parse. - * @throws DataSourceException Thrown if parsing of request parameters fails. - */ - public DataSourceParameters(String tqxValue) throws DataSourceException { - if (StringUtils.isEmpty(tqxValue)) { - // Return the default values in case tqx is empty. - return; - } - - this.tqxValue = tqxValue; - - // Split the tqx value to it's pair parts. - String[] parts = tqxValue.split(";"); - - // Loop over the parts. - for (String part : parts) { - // Each part should be a pair of key value. - String[] nameValuePair = part.split(":"); - if (nameValuePair.length != 2) { - log.error("Invalid name-value pair: " + part); - throw new DataSourceException(ReasonType.INVALID_REQUEST, - DEFAULT_ERROR_MSG + "(malformed)"); - } - - // Get the name and value. - String name = nameValuePair[0]; - String value = nameValuePair[1]; - - // Parse each part. - if (name.equals(REQUEST_ID_PARAM_NAME)) { - requestId = value; - } else if (name.equals(SIGNATURE_PARAM_NAME)) { - signature = value; - } else if (name.equals(OUTPUT_TYPE_PARAM_NAME)) { - outputType = OutputType.findByCode(value); - if (outputType == null) { - outputType = OutputType.defaultValue(); - } - } else if (name.equals(RESPONSE_HANDLER_PARAM_NAME)) { - responseHandler = value; - } else if (name.equals(REQUEST_OUTFILENAME_PARAM_NAME)) { - outFileName = value; - - // A heuristic that adds ".csv" if no . is provided. - if (!outFileName.contains(".")) { - outFileName += ".csv"; - } - } else { - // The server is tolerant to keys that it isn't - // aware of, to allow "Forward Compatibility" - // to later version. - } - } - } - - /** - * Returns the request id. - * - * @return The request id. - */ - public String getRequestId() { - return requestId; - } - - /** - * Returns the signature. - * - * @return The signature. - */ - public String getSignature() { - return signature; - } - - /** - * Sets the signature. - * - * @param signature The signature. - */ - public void setSignature(String signature) { - this.signature = signature; - } - - /** - * Returns the output type. - * - * @return The output type. - */ - public OutputType getOutputType() { - return outputType; - } - - /** - * Sets the output type. - * - * @param outputType The output type. - */ - public void setOutputType(OutputType outputType) { - this.outputType = outputType; - } - - /** - * Returns the response handler. - * - * @return The response handler. - */ - public String getResponseHandler() { - // Remove characters that can be a threat when injecting scripts. - return responseHandler.replaceAll("[^a-zA-Z0-9_\\.]", ""); - } - - /** - * Returns the out file name. - * - * @return The out file name. - */ - public String getOutFileName() { - return outFileName; - } - - /** - * Returns the "tqx" value. - * - * @return The "tqx" value. - */ - public String getTqxValue() { - return tqxValue; - } -} diff --git a/src/main/java/com/google/visualization/datasource/base/ErrorMessages.java b/src/main/java/com/google/visualization/datasource/base/ErrorMessages.java deleted file mode 100755 index e71da72..0000000 --- a/src/main/java/com/google/visualization/datasource/base/ErrorMessages.java +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.base; - -import java.util.ListResourceBundle; - -/** - * A resource bundle that contains all the error messages for a datasource in the en-US locale. - * This is the default locale used in this library. - * - * @author Yaniv S. - */ -public class ErrorMessages extends ListResourceBundle { - - /** - * The contents of this bundle. A key to message map. - */ - static final Object[][] CONTENTS = { - {"UNKNOWN_DATA_SOURCE_ID", "Unknown data source ID"}, - {"ACCESS_DENIED", "Access denied"}, - {"USER_NOT_AUTHENTICATED", "User not signed in"}, - {"UNSUPPORTED_QUERY_OPERATION", "Unsupported query operation"}, - {"INVALID_QUERY", "Invalid query"}, - {"INVALID_REQUEST", "Invalid request"}, - {"INTERNAL_ERROR", "Internal error"}, - {"NOT_SUPPORTED", "Operation not supported"}, - {"DATA_TRUNCATED", "Retrieved data was truncated"}, - {"NOT_MODIFIED", "Data not modified"}, - {"TIMEOUT", "Request timeout"}, - {"ILLEGAL_FORMATTING_PATTERNS", "Illegal formatting patterns"}, - {"OTHER", "Could not complete request"}, - {"SIGN_IN", "Sign in"}, - // QUERY Errors - {"NO_COLUMN", "Column [{0}] does not exist in table."}, - {"AVG_SUM_ONLY_NUMERIC", - "'Average' and 'sum' aggreagation functions can be applied only on numeric values."}, - {"INVALID_AGG_TYPE", "Invalid aggregation type: {0}"}, - // Parse - {"PARSE_ERROR", "Query parse error: {0}"}, - {"CANNOT_BE_IN_GROUP_BY", "Column [{0}] cannot be in GROUP BY because it has an aggregation."}, - {"CANNOT_BE_IN_PIVOT", "Column [{0}] cannot be in PIVOT because it has an aggregation."}, - {"CANNOT_BE_IN_WHERE", "Column [{0}] cannot appear in WHERE because it has an aggregation."}, - {"SELECT_WITH_AND_WITHOUT_AGG", - "Column [{0}] cannot be selected both with and without aggregation in SELECT."}, - {"COL_AGG_NOT_IN_SELECT", - "Column [{0}] which is aggregated in SELECT, cannot appear in GROUP BY."}, - {"CANNOT_GROUP_WITNOUT_AGG", "Cannot use GROUP BY when no aggregations are defined in SELECT."}, - {"CANNOT_PIVOT_WITNOUT_AGG", "Cannot use PIVOT when no aggregations are defined in SELECT."}, - {"AGG_IN_SELECT_NO_PIVOT", - "Column [{0}] which is aggregated in SELECT, cannot appear in PIVOT."}, - {"FORMAT_COL_NOT_IN_SELECT", - "Column [{0}] which is referenced in FORMAT, is not part of SELECT clause."}, - {"LABEL_COL_NOT_IN_SELECT", - "Column [{0}] which is referenced in LABEL, is not part of SELECT clause."}, - {"ADD_COL_TO_GROUP_BY_OR_AGG", - "Column [{0}] should be added to GROUP BY, removed from SELECT, or aggregated in SELECT."}, - {"AGG_IN_ORDER_NOT_IN_SELECT", - "Aggregation [{0}] found in ORDER BY but was not found in SELECT"}, - {"NO_AGG_IN_ORDER_WHEN_PIVOT", - "Column [{0}] cannot be aggregated in ORDER BY when PIVOT is used."}, - {"COL_IN_ORDER_MUST_BE_IN_SELECT", - "Column [{0}] which appears in ORDER BY, must be in SELECT as well, " + - "because SELECT contains aggregated columns."}, - {"NO_COL_IN_GROUP_AND_PIVOT", "Column [{0}] cannot appear both in GROUP BY and in PIVOT."}, - {"INVALID_OFFSET", "Invalid value for row offset: {0}"}, - {"INVALID_SKIPPING", "Invalid value for row skipping: {0}"}, - {"COLUMN_ONLY_ONCE", "Column [{0}] cannot appear more than once in {1}."} - - - }; - - /** - * Returns the error messages. - * Note that this method exposes the inner array. This means it can be changed by the outside - * world. We are not cloning here to avoid the computation time hit. Please do not change the - * inner values unless you know what you are doing. - */ - @Override - public Object[][] getContents() { - return CONTENTS; - } -} diff --git a/src/main/java/com/google/visualization/datasource/base/InvalidQueryException.java b/src/main/java/com/google/visualization/datasource/base/InvalidQueryException.java deleted file mode 100755 index 403cca6..0000000 --- a/src/main/java/com/google/visualization/datasource/base/InvalidQueryException.java +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.base; - -/** - * An exception that is thrown when trying to serve an invalid query. - * A query can fail at parsing time, or at later validations. - * - * @author Yonatan B.Y. - * @author Hillel M. - */ -public class InvalidQueryException extends DataSourceException { - - /** - * Construct a data source exception with an InvalidQuery reason type - * and a message to the user. - * - * @param messageToUser The message for the user. - */ - public InvalidQueryException(String messageToUser) { - super(ReasonType.INVALID_QUERY, messageToUser); - } -} diff --git a/src/main/java/com/google/visualization/datasource/base/LocaleUtil.java b/src/main/java/com/google/visualization/datasource/base/LocaleUtil.java deleted file mode 100755 index d899530..0000000 --- a/src/main/java/com/google/visualization/datasource/base/LocaleUtil.java +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.base; - -import com.ibm.icu.text.MessageFormat; -import com.ibm.icu.util.ULocale; - -import java.util.Locale; -import java.util.ResourceBundle; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * A utility class for locale handling. - * - * @author Yaniv S. - * - */ -public class LocaleUtil { - - /** - * Make the default constructor private. - */ - private LocaleUtil() {} - - /** - * A regular expression for extracting the language, country and variant from a locale string. - */ - private static final Pattern LOCALE_PATTERN = - Pattern.compile("(^[^_-]*)(?:[_-]([^_-]*)(?:[_-]([^_-]*))?)?"); - - /** - * The default locale. Used as a fall-back locale throughout the system. - */ - private static ULocale defaultLocale = ULocale.US; - - /** - * Converts a locale string from the RFC 3066 standard format to the Java locale format. - * You can call this on any locale string obtained from an external source - * (cookie, URL parameter, header, etc.). This method accepts more than just the standard - * format and will also tolerate capitalization discrepancies and the use of an underscore - * in place of a hyphen. - * - * @param s The locale string. - * - * @return The locale for the given locale string. - * - */ - public static Locale getLocaleFromLocaleString(String s) { - if (s == null) { - return null; - } - - Matcher matcher = LOCALE_PATTERN.matcher(s); - - // LOCALE_PATTERN will match any string, though it may not match the whole string. - // Specifically, it will not match a third _ or - or any subsequent text. - matcher.find(); - - String language = matcher.group(1); - language = (language == null) ? "" : language; - String country = matcher.group(2); - country = (country == null) ? "" : country; - String variant = matcher.group(3); - variant = (variant == null) ? "" : variant; - - return new Locale(language, country, variant); - } - - /** - * Sets the default locale. - * - * @param defaultLocale The default locale. - */ - public static void setDefaultLocale(ULocale defaultLocale) { - LocaleUtil.defaultLocale = defaultLocale; - } - - /** - * Returns the default locale. - * - * @return The default locale. - */ - public static ULocale getDefaultLocale() { - return defaultLocale; - } - - /** - * Returns a localized message from the specified ResourceBundle for the given key. - * In case the locale is null, uses the default locale. - * If locale is null, the default ResourceBundle is used. - * - * @param bundleName The name of the resource bundle. - * @param key The key of the requested string. - * @param locale The locale. - * - * @return A localized message from the bundle based on the given locale. - */ - public static String getLocalizedMessageFromBundle(String bundleName, String key, Locale locale) { - if (locale == null) { - // If no locale is specified, return the message in the default ResourceBundle. - return ResourceBundle.getBundle(bundleName).getString(key); - } - return ResourceBundle.getBundle(bundleName, locale).getString(key); - } - - /** - * Returns a localized message from the specified ResourceBundle for the given key - * with the given arguments inserted to the message in the specified locations. - * In case the locale is null, uses the default locale. - * If locale is null, the default ResourceBundle is used. - * - * - * @param bundleName The name of the resource bundle. - * @param key The key of the requested string. - * @param args Arguments to place in the error message. - * @param locale The locale. - * - * @return A localized message from the bundle based on the given locale. - */ - public static String getLocalizedMessageFromBundleWithArguments(String bundleName, String key, - String[] args, Locale locale) { - String rawMesage = getLocalizedMessageFromBundle(bundleName, key, locale); - if (args != null && args.length > 0) { - return MessageFormat.format(rawMesage, args); - } - return rawMesage; - } -} diff --git a/src/main/java/com/google/visualization/datasource/base/MessagesEnum.java b/src/main/java/com/google/visualization/datasource/base/MessagesEnum.java deleted file mode 100644 index 151b951..0000000 --- a/src/main/java/com/google/visualization/datasource/base/MessagesEnum.java +++ /dev/null @@ -1,246 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.base; - -import com.google.common.collect.Maps; - -import com.ibm.icu.util.ULocale; - -import java.util.Locale; -import java.util.Map; - -/** - * An enum for messages used in the DataSource library. Each element references a message - * in {@code ErrorMessages}. For example all the error messages produced in query parsing are - * listed here. - * - * @author Hillel M. - */ -public enum MessagesEnum { - - /** - * Column in query is missing from the data table. - * @param column id. - */ - NO_COLUMN, - - /** - * Average and sum aggregation can be applied only on numeric columns. - */ - AVG_SUM_ONLY_NUMERIC, - - /** - * Invalid aggregation type. - * @param aggregation type. - */ - INVALID_AGG_TYPE, - - /** - * An error when parsing the query. - * @param detailed message. - */ - PARSE_ERROR, - - /** - * Column can not be in group by because it has an aggregation. - * @param column id - */ - CANNOT_BE_IN_GROUP_BY, - - /** - * Column can not be in pivot because it has an aggregation. - * @param column id - */ - CANNOT_BE_IN_PIVOT, - - /** - * Column can not be in where because it has an aggregation. - * @param column id - */ - CANNOT_BE_IN_WHERE, - - /** - * Column can not appear in select with and without aggregation. - * @param column id. - */ - SELECT_WITH_AND_WITHOUT_AGG, - - /** - * Column which is aggregated in SELECT, cannot appear in GROUP BY. - * @param column id - */ - COL_AGG_NOT_IN_SELECT, - - /** - * Cannot use GROUP BY when no aggregations are defined in SELECT. - */ - CANNOT_GROUP_WITNOUT_AGG, - - /** - * Cannot use PIVOT when no aggregations are defined in SELECT. - */ - CANNOT_PIVOT_WITNOUT_AGG, - - /** - * Column which is aggregated in SELECT, cannot appear in PIVOT. - * @param column id - */ - AGG_IN_SELECT_NO_PIVOT, - - /** - * Column which is referenced in FORMAT, is not part of SELECT clause. - * @param column id - */ - FORMAT_COL_NOT_IN_SELECT, - - /** - * Column which is referenced in LABEL, is not part of SELECT clause. - * @param column id - */ - LABEL_COL_NOT_IN_SELECT, - - /** - * Column should be added to GROUP BY, removed from SELECT, or aggregated in SELECT. - * @param column id - */ - ADD_COL_TO_GROUP_BY_OR_AGG, - - - /** - * Aggregation found in ORDER BY but was not found in SELECT. - * @param aggreation column - */ - AGG_IN_ORDER_NOT_IN_SELECT, - - /** - * Column cannot be aggregated in ORDER BY when PIVOT is used. - * @param aggregation column - */ - NO_AGG_IN_ORDER_WHEN_PIVOT, - - /** - * Column which appears in ORDER BY, must be in SELECT as well, because SELECT - * contains aggregated columns. - */ - COL_IN_ORDER_MUST_BE_IN_SELECT, - - /** - * Column cannot appear both in GROUP BY and in PIVOT. - * @param column id - */ - NO_COL_IN_GROUP_AND_PIVOT, - - /** - * Invalid value for row offset. - * @param value - */ - INVALID_OFFSET, - - /** - * Invalid value for row skipping. - * @param value - */ - INVALID_SKIPPING, - - /** - * Column cannot appear more than once. - * @param column id - * @param clause - */ - COLUMN_ONLY_ONCE; - - /** - * A mapping from reason type to message. - */ - private static final Map - QUERY_ERROR_TO_MESSAGE = Maps.newEnumMap(MessagesEnum.class); - - static { - QUERY_ERROR_TO_MESSAGE.put(MessagesEnum.NO_COLUMN, - "NO_COLUMN"); - QUERY_ERROR_TO_MESSAGE.put(MessagesEnum.AVG_SUM_ONLY_NUMERIC, - "AVG_SUM_ONLY_NUMERIC"); - QUERY_ERROR_TO_MESSAGE.put(MessagesEnum.INVALID_AGG_TYPE, - "INVALID_AGG_TYPE"); - QUERY_ERROR_TO_MESSAGE.put(MessagesEnum.PARSE_ERROR, - "PARSE_ERROR"); - QUERY_ERROR_TO_MESSAGE.put(MessagesEnum.CANNOT_BE_IN_GROUP_BY, - "CANNOT_BE_IN_GROUP_BY"); - QUERY_ERROR_TO_MESSAGE.put(MessagesEnum.CANNOT_BE_IN_PIVOT, - "CANNOT_BE_IN_PIVOT"); - QUERY_ERROR_TO_MESSAGE.put(MessagesEnum.CANNOT_BE_IN_WHERE, - "CANNOT_BE_IN_WHERE"); - QUERY_ERROR_TO_MESSAGE.put(MessagesEnum.SELECT_WITH_AND_WITHOUT_AGG, - "SELECT_WITH_AND_WITHOUT_AGG"); - QUERY_ERROR_TO_MESSAGE.put(MessagesEnum.COL_AGG_NOT_IN_SELECT, - "COL_AGG_NOT_IN_SELECT"); - QUERY_ERROR_TO_MESSAGE.put(MessagesEnum.CANNOT_GROUP_WITNOUT_AGG, - "CANNOT_GROUP_WITNOUT_AGG"); - QUERY_ERROR_TO_MESSAGE.put(MessagesEnum.CANNOT_PIVOT_WITNOUT_AGG, - "CANNOT_PIVOT_WITNOUT_AGG"); - QUERY_ERROR_TO_MESSAGE.put(MessagesEnum.AGG_IN_SELECT_NO_PIVOT, - "AGG_IN_SELECT_NO_PIVOT"); - QUERY_ERROR_TO_MESSAGE.put(MessagesEnum.FORMAT_COL_NOT_IN_SELECT, - "FORMAT_COL_NOT_IN_SELECT"); - QUERY_ERROR_TO_MESSAGE.put(MessagesEnum.LABEL_COL_NOT_IN_SELECT, - "LABEL_COL_NOT_IN_SELECT"); - QUERY_ERROR_TO_MESSAGE.put(MessagesEnum.ADD_COL_TO_GROUP_BY_OR_AGG, - "ADD_COL_TO_GROUP_BY_OR_AGG"); - QUERY_ERROR_TO_MESSAGE.put(MessagesEnum.AGG_IN_ORDER_NOT_IN_SELECT, - "AGG_IN_ORDER_NOT_IN_SELECT"); - QUERY_ERROR_TO_MESSAGE.put(MessagesEnum.NO_AGG_IN_ORDER_WHEN_PIVOT, - "NO_AGG_IN_ORDER_WHEN_PIVOT"); - QUERY_ERROR_TO_MESSAGE.put(MessagesEnum.COL_IN_ORDER_MUST_BE_IN_SELECT, - "COL_IN_ORDER_MUST_BE_IN_SELECT"); - QUERY_ERROR_TO_MESSAGE.put(MessagesEnum.NO_COL_IN_GROUP_AND_PIVOT, - "NO_COL_IN_GROUP_AND_PIVOT"); - QUERY_ERROR_TO_MESSAGE.put(MessagesEnum.INVALID_OFFSET, - "INVALID_OFFSET"); - QUERY_ERROR_TO_MESSAGE.put(MessagesEnum.INVALID_SKIPPING, - "INVALID_SKIPPING"); - QUERY_ERROR_TO_MESSAGE.put(MessagesEnum.COLUMN_ONLY_ONCE, - "COLUMN_ONLY_ONCE"); - } - - - /** - * Returns a localized message for this reason type and locale. - * - * @param locale The locale. - * @param args An array of arguments. - * - * @return A localized message given a reason type and locale. - */ - public String getMessageWithArgs(ULocale ulocale, String... args) { - Locale locale = ulocale != null ? ulocale.toLocale() : null; - return LocaleUtil.getLocalizedMessageFromBundleWithArguments( - "com.google.visualization.datasource.base.ErrorMessages", QUERY_ERROR_TO_MESSAGE.get(this), - args, locale); - } - - /** - * Returns a localized message for this reason type and locale. - * - * @param locale The locale. - * - * @return A localized message given a reason type and locale. - */ - public String getMessage(ULocale ulocale) { - Locale locale = ulocale != null ? ulocale.toLocale() : null; - return LocaleUtil.getLocalizedMessageFromBundle( - "com.google.visualization.datasource.base.ErrorMessages", QUERY_ERROR_TO_MESSAGE.get(this), - locale); - } -} diff --git a/src/main/java/com/google/visualization/datasource/base/OutputType.java b/src/main/java/com/google/visualization/datasource/base/OutputType.java deleted file mode 100755 index ac7f6be..0000000 --- a/src/main/java/com/google/visualization/datasource/base/OutputType.java +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.base; - -/** - * Enumeration of the supported output formats for the data source. - * This enumeration almost exactly correlates to the "out" parameter of the wire protocol, except - * JSONP which is never explicitly specified in the "out" parameter. - * - * @author Nimrod T. - */ -public enum OutputType { - HTML("html"), - JSON("json"), - JSONP("jsonp"), - CSV("csv"), - - /** - * Output type value for tab-separated values encoded using UTF-16 - * little-endian with byte-order mark supported by Microsoft Excel. - * - * UTF-8 encoding used by {@link #CSV} output type is not supported by Excel. - * The Unicode encoding understood by Excel is UTF-16 little-endian with - * byte-order mark. Excel also does not support comma delimiter in UTF-16 - * encoded files, however, it supports tab delimiter. - * - * The default output filename for Excel should have a {@code .csv} extension in - * spite of containing tab-separated values because Excel does not - * automatically associate with files having {@code .tsv} extension. - */ - TSV_EXCEL("tsv-excel"); - - /** - * The code used to encode the output type in the tqx parameter. - */ - private String code; - - /** - * Constructs a new instance of this class with the given code. - * - * @param code Used to encode the output type in the tqx parameter. - */ - OutputType(String code) { - this.code = code; - } - - /** - * Returns the code for this OutputType. - * - * @return The code for this OutputType. - */ - public String getCode() { - return code; - } - - /** - * Finds the OutputType that matches the given code. - * - * @param code The code to search for. - * - * @return The OutputType that matches the given code or null if none are found. - */ - public static OutputType findByCode(String code) { - for (OutputType t : values()) { - if (t.code.equals(code)) { - return t; - } - } - return null; - } - - /** - * Returns the default OutputType. - * - * @return The default OutputType. - */ - public static OutputType defaultValue() { - return JSON; - } -} diff --git a/src/main/java/com/google/visualization/datasource/base/ReasonType.java b/src/main/java/com/google/visualization/datasource/base/ReasonType.java deleted file mode 100755 index 553ef17..0000000 --- a/src/main/java/com/google/visualization/datasource/base/ReasonType.java +++ /dev/null @@ -1,156 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.base; - -import com.google.common.collect.Maps; - -import java.util.Locale; -import java.util.Map; - -/** - * Possible reasons for errors or warnings. - * - * @author Hillel M. - */ -public enum ReasonType { - - /** - * The user has no access to the requested data. - */ - ACCESS_DENIED, - - /** - * The user cannot be authenticated. Used when the data requires - * authentication. Enable the data source to distinguish between - * 'no user' and 'user has no access' scenarios. - */ - USER_NOT_AUTHENTICATED, - - /** - * The query sent to the data source contains an operation that - * the data source does not support. - */ - UNSUPPORTED_QUERY_OPERATION, - - /** - * The query sent to the data source contains invalid data. - */ - INVALID_QUERY, - - /** - * The request from the client is invalid. - */ - INVALID_REQUEST, - - /** - * An internal error occured. - */ - INTERNAL_ERROR, - - /** - * This operation is not supported. - */ - NOT_SUPPORTED, - - /** - * Not all data is retrieved. - */ - DATA_TRUNCATED, - - /** - * The data hasn't been changed (signatures are the same). - */ - NOT_MODIFIED, - - /** - * The request has timed out. This is used only in the client, it is defined here for - * completeness. - */ - TIMEOUT, - - /** - * Illegal user given formatting patterns. - */ - ILLEGAL_FORMATTING_PATTERNS, - - /** - * Any other error that occured and prevented the data source from completing the action. - */ - OTHER; - - /** - * A mapping from reason type to message. - */ - private static final Map - REASON_TYPE_TO_MESSAGE = Maps.newEnumMap(ReasonType.class); - - static { - REASON_TYPE_TO_MESSAGE.put(ReasonType.ACCESS_DENIED, - "ACCESS_DENIED"); - REASON_TYPE_TO_MESSAGE.put(ReasonType.USER_NOT_AUTHENTICATED, - "USER_NOT_AUTHENTICATED"); - REASON_TYPE_TO_MESSAGE.put(ReasonType.UNSUPPORTED_QUERY_OPERATION, - "UNSUPPORTED_QUERY_OPERATION"); - REASON_TYPE_TO_MESSAGE.put(ReasonType.INVALID_QUERY, - "INVALID_QUERY"); - REASON_TYPE_TO_MESSAGE.put(ReasonType.INVALID_REQUEST, - "INVALID_REQUEST"); - REASON_TYPE_TO_MESSAGE.put(ReasonType.INTERNAL_ERROR, - "INTERNAL_ERROR"); - REASON_TYPE_TO_MESSAGE.put(ReasonType.NOT_SUPPORTED, - "NOT_SUPPORTED"); - REASON_TYPE_TO_MESSAGE.put(ReasonType.DATA_TRUNCATED, - "DATA_TRUNCATED"); - REASON_TYPE_TO_MESSAGE.put(ReasonType.NOT_MODIFIED, - "NOT_MODIFIED"); - REASON_TYPE_TO_MESSAGE.put(ReasonType.TIMEOUT, - "TIMEOUT"); - REASON_TYPE_TO_MESSAGE.put(ReasonType.ILLEGAL_FORMATTING_PATTERNS, - "ILLEGAL_FORMATTING_PATTERNS"); - REASON_TYPE_TO_MESSAGE.put(ReasonType.OTHER, - "OTHER"); - } - - /** - * Returns a localized message for this reason type and locale. - * - * @param locale The locale. - * - * @return A localized message given a reason type and locale. - */ - public String getMessageForReasonType(Locale locale) { - return LocaleUtil.getLocalizedMessageFromBundle( - "com.google.visualization.datasource.base.ErrorMessages", REASON_TYPE_TO_MESSAGE.get(this), - locale); - } - - /** - * Returns a message for this reason type in the default locale. - * - * @return A message message for this reason type in the default locale. - */ - public String getMessageForReasonType() { - return getMessageForReasonType(null); - } - - /** - * Returns a lower case string of this enum. - * - * @return a lower case string of this enum - */ - public String lowerCaseString() { - return this.toString().toLowerCase(); - } -} diff --git a/src/main/java/com/google/visualization/datasource/base/ResponseStatus.java b/src/main/java/com/google/visualization/datasource/base/ResponseStatus.java deleted file mode 100755 index 599e0e9..0000000 --- a/src/main/java/com/google/visualization/datasource/base/ResponseStatus.java +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.base; - -/** - * A response status holds three parameters: - * 1) The response type (Ok, Warning or Error). - * 2) The response reason type. - * 3) A string with an error message to the user. - * - * @author Hillel M. - */ -public class ResponseStatus { - - /** - * The response status type. - */ - private StatusType statusType; - - /** - * The response reason type (if OK or ERROR). - */ - private ReasonType reasonType; - - /** - * A message to be passed to the user (if ERROR). - */ - private String description; - - /** - * The sign in message key in the ResourceBundle - */ - public static final String SIGN_IN_MESSAGE_KEY = "SIGN_IN"; - - /** - * Constructs a response status object. - * This object contains a status type, reason type, - * and a message that is sent to the user. - * - * @param statusType The response status type. - * @param reasonType The response reason type. - * @param description A message to be passed to the user. - */ - public ResponseStatus(StatusType statusType, ReasonType reasonType, String description) { - this.statusType = statusType; - this.reasonType = reasonType; - this.description = description; - } - - /** - * Creates a ResponseStatus for the given DataSourceException. - * - * @param dse The data source exception. - * - * @return A response status object for the given data source exception. - */ - public static ResponseStatus createResponseStatus(DataSourceException dse) { - return new ResponseStatus(StatusType.ERROR, dse.getReasonType(), dse.getMessageToUser()); - } - - /** - * Gets a modified response status in case of ReasonType#USER_NOT_AUTHENTICATED - * by adding a sign in html link for the given url. If no url is provided in the - * ResponseStatus# no change is made. - * - * @param responseStatus The response status. - * - * @return The modified response status if modified, or else the original response status. - */ - public static ResponseStatus getModifiedResponseStatus(ResponseStatus responseStatus) { - - String signInString = LocaleUtil.getLocalizedMessageFromBundle( - "com.google.visualization.datasource.base.ErrorMessages", SIGN_IN_MESSAGE_KEY, null); - if (responseStatus.getReasonType() == ReasonType.USER_NOT_AUTHENTICATED) { - String msg = responseStatus.getDescription(); - if (!msg.contains(" ") - && (msg.startsWith("http://") - || msg.startsWith("https://"))) { - // The description is assumed to be a link to sign in page, transform the message into - // an html snippet of a link. - StringBuilder sb = new StringBuilder("") - .append(signInString) - .append(""); - responseStatus = new ResponseStatus(responseStatus.getStatusType(), - responseStatus.getReasonType(), sb.toString()); - } - } - return responseStatus; - } - - public ResponseStatus(StatusType statusType) { - this(statusType, null, null); - } - - /** - * Returns the response status type. - * - * @return the response status type. - */ - public StatusType getStatusType() { - return statusType; - } - - /** - * Returns the response reason type. - * - * @return the response reason type. - */ - public ReasonType getReasonType() { - return reasonType; - } - - /** - * Returns the message to pass to the user. - * - * @return The message to pass to the user. - */ - public String getDescription() { - return description; - } -} diff --git a/src/main/java/com/google/visualization/datasource/base/StatusType.java b/src/main/java/com/google/visualization/datasource/base/StatusType.java deleted file mode 100755 index f3f1a92..0000000 --- a/src/main/java/com/google/visualization/datasource/base/StatusType.java +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.base; - -/** - * An enum value to represent the status of a response. - * - * @author Hillel M. - */ -public enum StatusType { - - /** - * The query completed successfully and the data can be returned. - */ - OK, - - /** - * The query failed to complete. In this case, no data table is passed in the response. - */ - ERROR, - - /** - * The query completed with a warning. In some cases, part of the data is returned. - */ - WARNING; - - /** - * Returns a lower case string of this enum. - * - * @return a lower case string of this enum. - */ - public String lowerCaseString() { - return this.toString().toLowerCase(); - } -} diff --git a/src/main/java/com/google/visualization/datasource/base/TextFormat.java b/src/main/java/com/google/visualization/datasource/base/TextFormat.java deleted file mode 100755 index 31e238b..0000000 --- a/src/main/java/com/google/visualization/datasource/base/TextFormat.java +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.base; - -import com.ibm.icu.text.UFormat; - -import java.text.FieldPosition; -import java.text.ParsePosition; - -/** - * A UFormat that performs (dummy) formatting and parsing of text (string) values. - * - * This class is required only to be consistent with the UFormat API, its methods do nothing. - * - * @author Hillel M. - */ -public class TextFormat extends UFormat { - - /** - * Formats a TextValue and appends the result to a StringBuffer. - * - * @param obj The object to format. - * @param appendTo The StringBuffer to which the formatted string is appended. - * @param pos A FieldPosition parameter not used in this case. - * - * @return A StringBuffer with the formatted string for this object. - */ - @Override - public StringBuffer format(Object obj, StringBuffer appendTo, FieldPosition pos) { - if ((null == obj) || !(obj instanceof String)) { - throw new IllegalArgumentException(); - } - String text = (String) obj; - appendTo.append(text); - pos.setBeginIndex(0); - if (0 == text.length()) { - pos.setEndIndex(0); - } else { - pos.setEndIndex(text.length() - 1); - } - return appendTo; - } - - /** - * Parse a string into a TextValue. - * - * If this method is used to parse an empty string and it is called via - * Format.parseObject(Object) a ParseException is thrown. - * - * @param source The string to parse from. - * @param pos Marks the end of the parsing or 0 if the parsing failed. - * - * @return A BooleanValue for the parsed string. - * - * @throws NullPointerException if pos is null or source is null. - */ - @Override - public Object parseObject(String source, ParsePosition pos) { - if ((null == pos) || (null == source)) { - throw new NullPointerException(); - } - pos.setIndex(source.length()); - return source; - } -} diff --git a/src/main/java/com/google/visualization/datasource/base/TypeMismatchException.java b/src/main/java/com/google/visualization/datasource/base/TypeMismatchException.java deleted file mode 100755 index 90ca754..0000000 --- a/src/main/java/com/google/visualization/datasource/base/TypeMismatchException.java +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.base; - -/** - * This exception is thrown when there is a mismatch between a value type and a column type, - * for example when trying to assign a boolean value to a column of type number. - * - * @author Yaniv S. - */ -public class TypeMismatchException extends DataSourceException { - - /** - * Constructs a new exception with OTHER reason type and a message for the user. - * - * @param message The message for the user. - */ - public TypeMismatchException(String message) { - super(ReasonType.OTHER, message); - } -} diff --git a/src/main/java/com/google/visualization/datasource/base/Warning.java b/src/main/java/com/google/visualization/datasource/base/Warning.java deleted file mode 100755 index ca0e00d..0000000 --- a/src/main/java/com/google/visualization/datasource/base/Warning.java +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.base; - -/** - * A warning generated while processing a request. - * - * @author Yonatan B.Y. - */ -public class Warning { - - /** - * The reason for this warning. - */ - private ReasonType reasonType; - - /** - * The warning message to return to the user. - */ - private String messageToUser; - - /** - * Constructs a new exception with a reason type and a message for the user. - * - * @param reasonType The reason type of the exception. - * @param messageToUser The message to the user. - */ - public Warning(ReasonType reasonType, String messageToUser) { - this.messageToUser = messageToUser; - this.reasonType = reasonType; - } - - /** - * Returns the reason. - * - * @return The reason. - */ - public ReasonType getReasonType() { - return reasonType; - } - - /** - * Returns the message. - * - * @return The message. - */ - public String getMessage() { - return messageToUser; - } -} diff --git a/src/main/java/com/google/visualization/datasource/datatable/ColumnDescription.java b/src/main/java/com/google/visualization/datasource/datatable/ColumnDescription.java deleted file mode 100755 index 6213086..0000000 --- a/src/main/java/com/google/visualization/datasource/datatable/ColumnDescription.java +++ /dev/null @@ -1,199 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.datatable; - -import com.google.common.collect.Maps; -import com.google.visualization.datasource.datatable.value.ValueType; - -import java.util.Collections; -import java.util.Map; - -/** - * Holds all the information we keep for a single column in a {@link DataTable}. - * This does not include all the values, which are kept in {@link TableCell}s. - * The information that is included is: - *
    - *
  • Data type (see {@link ValueType})
  • - *
  • Id - used mainly for referencing columns in queries (see - * {@link com.google.visualization.datasource.query.Query}))
  • - *
  • Label - used mainly for display purposes
  • - *
  • Custom properties - can be used for any purpose.
  • - *
- * - * @author Yoah B.D. - */ -public class ColumnDescription { - - /** - * The column's identifier. - * This Id is used in query sort, filter and other query elements that - * need to refer to specific columns. - */ - private String id; - - /** - * The column's data type. - */ - private ValueType type; - - /** - * The column's displayed name. - */ - private String label; - - /** - * The column's formatting pattern. The pattern may be empty, otherwise indicates - * the formatting pattern in which the column is already, or should be, formatted. - */ - private String pattern; - - /** - * Custom properties for this column. - */ - private Map customProperties = null; - - /** - * Creates a new column description. - * - * @param id The column's identifier. - * @param type The column's data type. - * @param label The column's displayed name (label). - */ - public ColumnDescription(String id, ValueType type, String label) { - this.id = id; - this.type = type; - this.label = label; - this.pattern = ""; //empty by default - } - - /** - * Returns the column id. - * - * @return The column id. - */ - public String getId() { - return id; - } - - /** - * Returns the column type. - * - * @return The column type. - */ - public ValueType getType() { - return type; - } - - /** - * Returns the column label. - * - * @return The column label. - */ - public String getLabel() { - return label; - } - - /** - * Returns the column pattern. - * - * @return The column pattern. - */ - public String getPattern() { - return pattern; - } - - /** - * Sets a column pattern. - * - * @param pattern A pattern to set for this column. - */ - public void setPattern(String pattern) { - this.pattern = pattern; - } - - /** - * Sets a column label. - * - * @param label A label to set for this column. - */ - public void setLabel(String label) { - this.label = label; - } - - /** - * Retrieves a custom property. Returns null if it does not exist. - * - * @param key The property key. - * - * @return The property value, or null if it does not exist. - */ - public String getCustomProperty(String key) { - if (customProperties == null) { - return null; - } - if (key == null) { - throw new RuntimeException("Null keys are not allowed."); - } - return customProperties.get(key); - } - - /** - * Sets a custom property. - * - * @param propertyKey The property key. - * @param propertyValue The property value. - */ - public void setCustomProperty(String propertyKey, String propertyValue) { - if (customProperties == null) { - customProperties = Maps.newHashMap(); - } - if ((propertyKey == null) || (propertyValue == null)) { - throw new RuntimeException("Null keys/values are not allowed."); - } - customProperties.put(propertyKey, propertyValue); - } - - /** - * Returns an immutable map of the custom properties. - * - * @return An immutable map of the custom properties. - */ - public Map getCustomProperties() { - if (customProperties == null) { - return Collections.emptyMap(); - } - return Collections.unmodifiableMap(customProperties); - } - - /** - * Returns a clone of the ColumnDescription, meaning a column descriptor with the exact - * same properties. This is a deep clone as it copies all custom properties. - * - * @return The cloned ColumnDescription. - */ - @Override - public ColumnDescription clone() { - ColumnDescription result = new ColumnDescription(id, type, label); - result.setPattern(pattern); - - if (customProperties != null) { - result.customProperties = Maps.newHashMap(); - for (Map.Entry entry : customProperties.entrySet()) { - result.customProperties.put(entry.getKey(), entry.getValue()); - } - } - return result; - } -} diff --git a/src/main/java/com/google/visualization/datasource/datatable/DataTable.java b/src/main/java/com/google/visualization/datasource/datatable/DataTable.java deleted file mode 100755 index 334a546..0000000 --- a/src/main/java/com/google/visualization/datasource/datatable/DataTable.java +++ /dev/null @@ -1,599 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.datatable; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.collect.Ordering; -import com.google.common.collect.Sets; -import com.google.visualization.datasource.base.TypeMismatchException; -import com.google.visualization.datasource.base.Warning; -import com.google.visualization.datasource.datatable.value.Value; -import com.google.visualization.datasource.datatable.value.ValueType; - -import com.ibm.icu.util.ULocale; - -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * A table of data, arranged in typed columns. - * - * An instance of this class is the result of a request to a data source. A DataTable - * can be rendered in many ways: JSON, HTML, CSV (see - * {@link com.google.visualization.datasource.render}), and can be manipulated using queries (see - * {@link com.google.visualization.datasource.query.Query} and - * {@link com.google.visualization.datasource.query.engine.QueryEngine}). - * - * A table contains any number of typed columns (see (@link ColumnDescription}) each with an id and - * a label, and any number of rows. Each row must have as many cells as there are columns - * in the table, and the types of values in the cells must match the types of the columns. - * Each cell contains, as well as the typed value, a formatted value of type string, used for - * display purposes. - * Also, you can use the custom properties mechanism to hold any other data you require. There are - * custom properties on every cell, row, column, and on the entire table. - * - * @author Yoah B.D. - */ -public class DataTable { - - /** - * Column descriptions. - */ - private List columns; - - /** - * Map from a column to its index in the columns list. - */ - private Map columnIndexById; - - /** - * The list of returned rows. - */ - private List rows; - - /** - * Custom properties for this table. - */ - private Map customProperties = null; - - /** - * A list of warnings. - */ - private List warnings; - - /** - * The user locale, used to create localized messages. - */ - private ULocale localeForUserMessages = null; - - /** - * Create a new empty result. - */ - public DataTable() { - columns = Lists.newArrayList(); - columnIndexById = Maps.newHashMap(); - rows = Lists.newArrayList(); - warnings = Lists.newArrayList(); - } - - /** - * Adds a single row to the end of the result. Throws a TypeMismatchException if the row's cells - * do not match the current columns. If the row is too short, i.e., has too few cells, then the - * remaining columns are filled with null values (the given row is changed). - * - * @param row The row of values. - * - * @throws TypeMismatchException Thrown if the values in the cells do not match the columns. - */ - public void addRow(TableRow row) throws TypeMismatchException { - List cells = row.getCells(); - if (cells.size() > columns.size()) { - throw new TypeMismatchException("Row has too many cells. Should be at most of size: " + - columns.size()); - } - for (int i = 0; i < cells.size(); i++) { - if (cells.get(i).getType() != columns.get(i).getType()) { - throw new TypeMismatchException("Cell type does not match column type, at index: " + i + - ". Should be of type: " + columns.get(i).getType().toString()); - } - } - for (int i = cells.size(); i < columns.size(); i++) { - row.addCell(new TableCell(Value.getNullValueFromValueType(columns.get(i).getType()))); - } - - rows.add(row); - } - - /** - * A convenience method for creating a row directly from its cell values and - * adding it to the data table. - * - * @param values The row values. - * @throws TypeMismatchException Thrown if a value does not match its - * corresponding column. - */ - public void addRowFromValues(Object... values) throws TypeMismatchException { - Iterator columnIt = columns.listIterator(); - int i = 0; - TableRow row = new TableRow(); - - while (i < values.length && columnIt.hasNext()) { - ColumnDescription colDesc = columnIt.next(); - row.addCell(colDesc.getType().createValue(values[i])); - i++; - } - addRow(row); - } - - /** - * Adds a collection of rows to the end of the result. - * - * @param rowsToAdd The row collection. - */ - public void addRows(Collection rowsToAdd) throws TypeMismatchException { - for (TableRow row : rowsToAdd) { - addRow(row); - } - } - - /** - * Sets a collection of rows after clearing any current rows. - * - * @param rows The row collection. - */ - public void setRows(Collection rows) throws TypeMismatchException { - this.rows.clear(); - addRows(rows); - } - - /** - * Returns the list of all table rows. - * - * @return The list of all table rows. - */ - public List getRows() { - return rows; - } - - /** - * Returns the row at the given index. - * - * @param rowIndex the index of the requested row. - * - * @return The row at the given index. - */ - public TableRow getRow(int rowIndex) { - return rows.get(rowIndex); - } - - /** - * Returns the number of rows in this data table. - * - * @return The number of rows. - */ - public int getNumberOfRows() { - return rows.size(); - } - - /** - * Returns the number of columns in this data table. - * - * @return The number of columns. - */ - public int getNumberOfColumns() { - return columns.size(); - } - - /** - * Returns the list of all column descriptions. - * - * @return The list of all column descriptions. The returned list is - * immutable. - */ - public List getColumnDescriptions() { - return ImmutableList.copyOf(columns); - } - - /** - * Returns the column description of a column by its index. - * - * @param colIndex The column index. - * - * @return The column description. - */ - public ColumnDescription getColumnDescription(int colIndex) { - return columns.get(colIndex); - } - - /** - * Returns the column description of a column by it's id. - * - * @param columnId The id of the column. - * - * @return The column description of the specified column. - */ - public ColumnDescription getColumnDescription(String columnId) { - return columns.get(getColumnIndex(columnId)); - } - - /** - * Returns the list of all cells of a certain column, by the column index. - * Note: This is the most naive implementation, that for each request - * to this method just creates a new List of the needed cells. - * - * @param columnIndex The index of the requested column. - * - * @return The list of all cells of the requested column. - */ - public List getColumnCells(int columnIndex) { - List colCells = - Lists.newArrayListWithCapacity(getNumberOfRows()); - - for (TableRow row : getRows()) { - colCells.add(row.getCell(columnIndex)); - } - return colCells; - } - - /** - * Add a column to the table. - * - * @param columnDescription The column's description. - */ - public void addColumn(ColumnDescription columnDescription) { - String columnId = columnDescription.getId(); - if (columnIndexById.containsKey(columnId)) { - throw new RuntimeException("Column Id [" + columnId + "] already in table description"); - } - - columnIndexById.put(columnId, columns.size()); - columns.add(columnDescription); - for (TableRow row : rows) { - row.addCell(new TableCell(Value.getNullValueFromValueType(columnDescription.getType()))); - } - } - - /** - * Adds columns to the table. - * - * @param columnsToAdd The columns to add. - */ - public void addColumns(Collection columnsToAdd) { - for (ColumnDescription column : columnsToAdd) { - addColumn(column); - } - } - - /** - * Returns the column index in the columns of a row (first is zero). - * - * @param columnId The id of the column. - * - * @return The column index in the columns of a row (first is zero). - */ - public int getColumnIndex(String columnId) { - return columnIndexById.get(columnId); - } - - /** - * Returns the list of all cells of a certain column, by the column Id. - * - * @param columnId The id of the requested column. - * - * @return The list of all cells of the requested column. - */ - public List getColumnCells(String columnId) { - return getColumnCells(getColumnIndex(columnId)); - } - - /** - * Returns the cell at the specified row and column indexes. - * - * @param rowIndex The row index. - * @param colIndex The column index. - * - * @return The cell. - */ - public TableCell getCell(int rowIndex, int colIndex) { - return getRow(rowIndex).getCell(colIndex); - } - - /** - * Replaces an existing cell at a specified position in this table with the specified cell. - * The value type of the new cell must match the type of the existing one. - * - * @param rowIndex The row index. - * @param colIndex The column index. - * @param cell The cell to be stored at the specified position. - * - * @return The cell that was replaced. - * - * @throws TypeMismatchException Thrown if the new cell value type doesn't match - * the table column value type. - * @throws IndexOutOfBoundsException Thrown if the position is out of range. - */ - public TableCell setCell(int rowIndex, int colIndex, TableCell cell) - throws TypeMismatchException, IndexOutOfBoundsException { - TableRow row = rows.get(rowIndex); - if (!row.getCell(colIndex).getType().equals(cell.getType())) { - throw new TypeMismatchException("New cell value type does not match expected value type." + - " Expected type: " + row.getCell(colIndex).getType() + - " but was: " + cell.getType().toString()); - } - return row.setCell(colIndex, cell); - } - - /** - * Returns the value in the cell at the specified row and column indexes. - * - * @param rowIndex The row index. - * @param colIndex The column index. - * - * @return The value in the cell. - */ - public Value getValue(int rowIndex, int colIndex) { - return getCell(rowIndex, colIndex).getValue(); - } - - /** - * Returns the list of warnings in this table. The list returned is immutable. - * - * @return The list of warnings in this table. - */ - public List getWarnings() { - return ImmutableList.copyOf(warnings); - } - - /** - * Returns a sorted list of distinct table cells in the specified column. - * The cells are sorted according to the given comparator in ascending order. - * - * @param columnIndex The index of the required column. - * @param comparator A Comparator for TableCells. - * - * @return A sorted list of distinct table cells in the specified column. - */ - public List getColumnDistinctCellsSorted(int columnIndex, - Comparator comparator) { - // Get only the distinct Table cells (based on the comparator) - Set colCells = Sets.newTreeSet(comparator); - for (TableCell cell : getColumnCells(columnIndex)) { - colCells.add(cell); - } - - // Return the list of distinct Table cells sorted (based on the comparator). - return Ordering.from(comparator).sortedCopy(colCells); - } - - /** - * Returns an ordered list of all the distinct values of a single column. - * - * @param columnIndex The index of the requested column. - * - * @return An ordered list of all the distinct values of a single - * column. - */ - List getColumnDistinctValues(int columnIndex) { - Set values = Sets.newTreeSet(); - for (TableRow row : getRows()) { - values.add(row.getCell(columnIndex).getValue()); - } - return Lists.newArrayList(values); - } - - /** - * Adds a warning. - * - * @param warning The warning to add. - */ - public void addWarning(Warning warning) { - warnings.add(warning); - } - - /** - * Returns an ordered list of all the distinct values of a single column. - * - * @param columnId The id of the requested column. - * - * @return An ordered list of all the distinct values of a single - * column. - */ - List getColumnDistinctValues(String columnId) { - return getColumnDistinctValues(getColumnIndex(columnId)); - } - - /** - * Returns whether or not the table contains a column named columnId. - * - * @param columnId The column id to check. - * - * @return True if columnId exists in this table, false otherwise. - */ - public boolean containsColumn(String columnId) { - return columnIndexById.containsKey(columnId); - } - - /** - * Check that all the cols in colIds are in the data. - * - * @param colIds A list of column ids. - * - * @return True if all the columns are in the data table, false otherwise. - */ - public boolean containsAllColumnIds(Collection colIds) { - - for (String id : colIds) { - if (!containsColumn(id)) { - return false; - } - } - return true; - - } - - /** - * Returns a data table with str as the content of its single cell. - * - * @param str The cell's content - * @return A data table with str as the content of its single cell. - */ - public static DataTable createSingleCellTable(String str) { - DataTable dataTable = new DataTable(); - ColumnDescription colDesc = new ColumnDescription("SingleCellTable", - ValueType.TEXT, ""); - dataTable.addColumn(colDesc); - TableRow row = new TableRow(); - row.addCell(new TableCell(str)); - - try { - dataTable.addRow(row); - } catch (TypeMismatchException e) { - // Should not happen. We control the column description. - } - - return dataTable; - } - - /** - * Returns a new data table, with the same data and metadata as this one. - * Any change to the returned table should not change this table and vice - * versa. This is a deep clone. - * - * @return The cloned data table. - */ - @Override - public DataTable clone() { - DataTable result = new DataTable(); - - for (ColumnDescription column : columns) { - result.addColumn(column.clone()); - } - try { - for (TableRow row : rows) { - result.addRow(row.clone()); - } - } catch (TypeMismatchException e) { - // Should not happen. We assume this table is valid. - } - if (customProperties != null) { - result.customProperties = Maps.newHashMap(); - for (Map.Entry entry : customProperties.entrySet()) { - result.customProperties.put(entry.getKey(), entry.getValue()); - } - } - result.warnings = Lists.newArrayList(); - for (Warning warning : warnings) { - result.warnings.add(warning); - } - result.setLocaleForUserMessages(localeForUserMessages); - - return result; - } - - /** - * Retrieves a custom property. Returns null if it does not exist. - * - * @param key The property key. - * - * @return The property value, or null if it does not exist. - */ - public String getCustomProperty(String key) { - if (customProperties == null) { - return null; - } - if (key == null) { - throw new RuntimeException("Null keys are not allowed."); - } - return customProperties.get(key); - } - - /** - * Sets a custom property. - * - * @param propertyKey The property key. - * @param propertyValue The property value. - */ - public void setCustomProperty(String propertyKey, String propertyValue) { - if (customProperties == null) { - customProperties = Maps.newHashMap(); - } - if ((propertyKey == null) || (propertyValue == null)) { - throw new RuntimeException("Null keys/values are not allowed."); - } - customProperties.put(propertyKey, propertyValue); - } - - /** - * Returns an immutable map of the custom properties. - * - * @return An immutable map of the custom properties. - */ - public Map getCustomProperties() { - if (customProperties == null) { - return Collections.emptyMap(); - } - return Collections.unmodifiableMap(customProperties); - } - - /** - * Returns a string representation of the data table. - * Useful mainly for debugging. - * - * @return A string representation of the data table. - */ - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - - for (int rowIndex = 0; rowIndex < rows.size(); rowIndex++) { - TableRow tableRow = rows.get(rowIndex); - for (int cellIndex = 0; cellIndex < tableRow.getCells().size(); cellIndex++) { - TableCell tableCell = tableRow.getCells().get(cellIndex); - sb.append(tableCell.toString()); - if (cellIndex < tableRow.getCells().size() - 1) { - sb.append(","); - } - } - if (rowIndex < rows.size() - 1) { - sb.append("\n"); - } - } - - return sb.toString(); - } - - /** - * Sets the user locale for creating localized messages. - * @param userLocale the user locale. - */ - public void setLocaleForUserMessages(ULocale localeForUserMessges) { - this.localeForUserMessages = localeForUserMessges; - } - - /** - * Returns the locale to use to create localized user messages. - * @return The locale for user messages. - */ - public ULocale getLocaleForUserMessages() { - return localeForUserMessages; - } -} diff --git a/src/main/java/com/google/visualization/datasource/datatable/TableCell.java b/src/main/java/com/google/visualization/datasource/datatable/TableCell.java deleted file mode 100755 index 6692a35..0000000 --- a/src/main/java/com/google/visualization/datasource/datatable/TableCell.java +++ /dev/null @@ -1,259 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.datatable; - -import com.google.common.collect.Maps; -import com.google.visualization.datasource.datatable.value.BooleanValue; -import com.google.visualization.datasource.datatable.value.NumberValue; -import com.google.visualization.datasource.datatable.value.TextValue; -import com.google.visualization.datasource.datatable.value.Value; -import com.google.visualization.datasource.datatable.value.ValueType; -import com.ibm.icu.util.ULocale; - -import java.util.Collections; -import java.util.Comparator; -import java.util.Map; - -/** - * A single cell in a {@link DataTable}. - * - * Contains a value, a formatted value, and a dictionary of custom properties. - * The value should match the type of the column in which it resides. See {@link ColumnDescription}. - * The formatted value is used for display purposes. The custom properties can be used for any - * purpose. - * - * @author Yoah B.D. - */ -public class TableCell { - - /** - * The internal value of this cell. - */ - private Value value; - - /** - * The formatted value for this cell. - */ - private String formattedValue = null; - - /** - * Custom properties for this cell. - */ - private Map customProperties = null; - - /** - * Returns a comparator that compares table cells according to their inner - * values and, in the case of text values, according to a given locale. - * - * @param ulocale The ULocale defining the order relation of text values. - * - * @return A comparator that compares table cells according to their inner - * values and, in the case of text values, according to a given locale. - */ - public static Comparator getLocalizedComparator( - final ULocale ulocale) { - return new Comparator() { - private Comparator textValueComparator = - TextValue.getTextLocalizedComparator(ulocale); - - @Override - public int compare(TableCell cell1, TableCell cell2) { - if (cell1 == cell2) { - return 0; - } - if (cell1.getType() == ValueType.TEXT) { - return textValueComparator.compare((TextValue) cell1.value, - (TextValue) cell2.value); - } else { - return cell1.getValue().compareTo(cell2.getValue()); - } - } - }; - } - - /** - * Returns the formatted value of this cell. - * - * @return The formatted value of this cell. - */ - public String getFormattedValue() { - return formattedValue; - } - - /** - * Set a formatted value for the value in this table cell. - * - * @param formattedValue The formatted value to set. - */ - public void setFormattedValue(String formattedValue) { - this.formattedValue = formattedValue; - } - - /** - * Construct a new TableCell with the parameter as the inner value. - * - * @param value The inner value of this cell. - */ - public TableCell(Value value) { - this.value = value; - } - - - /** - * Construct a new TableCell with the parameter as the inner value and with - * a FormattedValue representing this.value. - * - * @param value The inner value of this cell. - * @param formattedValue The formatted form of this value. - */ - public TableCell(Value value, String formattedValue) { - this.value = value; - this.formattedValue = formattedValue; - } - - /** - * Copy constructor. - * - * @param other The other table cell to construct from. - */ - public TableCell(TableCell other) { - this(other.value, other.formattedValue); - } - /** - * Constructs a new TableCell with a text value. - * - * @param value The inner text value of this cell. - */ - public TableCell(String value) { - this.value = new TextValue(value); - } - - /** - * Constructs a new TableCell with a boolean value. - * - * @param value The inner boolean value of this cell. - */ - public TableCell(boolean value) { - this.value = BooleanValue.getInstance(value); - } - - /** - * Constructs a new TableCell with a number value. - * - * @param value The inner number value of this cell. - */ - public TableCell(double value) { - this.value = new NumberValue(value); - } - - /** - * Returns the inner value of this cell. - * - * @return The inner value of this cell. - */ - public Value getValue() { - return value; - } - - /** - * Returns the type of this cell. - * - * @return The type of this cell. - */ - public ValueType getType() { - return value.getType(); - } - - /** - * Tests whether this cell's value is a logical null. - * - * @return Indication whether the call's value is null. - */ - public boolean isNull() { - return value.isNull(); - } - - /** - * Returns the String representation of the inner value. - * - * @return The String representation of the inner value. - */ - @Override - public String toString() { - return value.toString(); - } - - /** - * Retrieves a custom property. Returns null if it does not exist. - * - * @param key The property key. - * - * @return The property value, or null if it does not exist. - */ - public String getCustomProperty(String key) { - if (customProperties == null) { - return null; - } - if (key == null) { - throw new RuntimeException("Null keys are not allowed."); - } - return customProperties.get(key); - } - - /** - * Sets a custom property. - * - * @param propertyKey The property key. - * @param propertyValue The property value. - */ - public void setCustomProperty(String propertyKey, String propertyValue) { - if (customProperties == null) { - customProperties = Maps.newHashMap(); - } - if ((propertyKey == null) || (propertyValue == null)) { - throw new RuntimeException("Null keys/values are not allowed."); - } - customProperties.put(propertyKey, propertyValue); - } - - /** - * Returns an immutable map of the custom properties. - * - * @return An immutable map of the custom properties. - */ - public Map getCustomProperties() { - if (customProperties == null) { - return Collections.emptyMap(); - } - return Collections.unmodifiableMap(customProperties); - } - - /** - * Returns a copy of this TableCell. - * - * @return A copy of this TableCell. - */ - @Override - public TableCell clone() { - TableCell result = new TableCell(value, formattedValue); - if (customProperties != null) { - result.customProperties = Maps.newHashMap(); - for (Map.Entry entry : customProperties.entrySet()) { - result.customProperties.put(entry.getKey(), entry.getValue()); - } - } - return result; - } -} diff --git a/src/main/java/com/google/visualization/datasource/datatable/TableRow.java b/src/main/java/com/google/visualization/datasource/datatable/TableRow.java deleted file mode 100755 index 249f3e3..0000000 --- a/src/main/java/com/google/visualization/datasource/datatable/TableRow.java +++ /dev/null @@ -1,199 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.datatable; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.visualization.datasource.datatable.value.Value; - -import java.util.Collections; -import java.util.List; -import java.util.Map; - -/** - * A single row in a {@link DataTable}. - * - * The number of cells is expected to match the number of columns in the table, and the type - * of the value held in each cell is expected to match the type defined for the corresponding - * column. - * - * @author Yoah B.D. - */ -public class TableRow { - - /** - * A list of the cells in the row. - */ - private List cells = Lists.newArrayList(); - - /** - * Custom properties for the row. - */ - private Map customProperties = null; - - /** - * Create an empty row list. - */ - public TableRow() { - } - - /** - * Adds a single cell to the end of the row. - * - * @param cell The cell's value. - */ - public void addCell(TableCell cell) { - cells.add(cell); - } - - /** - * Adds a value of a single cell to the end of the row. - * - * @param value The inner value of the cell to add. - */ - public void addCell(Value value) { - addCell(new TableCell(value)); - } - - /** - * Adds a numeric value of a single cell to the end of the row. - * - * @param value The inner numeric value of the cell to add. - */ - public void addCell(double value) { - addCell(new TableCell(value)); - } - - /** - * Adds a boolean value of a single cell to the end of the row. - * - * @param value The inner boolean value of the cell to add. - */ - public void addCell(boolean value) { - addCell(new TableCell(value)); - } - - /** - * Adds a text value of a single cell to the end of the row. - * - * @param value The inner text value of the cell to add. - */ - public void addCell(String value) { - addCell(new TableCell(value)); - } - - /** - * Returns the list of all cell values. - * - * @return The list of all cell values. The returned list is - * immutable. - */ - public List getCells() { - return ImmutableList.copyOf(cells); - } - - /** - * Returns a single cell by its index. - * - * @param index The index of the cell to get. - * - * @return A single cell by it's index. - */ - public TableCell getCell(int index) { - return cells.get(index); - } - - /** - * Package protected function. - * Replaces the cell at the specified position in this row with the specified cell. - * The value type of the new cell must match the that of the replaced one. - * - * @param index The index of the cell to replace. - * @param cell The cell to be stored at the specified position. - * - * @return The cell that was replaced. - * - * @throws IndexOutOfBoundsException Thrown if the index out of range. - */ - TableCell setCell(int index, TableCell cell) throws IndexOutOfBoundsException { - return cells.set(index, cell); - } - - /** - * Retrieves a custom property. Returns null if it does not exist. - * - * @param key The property key. - * - * @return The property value, or null if it does not exist. - */ - public String getCustomProperty(String key) { - if (customProperties == null) { - return null; - } - if (key == null) { - throw new RuntimeException("Null keys are not allowed."); - } - return customProperties.get(key); - } - - /** - * Sets a custom property. - * - * @param propertyKey The property key. - * @param propertyValue The property value. - */ - public void setCustomProperty(String propertyKey, String propertyValue) { - if (customProperties == null) { - customProperties = Maps.newHashMap(); - } - if ((propertyKey == null) || (propertyValue == null)) { - throw new RuntimeException("Null keys/values are not allowed."); - } - customProperties.put(propertyKey, propertyValue); - } - - /** - * Returns an immutable map of the custom properties. - * - * @return An immutable map of the custom properties. - */ - public Map getCustomProperties() { - if (customProperties == null) { - return Collections.emptyMap(); - } - return Collections.unmodifiableMap(customProperties); - } - - /** - * Returns a clone of this TableRow. This is a deep clone. - * - * @return A clone of this TableRow. - */ - @Override - public TableRow clone() { - TableRow result = new TableRow(); - for (TableCell cell : cells) { - result.addCell(cell.clone()); - } - if (customProperties != null) { - result.customProperties = Maps.newHashMap(); - for (Map.Entry entry : customProperties.entrySet()) { - result.customProperties.put(entry.getKey(), entry.getValue()); - } - } - return result; - } -} diff --git a/src/main/java/com/google/visualization/datasource/datatable/ValueFormatter.java b/src/main/java/com/google/visualization/datasource/datatable/ValueFormatter.java deleted file mode 100755 index 76d3768..0000000 --- a/src/main/java/com/google/visualization/datasource/datatable/ValueFormatter.java +++ /dev/null @@ -1,433 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.datatable; - -import com.google.common.collect.Maps; -import com.google.visualization.datasource.base.BooleanFormat; -import com.google.visualization.datasource.base.LocaleUtil; -import com.google.visualization.datasource.base.TextFormat; -import com.google.visualization.datasource.datatable.value.BooleanValue; -import com.google.visualization.datasource.datatable.value.DateTimeValue; -import com.google.visualization.datasource.datatable.value.DateValue; -import com.google.visualization.datasource.datatable.value.NumberValue; -import com.google.visualization.datasource.datatable.value.TextValue; -import com.google.visualization.datasource.datatable.value.TimeOfDayValue; -import com.google.visualization.datasource.datatable.value.Value; -import com.google.visualization.datasource.datatable.value.ValueType; - -import com.ibm.icu.text.DecimalFormat; -import com.ibm.icu.text.DecimalFormatSymbols; -import com.ibm.icu.text.NumberFormat; -import com.ibm.icu.text.SimpleDateFormat; -import com.ibm.icu.text.UFormat; -import com.ibm.icu.util.GregorianCalendar; -import com.ibm.icu.util.TimeZone; -import com.ibm.icu.util.ULocale; - -import java.text.ParseException; -import java.util.Date; -import java.util.Map; - - -/** - * Formats a {@link Value}, or parses a string to create a {@link Value}. - * An instance of this class can be created using the - * {@link #createFromPattern(ValueType, String, ULocale)} method, and can then use the format - * and/or parse. - * - * The class also supplies a set of default patterns per {@link ValueType}. The default patterns - * can be used for parsing/formatting values when there is no specified pattern. - * Otherwise, create a class instance by specifying a pattern and locale. - * - * Note: This class is not thread safe since it uses {@code UFormat}. - * - * @author Yonatan B.Y. - */ - -public class ValueFormatter { - - /** - * A uFormat that does the actual formatting. - */ - private UFormat uFormat; - - /** - * The underlying pattern for the {@code UFormat}. - */ - private String pattern; - - /** - * The locale used for the UFormatter. - */ - private ULocale locale; - - /** - * The {@code ValueType}. - */ - private ValueType type; - - /** - * The default pattern for parsing a string to a text value. - * - * @see com.google.visualization.datasource.datatable.value.TextValue - */ - private static final String DEFAULT_TEXT_DUMMY_PATTERN = "dummy"; - - /** - * The default pattern for parsing a string to a date time value. - * - * @see DateTimeValue - */ - private static final String DEFAULT_DATETIME_PATTERN = "yyyy-MM-dd HH:mm:ss"; - - /** - * The default pattern for parsing a string to a date value. - * - * @see DateValue - */ - private static final String DEFAULT_DATE_PATTERNS = "yyyy-MM-dd"; - - /** - * The default pattern for parsing a string to a time of day value. - * - * @see TimeOfDayValue - */ - private static final String DEFAULT_TIMEOFDAY_PATTERN = "HH:mm:ss"; - - /** - * The default pattern for parsing a string to a boolean value. - * - * @see BooleanValue - */ - private static final String DEFAULT_BOOLEAN_PATTERN = "true:false"; - - /** - * The default pattern for parsing a string to a number value. - * - * @see NumberValue - */ - private static final String DEFAULT_NUMBER_PATTERN = ""; - - /** - * Private constructor that constructs an instance of this class from a UFormat. - * Use {@link #createFromPattern(ValueType, String, ULocale)} to create an instance. - */ - private ValueFormatter(String pattern, UFormat uFormat, ValueType type, ULocale locale) { - this.pattern = pattern; - this.uFormat = uFormat; - this.type = type; - this.locale = locale; - } - - /** - * Creates a formatter for the given value type with the given pattern string and locale. - * If the pattern is illegal returns null. - * If pattern is null, uses the first default pattern for the given type. - * If ulocale is null, uses the default locale return by {@code LocaleUtil#getDefaultLocale}. - * - * @param type The column value type. - * @param pattern The string pattern representing the formatter pattern. - * @param locale The ULocale of the formatter. - * - * @return A formatter for the given type, pattern and locale, or null if the pattern is illegal. - */ - public static ValueFormatter createFromPattern(ValueType type, String pattern, ULocale locale) { - UFormat uFormat = null; - if (pattern == null) { - pattern = getDefaultPatternByType(type); - } - - if (locale == null) { - locale = LocaleUtil.getDefaultLocale(); - } - - // For whichever formatter is created, try to format some arbitrary value, and see if an - // exception was thrown. If it was thrown, conclude the pattern was illegal, and return null. - try { - switch (type) { - case BOOLEAN: - uFormat = new BooleanFormat(pattern); - uFormat.format(BooleanValue.TRUE.getObjectToFormat()); - break; - case TEXT: - // Dummy format so no need to check it for problems. - uFormat = new TextFormat(); - break; - case DATE: - uFormat = new SimpleDateFormat(pattern, locale); - ((SimpleDateFormat) uFormat).setTimeZone(TimeZone.getTimeZone("GMT")); - uFormat.format(new DateValue(1995, 7, 3).getObjectToFormat()); - break; - case TIMEOFDAY: - uFormat = new SimpleDateFormat(pattern, locale); - ((SimpleDateFormat) uFormat).setTimeZone(TimeZone.getTimeZone("GMT")); - uFormat.format(new TimeOfDayValue(2, 59, 12, 123).getObjectToFormat()); - break; - case DATETIME: - uFormat = new SimpleDateFormat(pattern, locale); - ((SimpleDateFormat) uFormat).setTimeZone(TimeZone.getTimeZone("GMT")); - uFormat.format(new DateTimeValue(1995, 7, 3, 2, 59, 12, 123).getObjectToFormat()); - break; - case NUMBER: - DecimalFormatSymbols symbols = new DecimalFormatSymbols(locale); - uFormat = new DecimalFormat(pattern, symbols); - uFormat.format(new NumberValue(-12.3).getObjectToFormat()); - break; - } - } catch (RuntimeException e) { - // The formatter is illegal return null. - return null; - } - return new ValueFormatter(pattern, uFormat, type, locale); - } - - /** - * Creates a default formatter for the specified value type and locale. - * If locale is null, uses the default locale returned by {@code LocaleUtil#getDefaultLocale}. - * - * @param type The value type. - * @param locale The data table locale. - * - * @return A default formatter for the given type and locale. - */ - public static ValueFormatter createDefault(ValueType type, ULocale locale) { - String pattern = getDefaultPatternByType(type); - return createFromPattern(type, pattern, locale); - } - - /** - * Creates default formatters for all the value types for the specified locale. - * Returns a map of default formatters by type. - * The map can be used for iterating over a data table and parsing/formatting its values. - * - * @param locale The data table locale. - * - * @return A map of default formatters by type with the given locale. - */ - public static Map createDefaultFormatters(ULocale locale) { - Map foramtters = Maps.newHashMap(); - for (ValueType type : ValueType.values()) { - foramtters.put(type, createDefault(type, locale)); - } - return foramtters; - } - - /** - * Formats a value to a string, using the given pattern. - * - * @param value The value to format. - * - * @return The formatted value. - */ - public String format(Value value) { - if (value.isNull()) { - return ""; - } - return uFormat.format(value.getObjectToFormat()); - } - - - /** - * Creates the corresponding {@code Value} from the given string. - * If parsing fails, returns a NULL_VALUE for the specified type. - * For example, if val="3" and type=ValueType.Number, then after successfully parsing - * the string "3" into the double 3.0 a new NumberValue would - * be returned with an internal double value = 3. - * - * @param val The string to parse. - * - * @return A corresponding {@code Value} for the given string. If parsing fails the value would - * be a NULL_VALUE of the correct {@code ValueType}. - */ - public Value parse(String val) { - Value value = null; - try { - switch(type) { - case DATE: - value = parseDate(val); - break; - case TIMEOFDAY: - value = parseTimeOfDay(val); - break; - case DATETIME: - value = parseDateTime(val); - break; - case NUMBER: - value = parseNumber(val); - break; - case BOOLEAN: - value = parseBoolean(val); - break; - case TEXT: - // do nothing - value = new TextValue(val); - break; - } - } catch (ParseException pe) { - value = Value.getNullValueFromValueType(type); - } - return value; - } - - /** - * Returns the default pattern for the specified value type and index. - * - * @param type The value type. - * - * @return The default pattern for the specified value type and index. - */ - private static String getDefaultPatternByType(ValueType type) { - String defaultPattern; - switch (type) { - case TEXT: - defaultPattern = DEFAULT_TEXT_DUMMY_PATTERN; - break; - case DATE: - defaultPattern = DEFAULT_DATE_PATTERNS; - break; - case DATETIME: - defaultPattern = DEFAULT_DATETIME_PATTERN; - break; - case TIMEOFDAY: - defaultPattern = DEFAULT_TIMEOFDAY_PATTERN; - break; - case BOOLEAN: - defaultPattern = DEFAULT_BOOLEAN_PATTERN; - break; - case NUMBER: - defaultPattern = DEFAULT_NUMBER_PATTERN; - break; - default: - defaultPattern = null; - } - return defaultPattern; - } - - - - /** - * Parses a string to a boolean value. - * - * @param val The string to parse. - * - * @return A boolean value based on the given string. - * - * @throws ParseException if val cannot be parsed into a boolean value. - */ - private BooleanValue parseBoolean(String val) throws ParseException { - Boolean bool = ((BooleanFormat) uFormat).parse(val); - return BooleanValue.getInstance(bool); - } - - /** - * Parses a string to a number value. - * - * @param val The string to parse. - * - * @return A number value based on the given string. - * - * @throws ParseException If val cannot be parsed into a number value. - */ - private NumberValue parseNumber(String val) throws ParseException { - Number n = ((NumberFormat) uFormat).parse(val); - return new NumberValue(n.doubleValue()); - } - - /** - * Parses a string to a date time value. - * - * @param val The string to parse. - * - * @return A date time value based on the given string. - * - * @throws ParseException If val cannot be parsed into a date. - */ - private DateTimeValue parseDateTime(String val) throws ParseException { - Date date = ((SimpleDateFormat) uFormat).parse(val); - GregorianCalendar gc = new GregorianCalendar(TimeZone.getTimeZone("GMT")); - gc.setTime(date); - return new DateTimeValue(gc); - } - - /** - * Parses a string to a date value. - * - * @param val The string to parse. - * - * @return A date value based on the given string. - * - * @throws ParseException If val cannot be parsed into a date. - */ - private DateValue parseDate(String val) throws ParseException { - Date date = ((SimpleDateFormat) uFormat).parse(val); - GregorianCalendar gc = new GregorianCalendar(TimeZone.getTimeZone("GMT")); - gc.setTime(date); - return new DateValue(gc); - } - - /** - * Parses a string to a time of day value. - * - * @param val The string to parse. - * - * @return A time of day value based on the given string. - * - * @throws ParseException If val cannot be parsed into a date. - */ - private TimeOfDayValue parseTimeOfDay(String val) throws ParseException { - Date date = ((SimpleDateFormat) uFormat).parse(val); - GregorianCalendar gc = new GregorianCalendar(TimeZone.getTimeZone("GMT")); - gc.setTime(date); - return new TimeOfDayValue(gc); - } - - - - /** - * Returns the internal UFormat object. - * - * @return The internal UFormat object. - */ - public UFormat getUFormat() { - return uFormat; - } - - /** - * Returns the pattern for this formatter. - * - * @return The pattern for this formatter. - */ - public String getPattern() { - return pattern; -} - - /** - * Returns the ulocale. - * - * @return The ulocale. - */ - public ULocale getLocale() { - return locale; - } - - /** - * Returns the type. - * - * @return The type. - */ - public ValueType getType() { - return type; - } -} diff --git a/src/main/java/com/google/visualization/datasource/datatable/value/BooleanValue.java b/src/main/java/com/google/visualization/datasource/datatable/value/BooleanValue.java deleted file mode 100755 index dd47a28..0000000 --- a/src/main/java/com/google/visualization/datasource/datatable/value/BooleanValue.java +++ /dev/null @@ -1,168 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.datatable.value; - -/** - * A value of type boolean. Valid values are TRUE, FALSE and NULL_VALUE. - * - * @author Yoah B.D. - */ -public class BooleanValue extends Value { - - /** - * A single static null value. - */ - private static final BooleanValue NULL_VALUE = new BooleanValue(false); - - /** - * A single static TRUE value. - */ - public static final BooleanValue TRUE = new BooleanValue(true); - - /** - * A single static FALSE value. - */ - public static final BooleanValue FALSE = new BooleanValue(false); - - /** - * Static method to return the null value (same one for all calls) - * - * @return Null value. - */ - public static BooleanValue getNullValue() { - return NULL_VALUE; - } - - /** - * Static method to return a BooleanValue based on a given java boolean. - * If the parameter is null, returns NULL_VALUE. - * - * @param value The java Boolean value to be represented. - * - * @return The static predefined instance of the given value. - */ - public static BooleanValue getInstance(Boolean value) { - if (value == null) { - return NULL_VALUE; - } - return value ? TRUE : FALSE; - } - - /** - * The underlying value - */ - private boolean value; - - /** - * Create a new boolean value. - * This is private so users must use the three predefined values here (Null, - * true, and false), like an enum. - * - * @param value The underlying value. - */ - private BooleanValue(boolean value) { - this.value = value; - } - - @Override - public ValueType getType() { - return ValueType.BOOLEAN; - } - - /** - * Returns the underlying value. - * - * @return The underlying value. - */ - public boolean getValue() { - if (this == NULL_VALUE) { - throw new NullValueException("This null boolean has no value"); - } - return value; - } - - /** - * Returns the value with default formatting. - * - * @return The value with default formatting. - */ - @Override - public String toString() { - if (this == NULL_VALUE) { - return "null"; - } - return Boolean.toString(value); - } - - /** - * Tests whether this cell's value is a logical null. - * - * @return Indication if the call's value is null. - */ - @Override - public boolean isNull() { - return (this == NULL_VALUE); - } - - /** - * Compares this cell to another cell of the same type. - * - * @param other Other cell. - * - * @return 0 if equal, negative if this is smaller, positive if larger. - */ - @Override - public int compareTo(Value other) { - if (this == other) { - return 0; // If same cell, or both are null. - } - BooleanValue otherBoolean = (BooleanValue) other; - if (isNull()) { - return -1; - } - if (otherBoolean.isNull()) { - return 1; - } - return (value == otherBoolean.value ? 0 : (value ? 1 : -1)); - } - - /** - * Returns a hash code for this boolean value. - * - * @return A hash code for this boolean value. Null gets -1, false gets 0, - * true gets 1. - */ - @Override - public int hashCode() { - return (isNull() ? -1 : (value ? 1 : 0)); - } - - - @Override - public Boolean getObjectToFormat() { - if (isNull()) { - return null; - } - return value; - } - - /** - * {@inheritDoc} - */ - @Override - protected String innerToQueryString() { - return value ? "true" : "false"; - } -} diff --git a/src/main/java/com/google/visualization/datasource/datatable/value/DateTimeValue.java b/src/main/java/com/google/visualization/datasource/datatable/value/DateTimeValue.java deleted file mode 100755 index c5b444c..0000000 --- a/src/main/java/com/google/visualization/datasource/datatable/value/DateTimeValue.java +++ /dev/null @@ -1,308 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.datatable.value; - -import com.ibm.icu.util.Calendar; -import com.ibm.icu.util.GregorianCalendar; -import com.ibm.icu.util.TimeZone; - -/** - * A value of type date-time. Used to represent a specific day in a given year as well as a - * specific time during that day. This differs from {@link DateValue}, which represents only a - * specific day in a given year. - * DateTime is represented internally by a GregorianCalendar. The - * calendar is immutable and is kept only for validation of the input. - * - * @author Hillel M. - */ -public class DateTimeValue extends Value { - - /** - * A single static null value. - */ - private static final DateTimeValue NULL_VALUE = new DateTimeValue(); - - - /** - * Static method to return the null value (same one for all calls). - * - * @return Null value. - */ - public static DateTimeValue getNullValue() { - return NULL_VALUE; - } - - /** - * Underlying GregorianCalendar. - * The calendar is immutable and is set only in the constructor. - */ - private GregorianCalendar calendar; - - /** - * Stores the hash code for this DateTime. Do not use GregorianCalendar - * hash code since it does not consider time values and it might trigger - * internal changes in the calendar values. - * The hashCode of NULL_VALUE is zero. - */ - private Integer hashCode = null; - - /** - * Creates a new DateTime value. This constructor is private and is used - * only to create a NULL_VALUE for this class. - */ - private DateTimeValue() { - hashCode = 0; - } - - /** - * Creates a new DateTime value. - * The input is checked using a gregorian calendar. - * Note this uses the java convention for months: - * January = 0, ..., December = 11. - * - * @param year The year. - * @param month The month. - * @param dayOfMonth The day of month. - * @param hours The hours. - * @param minutes The minutes. - * @param seconds The seconds. - * @param milliseconds The milliseconds. - * - * @throws IllegalArgumentException Thrown if one of the - * parameters is illegal. - */ - public DateTimeValue(int year, int month, int dayOfMonth, int hours, - int minutes, int seconds, int milliseconds) { - // Constructs a GregorianCalendar with the given date and time. - calendar = new GregorianCalendar(year, month, dayOfMonth, hours, - minutes, seconds); - calendar.set(GregorianCalendar.MILLISECOND, milliseconds); - calendar.setTimeZone(TimeZone.getTimeZone("GMT")); - - // Check input. - // A RunTimeException is thrown here since it is very unusual for structured - // data to be incorrect. - if ((getYear() != year) - || (getMonth() != month) - || (getDayOfMonth() != dayOfMonth) - || (getHourOfDay() != hours) - || (getMinute() != minutes) - || (getSecond() != seconds) - || (getMillisecond() != milliseconds)) { - throw new IllegalArgumentException("Invalid java date " - + "(yyyy-MM-dd hh:mm:ss.S): " - + year + '-' + month + '-' + dayOfMonth + ' ' + hours + ':' - + minutes + ':' + seconds + '.' + milliseconds); - } - } - - /** - * Creates a new instance based on the given {@code GregorianCalendar}. - * The given calendar's time zone must be set to "GMT" as a precondition to - * use this constructor. - * Note: The date time values: year, month, dayOfMonth, hour, minute, second - * and millisecond correspond to the values returned by calendar.get(field) - * of the given calendar. - * - * @param calendar A Gregorian calendar on which to base this instance. - * - * @throws IllegalArgumentException When calendar time zone is not set - * to GMT. - */ - public DateTimeValue(GregorianCalendar calendar) { - if (!calendar.getTimeZone().equals(TimeZone.getTimeZone("GMT"))) { - throw new IllegalArgumentException( - "Can't create DateTimeValue from GregorianCalendar that is not GMT."); - } - this.calendar = (GregorianCalendar) calendar.clone(); - } - - /** - * Returns the year. - * - * @return The year. - */ - public int getYear() { - return calendar.get(GregorianCalendar.YEAR); - } - - /** - * Returns the month. The values are from 0 (January) to 11 (December). - * - * @return The month. - */ - public int getMonth() { - return calendar.get(GregorianCalendar.MONTH); - } - - /** - * Returns the day of month. The first day of the month is 1. - * - * @return The day of month. - */ - public int getDayOfMonth() { - return calendar.get(GregorianCalendar.DAY_OF_MONTH); - } - - /** - * Returns the hour of day. - * - * @return The hour of day. - */ - public int getHourOfDay() { - return calendar.get(GregorianCalendar.HOUR_OF_DAY); - } - - /** - * Returns the minute. - * - * @return The minute. - */ - public int getMinute() { - return calendar.get(GregorianCalendar.MINUTE); - } - - /** - * Returns the second. - * - * @return The second. - */ - public int getSecond() { - return calendar.get(GregorianCalendar.SECOND); - } - - /** - * Returns the millisecond. - * - * @return The millisecond. - */ - public int getMillisecond() { - return calendar.get(GregorianCalendar.MILLISECOND); - } - - - @Override - public ValueType getType() { - return ValueType.DATETIME; - } - - /** - * Returns the DateTimeValue as a String using default formatting. - * - * @return The DateTimeValue as a String using default formatting. - */ - @Override - public String toString() { - if (this == NULL_VALUE) { - return "null"; - } - String result = String.format("%1$d-%2$02d-%3$02d %4$02d:%5$02d:%6$02d", - getYear(), getMonth() + 1, getDayOfMonth(), getHourOfDay(), getMinute(), - getSecond()); - if (getMillisecond() > 0) { - result += "." + String.format("%1$03d", getMillisecond()); - } - return result; - } - - /** - * Tests whether this value is a logical null. - * - * @return Indication if the value is null. - */ - @Override - public boolean isNull() { - return (this == NULL_VALUE); - } - - /** - * Compares this value to another value of the same type. - * - * @param other Other value. - * - * @return 0 if equal, negative if this is smaller, positive if larger. - */ - @Override - public int compareTo(Value other) { - if (this == other) { - return 0; - } - DateTimeValue otherDateTime = (DateTimeValue) other; - if (isNull()) { - return -1; - } - if (otherDateTime.isNull()) { - return 1; - } - // Calendar implements compareTo by converting to milliseconds. - return (calendar.compareTo(otherDateTime.getCalendar())); - } - - @Override - public int hashCode() { - if (null != hashCode) { - return hashCode; - } - // Compute and store hashCode for this DateTimeValue. - int hash = 1579; // Some arbitrary prime number. - hash = (hash * 11) + getYear(); - hash = (hash * 11) + getMonth(); - hash = (hash * 11) + getDayOfMonth(); - hash = (hash * 11) + getHourOfDay(); - hash = (hash * 11) + getMinute(); - hash = (hash * 11) + getSecond(); - hash = (hash * 11) + getMillisecond(); - hashCode = hash; - return hashCode; - } - - @Override - public Calendar getObjectToFormat() { - if (isNull()) { - return null; - } - return calendar; - } - - /** - * Returns the internal GregorianCalendar. - * - * @return The internal GregorianCalendar. - * - * @throws NullValueException Thrown when this Value is NULL_VALUE. - */ - public GregorianCalendar getCalendar() { - if (isNull()) { - throw new NullValueException("This object is null"); - } - return calendar; - } - - /** - * {@inheritDoc} - */ - @Override - protected String innerToQueryString() { - String s = "DATETIME '" + getYear() + "-" + (getMonth() + 1) + "-" - + getDayOfMonth() + " " + getHourOfDay() + ":" + getMinute() + ":" - + getSecond(); - int milli = getMillisecond(); - if (milli != 0) { - s += "." + milli; - } - s += "'"; - return s; - } -} diff --git a/src/main/java/com/google/visualization/datasource/datatable/value/DateValue.java b/src/main/java/com/google/visualization/datasource/datatable/value/DateValue.java deleted file mode 100755 index e1970b0..0000000 --- a/src/main/java/com/google/visualization/datasource/datatable/value/DateValue.java +++ /dev/null @@ -1,278 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.datatable.value; - -import com.ibm.icu.util.Calendar; -import com.ibm.icu.util.GregorianCalendar; -import com.ibm.icu.util.TimeZone; - - -/** - * A value of type date. Used to represent a specific day in a given year. This differs from - * {@link DateTimeValue}, which represents a specific day in a given year as well as a specific - * time during that day. - * Date is represented internally by three values: year, month and dayOfMonth. - * This class stores only legitimate dates where the validation is done using - * ibm.icu.GregorianCalendar. - * - * @author Hillel M. - */ -public class DateValue extends Value { - - /** - * A single static null value. - */ - private static final DateValue NULL_VALUE = new DateValue(); - - /** - * Static method to return the null value (same one for all calls). - * - * @return Null value. - */ - public static DateValue getNullValue() { - return NULL_VALUE; - } - - /** - * Underlying value: year. - */ - private int year; - - /** - * Underlying value: month. Note we use the java convention for months, this is: - * January = 0, February = 1, ..., December = 11. - */ - private int month; - - /** - * Underlying value: day of month. - */ - private int dayOfMonth; - - /** - * The hashCode for this DateValue. The hashCode of a NULL_VALUE is zero. - */ - private Integer hashCode = null; - - /** - * Create a new date value. This constructor is private and is used only to - * create a NULL_VALUE for this class. - */ - private DateValue() { - hashCode = 0; - } - - /** - * Creates a new date value. - * The input is checked using a GregorianCalendar. - * Note that we use java convention for months: - * January = 0, ..., December = 11. - * - * @param year The year. - * @param month The month. - * @param dayOfMonth The day in the month. - * - * @throws IllegalArgumentException Thrown when one of the - * parameters is illegal. - */ - public DateValue(int year, int month, int dayOfMonth) { - // Constructs a GregorianCalendar with the given date set in - // the default time zone. - GregorianCalendar calendar = - new GregorianCalendar(year, month, dayOfMonth); - - // Input check. If the date is invalid the calendar object will output - // different fields for year, month and/or dayOfMonth. - // A RunTimeException is thrown here since it is very unusual for structured - // data to be incorrect. - if ((calendar.get(GregorianCalendar.YEAR) != year) - || (calendar.get(GregorianCalendar.MONTH) != month) - || (calendar.get(GregorianCalendar.DAY_OF_MONTH) != dayOfMonth)) { - throw new IllegalArgumentException("Invalid java date (yyyy-MM-dd): " - + year + '-' + month + '-' + dayOfMonth); - } - // Assign internal variables. - this.year = year; - this.month = month; - this.dayOfMonth = dayOfMonth; - } - - /** - * Creates a new instance based on the given {@code GregorianCalendar}. - * The given calendar's time zone must be set to "GMT" as a precondition to - * use this constructor. - * Note: The date values: year, month, dayOfMonth correspond to the values - * returned by calendar.get(field) of the given calendar. - * - * @param calendar A gregorian to extract this instance values: year, month - * and dayOfMonth. - * - * @throws IllegalArgumentException When calendar time zone is not set - * to GMT. - */ - public DateValue(GregorianCalendar calendar) { - if (!calendar.getTimeZone().equals(TimeZone.getTimeZone("GMT"))) { - throw new IllegalArgumentException( - "Can't create DateValue from GregorianCalendar that is not GMT."); - } - this.year = calendar.get(GregorianCalendar.YEAR); - this.month = calendar.get(GregorianCalendar.MONTH); - this.dayOfMonth = calendar.get(GregorianCalendar.DAY_OF_MONTH); - } - - @Override - public ValueType getType() { - return ValueType.DATE; - } - - /** - * Returns the dateValue as a String using temporary formatting. - * - * @return The dateValue as a String using temporary formatting. - */ - @Override - public String toString() { - if (this == NULL_VALUE) { - return "null"; - } - return String.format("%1$d-%2$02d-%3$02d", year, month + 1, dayOfMonth); - - } - - /** - * Tests whether this value a logical null. - * - * @return Indication of whether the value is null. - */ - @Override - public boolean isNull() { - return (this == NULL_VALUE); - } - - /** - * Compares this value to another value of the same type. - * - * @param other Other value. - * - * @return 0 if equal, negative if this is smaller, positive if larger. - */ - @Override - public int compareTo(Value other) { - if (this == other) { - return 0; // If same value, or both are null. - } - DateValue otherDate = (DateValue) other; - if (isNull()) { - return -1; - } - if (otherDate.isNull()) { - return 1; - } - // Compare year. - if (this.year > otherDate.year) { - return 1; - } else if (this.year < otherDate.year) { - return -1; - } - // Compare month. - if (this.month > otherDate.month) { - return 1; - } else if (this.month < otherDate.month) { - return -1; - } - // Compare dayOfMonth. - if (this.dayOfMonth > otherDate.dayOfMonth) { - return 1; - } else if (this.dayOfMonth < otherDate.dayOfMonth) { - return -1; - } - // Equal Values. - return 0; - } - - @Override - public int hashCode() { - if (null != hashCode) { - return hashCode; - } - // Compute and store hashCode for this DateValue. - int hash = 1279; // Some arbitrary prime number. - hash = (hash * 17) + year; - hash = (hash * 17) + month; - hash = (hash * 17) + dayOfMonth; - hashCode = hash; - return hashCode; - } - - @Override - public Calendar getObjectToFormat() { - if (isNull()) { - return null; - } - GregorianCalendar cal = new GregorianCalendar(year, month, dayOfMonth); - cal.setTimeZone(TimeZone.getTimeZone("GMT")); - return cal; - } - - /** - * Returns the underlying year. - * - * @return The underlying year. - * - * @throws NullValueException Thrown when this Value is NULL_VALUE. - */ - public int getYear() { - if (isNull()) { - throw new NullValueException("This object is null"); - } - return year; - } - - /** - * Returns the underlying month. - * - * @return The underlying month. - * - * @throws NullValueException Thrown when this Value is NULL_VALUE. - */ - public int getMonth() { - if (isNull()) { - throw new NullValueException("This object is null"); - } - return month; - } - - /** - * Returns the underlying dayOfMonth. - * - * @return the underlying dayOfMonth. - * - * @throws NullValueException Thrown when this Value is NULL_VALUE. - */ - public int getDayOfMonth() { - if (isNull()) { - throw new NullValueException("This object is null"); - } - return dayOfMonth; - } - - /** - * {@inheritDoc} - */ - @Override - protected String innerToQueryString() { - return "DATE '" + year + "-" + (month + 1) + "-" + dayOfMonth + "'"; - } -} diff --git a/src/main/java/com/google/visualization/datasource/datatable/value/NullValueException.java b/src/main/java/com/google/visualization/datasource/datatable/value/NullValueException.java deleted file mode 100755 index f093ceb..0000000 --- a/src/main/java/com/google/visualization/datasource/datatable/value/NullValueException.java +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.datatable.value; - -/** - * Exception that is thrown when there is an attempt to request the value of - * a cell with a null value. - * - * @author Itai R. - */ -public class NullValueException extends RuntimeException { - - /** - * Constructor. - * - * @param message The detailed message of this exception. - */ - public NullValueException(String message) { - super(message); - } -} diff --git a/src/main/java/com/google/visualization/datasource/datatable/value/NumberValue.java b/src/main/java/com/google/visualization/datasource/datatable/value/NumberValue.java deleted file mode 100755 index 24efbc4..0000000 --- a/src/main/java/com/google/visualization/datasource/datatable/value/NumberValue.java +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.datatable.value; - -/** - * A value of type number. Valid values are double-precision floating-point numbers - * (including integers) or NULL_VALUE. - * - * @author Yoah B.D. - */ -public class NumberValue extends Value { - - /** - * A single static null value. - */ - private static final NumberValue NULL_VALUE = new NumberValue(-9999); - - /** - * Static method to return the null value (same one for all calls). - * @return Null value. - */ - public static NumberValue getNullValue() { - return NULL_VALUE; - } - - /** - * The underlying value. - */ - private double value; - - /** - * Create a new number value. - * - * @param value The underlying value. - */ - public NumberValue(double value) { - this.value = value; - } - - @Override - public ValueType getType() { - return ValueType.NUMBER; - } - - /** - * Returns the underlying value. - * - * @return The underlying value. - */ - public double getValue() { - if (this == NULL_VALUE) { - throw new NullValueException("This null number has no value"); - } - return value; - } - - /** - * Returns the number as a String using default formatting. - * - * @return The number as a String using default formatting. - */ - @Override - public String toString() { - if (this == NULL_VALUE) { - return "null"; - } - return Double.toString(value); - } - - /** - * Tests whether this value is a logical null. - * - * @return Indication of whether the value is null. - */ - @Override - public boolean isNull() { - return (this == NULL_VALUE); - } - - /** - * Compares this value to another value of the same type. - * - * @param other Other value. - * - * @return 0 if equal, negative if this is smaller, positive if larger. - */ - @Override - public int compareTo(Value other) { - if (this == other) { - return 0; // If same value, or both are null. - } - NumberValue otherNumber = (NumberValue) other; - if (isNull()) { - return -1; - } - if (otherNumber.isNull()) { - return 1; - } - return Double.compare(value, otherNumber.value); - } - - /** - * Returns a hash code for this number value. - * - * @return A hash code for this number value. - */ - @Override - public int hashCode() { - if (isNull()) { - return 0; - } - return new Double(value).hashCode(); - } - - @Override - public Number getObjectToFormat() { - if (isNull()) { - return null; - } - return value; - } - - /** - * {@inheritDoc} - */ - @Override - protected String innerToQueryString() { - return Double.toString(value); - } -} diff --git a/src/main/java/com/google/visualization/datasource/datatable/value/TextValue.java b/src/main/java/com/google/visualization/datasource/datatable/value/TextValue.java deleted file mode 100755 index be37d4f..0000000 --- a/src/main/java/com/google/visualization/datasource/datatable/value/TextValue.java +++ /dev/null @@ -1,163 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.datatable.value; - -import com.ibm.icu.text.Collator; -import com.ibm.icu.util.ULocale; - -import java.util.Comparator; - -/** - * A value of type text (string). - * - * @author Yoah B.D. - */ -public class TextValue extends Value { - - /** - * A single static null value. - */ - private static final TextValue NULL_VALUE = new TextValue(""); - - /** - * The underlying value. - */ - private String value; - - /** - * Creates a new text cell. - * - * @param value The cell's value. - */ - public TextValue(String value) { - if (value == null) { - throw new NullPointerException("Cannot create a text value from null."); - } - this.value = value; - } - - @Override - public ValueType getType() { - return ValueType.TEXT; - } - - /** - * Returns the text. - * - * @return The underlying text. - */ - @Override - public String toString() { - return value; - } - - /** - * Static method to return the null value (same one for all calls). - * - * @return Null value. - */ - public static TextValue getNullValue() { - return NULL_VALUE; - } - - /** - * Tests whether this cell's value is logical null. - * - * @return Indication of whether the cell's value is null. - */ - @Override - public boolean isNull() { - return (this == NULL_VALUE); - } - - /** - * Compares this value to another value of the same type. - * - * @param other Other value. - * - * @return 0 if equal, negative if this is smaller, positive if larger. - */ - @Override - public int compareTo(Value other) { - if (this == other) { - return 0; - } - // TextValue has no NULL_VALUE. - return value.compareTo(((TextValue) other).value); - } - - /** - * Returns a hash code for this string value. - * - * @return A hash code for this string value. - */ - @Override - public int hashCode() { - // TextValue has no NULL_VALUE. - return value.hashCode(); - } - - @Override - public String getObjectToFormat() { - return value; - } - - /** - * Returns a comparator that compares text values according to a given locale. - * - * @param ulocale The ulocale defining the order relation for text values. - * - * @return A comparator that compares text values according to a given locale. - */ - public static Comparator getTextLocalizedComparator(final ULocale ulocale) { - return new Comparator() { - Collator collator = Collator.getInstance(ulocale); - - @Override - public int compare(TextValue tv1, TextValue tv2) { - if (tv1 == tv2) { - return 0; - } - return collator.compare(tv1.value, tv2.value); - } - }; - } - - /** - * Returns the text value. - * - * @return The underlying text value. - */ - public String getValue() { - return value; - } - - /** - * {@inheritDoc} - */ - @Override - protected String innerToQueryString() { - if (value.contains("\"")) { - if (value.contains("'")) { - throw new RuntimeException("Cannot run toQueryString() on string" - + " values that contain both \" and '."); - } else { - return "'" + value + "'"; - } - } else { - return "\"" + value + "\""; - } - } -} diff --git a/src/main/java/com/google/visualization/datasource/datatable/value/TimeOfDayValue.java b/src/main/java/com/google/visualization/datasource/datatable/value/TimeOfDayValue.java deleted file mode 100755 index 863bdc6..0000000 --- a/src/main/java/com/google/visualization/datasource/datatable/value/TimeOfDayValue.java +++ /dev/null @@ -1,344 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.datatable.value; - - -import com.ibm.icu.util.Calendar; -import com.ibm.icu.util.GregorianCalendar; -import com.ibm.icu.util.TimeZone; - - -/** - * A value of type time-of-day. - * Time is represented internally by four fields: hours, minutes, seconds and milliseconds. - * - * @author Hillel M. - */ -public class TimeOfDayValue extends Value { - - /** - * A single static null value. - */ - private static final TimeOfDayValue NULL_VALUE = new TimeOfDayValue(); - - /** - * Static method to return the null value (same one for all calls). - * - * @return Null value. - */ - public static TimeOfDayValue getNullValue() { - return NULL_VALUE; - } - - /** - * Underlying value: hours (24 hours). - */ - private int hours; - - /** - * Underlying value: minutes (60 minutes). - */ - private int minutes; - - /** - * Underlying value: seconds (60 seconds). - */ - private int seconds; - - /** - * Underlying value: milliseconds (1000 milliseconds). - */ - private int milliseconds; - - /** - * The hashCode for this TimeOfDayValue. The hashCode of NULL_VALUE is zero. - */ - private Integer hashCode = null; - - /** - * Creates a new time value. This constructor is private and is used only to - * create a NULL_VALUE for this class. - */ - private TimeOfDayValue() { - hashCode = 0; - } - - /** - * Creates a new TimeOfDayValue. - * - * @param hours The hours. - * @param minutes The minutes. - * @param seconds The seconds. - * - * @throws IllegalArgumentException Thrown when one of the - * paramters is illegal. - */ - public TimeOfDayValue(int hours, int minutes, int seconds) { - this(hours, minutes, seconds, 0); - } - - /** - * Creates a new TimeOfDayValue. - * - * @param hours The hours. - * @param minutes The minutes. - * @param seconds The seconds. - * @param milliseconds The milliseconds. - * - * @throws IllegalArgumentException Thrown when one of the - * parameters is illegal. - */ - public TimeOfDayValue(int hours, int minutes, int seconds, int milliseconds) { - // Input checks. - // A RunTimeException is thrown here since it is very unusual for structured - // data to be incorrect. - if ((hours >= 24) || (hours < 0)) { - throw new IllegalArgumentException("This hours value is invalid: " - + hours); - } - if ((minutes >= 60) || (minutes < 0)) { - throw new IllegalArgumentException("This minutes value is invalid: " - + minutes); - } - if ((seconds >= 60) || (seconds < 0)) { - throw new IllegalArgumentException("This seconds value is invalid: " - + seconds); - } - if ((milliseconds >= 1000) || (milliseconds < 0)) { - throw new IllegalArgumentException("This milliseconds value is invalid: " - + milliseconds); - } - // Assign internal variables. - this.hours = hours; - this.minutes = minutes; - this.seconds = seconds; - this.milliseconds = milliseconds; - } - - /** - * Creates a new instance based on the given {@code GregorianCalendar}. - * The given calendar's time zone must be set to "GMT" as a precondition to - * use this constructor. - * Note: The date time values: hour, minute, second and millisecond - * correspond to the values returned by calendar.get(field) of the given - * calendar. - * - * @param calendar A GregorianCalendar from which to extract this instance - * values: hour, minutes, seconds and milliseconds. - * - * @throws IllegalArgumentException When calendar time zone is not set - * to GMT. - */ - public TimeOfDayValue(GregorianCalendar calendar) { - if (!calendar.getTimeZone().equals(TimeZone.getTimeZone("GMT"))) { - throw new IllegalArgumentException( - "Can't create TimeOfDayValue from GregorianCalendar that is not GMT."); - } - this.hours = calendar.get(GregorianCalendar.HOUR_OF_DAY); - this.minutes = calendar.get(GregorianCalendar.MINUTE); - this.seconds = calendar.get(GregorianCalendar.SECOND); - this.milliseconds = calendar.get(GregorianCalendar.MILLISECOND); - } - - @Override - public ValueType getType() { - return ValueType.TIMEOFDAY; - } - - /** - * Returns the timeValue as a String using default formatting. - * - * @return The timeValue as a String using default formatting. - */ - @Override - public String toString() { - if (this == NULL_VALUE) { - return "null"; - } - String result = String.format("%1$02d:%2$02d:%3$02d", hours, minutes, - seconds); - if (milliseconds > 0) { - result += "." + String.format("%1$3d", milliseconds); - } - return result; - } - - /** - * Tests whether this value is a logical null. - * - * @return Indication of whether the value is null. - */ - @Override - public boolean isNull() { - return (this == NULL_VALUE); - } - - /** - * Compares this value to another value of the same type. - * - * @param other Other value. - * - * @return 0 if equal, negative if this is smaller, positive if larger. - */ - @Override - public int compareTo(Value other) { - if (this == other) { - return 0; - } - TimeOfDayValue otherTimeOfDay = (TimeOfDayValue) other; - if (isNull()) { - return -1; - } - if (otherTimeOfDay.isNull()) { - return 1; - } - // Compare hours. - if (this.hours > otherTimeOfDay.hours) { - return 1; - } else if (this.hours < otherTimeOfDay.hours) { - return -1; - } - // Compare minutes. - if (this.minutes > otherTimeOfDay.minutes) { - return 1; - } else if (this.minutes < otherTimeOfDay.minutes) { - return -1; - } - // Compare seconds. - if (this.seconds > otherTimeOfDay.seconds) { - return 1; - } else if (this.seconds < otherTimeOfDay.seconds) { - return -1; - } - // Compare milliseconds. - if (this.milliseconds > otherTimeOfDay.milliseconds) { - return 1; - } else if (this.milliseconds < otherTimeOfDay.milliseconds) { - return -1; - } - // Equal Values. - return 0; - } - - - @Override - public int hashCode() { - if (null != hashCode) { - return hashCode; - } - // Compute and store hashCode for this TimeOfDayValue - done only once. - int hash = 1193; // Some arbitrary prime number. - hash = (hash * 13) + hours; - hash = (hash * 13) + minutes; - hash = (hash * 13) + seconds; - hash = (hash * 13) + milliseconds; - hashCode = hash; - return hashCode; - } - - /** - * A method to retrieve a formattable object for this object. - * It is important to set the GMT TimeZone to avoid conversions related to TimeZone. - */ - @Override - public Calendar getObjectToFormat() { - if (isNull()) { - return null; - } - - // Set GMT TimeZone. - Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT")); - // Set to some predefined default. Don't change this default. - cal.set(Calendar.YEAR, 1899); - cal.set(Calendar.MONTH, Calendar.DECEMBER); - cal.set(Calendar.DAY_OF_MONTH, 30); - // Set the TimeOfDay based on this TimeOfDayValue. - cal.set(Calendar.HOUR_OF_DAY, hours); - cal.set(Calendar.MINUTE, minutes); - cal.set(Calendar.SECOND, seconds); - cal.set(Calendar.MILLISECOND, milliseconds); - - return cal; - } - - /** - * Returns the underlying hours. - * - * @return The underlying hours. - * - * @throws NullValueException Thrown when this Value is NULL_VALUE. - */ - public int getHours() { - if (isNull()) { - throw new NullValueException("This object is null"); - } - return hours; - } - - /** - * Returns the underlying minutes. - * - * @return The underlying minutes. - * - * @throws NullValueException Thrown when this Value is NULL_VALUE. - */ - public int getMinutes() { - if (isNull()) { - throw new NullValueException("This object is null"); - } - return minutes; - } - - /** - * Returns the underlying seconds. - * - * @return The underlying seconds. - * - * @throws NullValueException Thrown when this Value is NULL_VALUE. - */ - public int getSeconds() { - if (isNull()) { - throw new NullValueException("This object is null"); - } - return seconds; - } - - /** - * Returns the underlying milliseconds. - * - * @return The underlying milliseconds. - * - * @throws NullValueException Thrown when this Value is NULL_VALUE. - */ - public int getMilliseconds() { - if (isNull()) { - throw new NullValueException("This object is null"); - } - return milliseconds; - } - - /** - * {@inheritDoc} - */ - @Override - protected String innerToQueryString() { - String s = "TIMEOFDAY '" + hours + ":" + minutes + ":" + seconds; - if (milliseconds != 0) { - s += "." + milliseconds; - } - s += "'"; - return s; - } -} diff --git a/src/main/java/com/google/visualization/datasource/datatable/value/Value.java b/src/main/java/com/google/visualization/datasource/datatable/value/Value.java deleted file mode 100755 index 97ac0de..0000000 --- a/src/main/java/com/google/visualization/datasource/datatable/value/Value.java +++ /dev/null @@ -1,158 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.datatable.value; - -import com.ibm.icu.util.ULocale; - -import java.util.Comparator; - -/** - * An abstract value of a single cell in a table. - * Acts as a base class for all the typed value classes. - * A value should be an immutable class, because it is reference-copied when cloning complex - * objects like rows or whole tables. - * - * @author Itai R. - */ -public abstract class Value implements Comparable { - - /** - * Returns the type of this cell. - * - * @return The type of this cell. - */ - public abstract ValueType getType(); - - /** - * Returns whether or not this cell's value is a logical null. - * - * @return true iff this cell's value is a logical null. - */ - public abstract boolean isNull(); - - /** - * Checks if this object is equal to the given object. - * Note that no instance can be equal to null and two - * instances of different classes are not equal. - * - * @param o The object with which to compare. - * - * @return true if this equals o and false otherwise. - */ - @Override - public boolean equals(Object o) { - if ((null == o) || (this.getClass() != o.getClass())) { - return false; - } - // Does not throw exception since the classes match. - return (this.compareTo((Value) o) == 0); - } - - /** - * Returns the hashcode of this value. This is introduced here to force the - * subclasses to define this function. - * - * @return The hashcode of this value. - */ - @Override - public abstract int hashCode(); - - /** - * Uses an ibm.icu.text.UFormat instance to format Values. - * The following method returns an object representing this Value that a - * UFormat can format. - * - * @return An object representing this value that can be formatted by a - * UFormat formatter, null for a NULL_VALUE. - */ - public abstract Object getObjectToFormat(); - - - /** - * Returns the NullValue for the given type. - * - * @param type The value type. - * - * @return The NullValue for the given type. - */ - public static Value getNullValueFromValueType(ValueType type) { - switch (type) { - case BOOLEAN: - return BooleanValue.getNullValue(); - case TEXT: - return TextValue.getNullValue(); - case NUMBER: - return NumberValue.getNullValue(); - case TIMEOFDAY: - return TimeOfDayValue.getNullValue(); - case DATE: - return DateValue.getNullValue(); - case DATETIME: - return DateTimeValue.getNullValue(); - } - return null; // shouldn't get here - } - - /** - * Returns a string that, when parsed by the query parser, should return an - * identical value. Throws an exception when called on a null value. - * - * @return A string form of this value. - */ - public final String toQueryString() { - if (isNull()) { - throw new RuntimeException("Cannot run toQueryString() on a null value."); - } - return innerToQueryString(); - } - - /** - * Returns a string that, when parsed by the query parser, should return an - * identical value. Assumes this value is not null. - * - * @return A string form of this value. - */ - protected abstract String innerToQueryString(); - - /** - * Returns a comparator that compares values according to a given locale - * (in case of text values). - * - * @param ulocale The ULocale defining the order relation of text values. - * - * @return A comparator that compares values according to a given locale - * (in case of text values). - */ - public static Comparator getLocalizedComparator( - final ULocale ulocale) { - return new Comparator() { - private Comparator textValueComparator = - TextValue.getTextLocalizedComparator(ulocale); - - @Override - public int compare(Value value1, Value value2) { - if (value1 == value2) { - return 0; - } - if (value1.getType() == ValueType.TEXT) { - return textValueComparator.compare((TextValue) value1, - (TextValue) value2); - } else { - return value1.compareTo(value2); - } - } - }; - } -} diff --git a/src/main/java/com/google/visualization/datasource/datatable/value/ValueType.java b/src/main/java/com/google/visualization/datasource/datatable/value/ValueType.java deleted file mode 100755 index b885432..0000000 --- a/src/main/java/com/google/visualization/datasource/datatable/value/ValueType.java +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.datatable.value; - -import com.google.common.collect.Maps; -import com.google.visualization.datasource.base.TypeMismatchException; - -import com.ibm.icu.util.GregorianCalendar; - -import java.util.Map; - -/** - * Represents a supported value type for a table. - * - * @author Yoah B.D. - */ -public enum ValueType { - BOOLEAN("BOOLEAN"), - NUMBER("NUMBER"), - TEXT("STRING"), - DATE("DATE"), - TIMEOFDAY("TIMEOFDAY"), - DATETIME("DATETIME"); - - /** - * The type code string for this ValueType. - */ - private String typeCode; - - /** - * Constructs a ValueType with a given type code string. - * - * @param typeCode The type code string for the ValueType. - */ - ValueType(String typeCode) { - this.typeCode = typeCode; - } - - /** - * Returns the type code string for this ValueType. - * - * @return The type code string for this ValueType. - */ - String getTypeCode() { - return typeCode; - } - - /** - * Returns the type code string for this ValueType as a lower case string. - * - * @return The type code string for this ValueType as a lower case string. - */ - public String getTypeCodeLowerCase() { - return typeCode.toLowerCase(); - } - - /** - * Returns the correct ValueType for a given type code string. - * - * @param string The type code string. - * - * @return The correct ValueType for the type code string. - */ - static ValueType getByTypeCode(String string) { - return typeCodeToValueType.get(string); - } - - /** - * Holds the mapping of type code to an instance of this class. - */ - private static Map typeCodeToValueType; - - /** - * Creates a value of this ValueType. The value must be of an appropriate - * class, otherwise an exception is thrown. - * Java native types/classes are translated to Value in the following way: - * String -> TextValue - * Number (inc. all derivatives such as Integer, Double) -> NumberValue - * Boolean -> BooleanValue - * com.ibm.icu.util.GregorianCalendar -> DateValue, DateTimeValue or - * TimeOfDayValue - * - * @param value The value to create. - * @return A Value of this ValueType. - * @throws TypeMismatchException When the type of value does not match this. - */ - public Value createValue(Object value) throws TypeMismatchException { - Value ret = null; - - if (value == null) { - ret = Value.getNullValueFromValueType(this); - } else if ((this == TEXT) && - ((value instanceof String) || value == null)) { - ret = new TextValue((String) value); - } else if ((this == NUMBER) && (value instanceof Number)) { - ret = new NumberValue(((Number) value).doubleValue()); - } else if ((this == BOOLEAN) && (value instanceof Boolean)) { - ret = ((Boolean) value).booleanValue() ? BooleanValue.TRUE - : BooleanValue.FALSE; - } else if ((this == DATE) && (value instanceof GregorianCalendar)) { - ret = new DateValue((GregorianCalendar) value); - } else if ((this == DATETIME) && (value instanceof GregorianCalendar)) { - ret = new DateTimeValue((GregorianCalendar) value); - } else if ((this == TIMEOFDAY) && (value instanceof GregorianCalendar)) { - ret = new TimeOfDayValue((GregorianCalendar) value); - } - - // If none of the above hold, we have a type mismatch. - if (ret == null) { - throw new TypeMismatchException("Value type mismatch."); - } - - return ret; - } - - /** - * Initializes the static map. - */ - static { - typeCodeToValueType = Maps.newHashMap(); - for (ValueType type : ValueType.values()) { - typeCodeToValueType.put(type.typeCode, type); - } - } -} diff --git a/src/main/java/com/google/visualization/datasource/query/AbstractColumn.java b/src/main/java/com/google/visualization/datasource/query/AbstractColumn.java deleted file mode 100755 index 1483ea9..0000000 --- a/src/main/java/com/google/visualization/datasource/query/AbstractColumn.java +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query; - -import com.google.visualization.datasource.base.InvalidQueryException; -import com.google.visualization.datasource.datatable.DataTable; -import com.google.visualization.datasource.datatable.TableCell; -import com.google.visualization.datasource.datatable.TableRow; -import com.google.visualization.datasource.datatable.value.Value; -import com.google.visualization.datasource.datatable.value.ValueType; - -import java.util.List; - -/** - * A column. - * This can be either a column by ID, or an aggregation column such as min(c1), - * etc. - * - * @author Yonatan B.Y. - */ -public abstract class AbstractColumn { - - /** - * Returns a string ID for this column. It can be already existing in the - * instance, or generated upon request, depending on the specific class - * implementation. - * - * @return The string ID for this column. - */ - public abstract String getId(); - - /** - * Returns a list of all simple (primitive) column IDs included in this - * AbstractColumn. This is a list to support calculated columns in the future. - * For example, a simple column would just return a list containing its own - * ID. An aggregation column would just return a list containing the ID of - * its aggregated column. In future, when calculated columns are - * introduced, a calculated column will return a list with more than one - * element. - * - * @return A list of all simple column IDs included in this AbstractColumn. - */ - public abstract List getAllSimpleColumnIds(); - - /** - * Returns the value of the column in the given row. - * - * @param row The given row. - * @param lookup The column lookup. - * - * @return The value of the column in the given row. - */ - public Value getValue(ColumnLookup lookup, TableRow row) { - return getCell(lookup, row).getValue(); - } - - /** - * Returns the cell of the column in the given row. - * - * @param row The given row. - * @param lookup The column lookup. - * - * @return The cell of the column in the given row. - */ - public TableCell getCell(ColumnLookup lookup, TableRow row) { - int columnIndex = lookup.getColumnIndex(this); - return row.getCells().get(columnIndex); - } - - /** - * Returns a list of all simple columns included in this abstract column. - * - * @return A list of all simple columns included in this abstract column. - */ - public abstract List getAllSimpleColumns(); - - /** - * Returns a list of all aggregation columns included in this abstract - * column. - * - * @return A list of all aggregation columns included in this abstract - * column. - */ - public abstract List getAllAggregationColumns(); - - /** - * Returns a list of all scalar function columns included in this abstract - * column. - * - * @return A list of all scalar function columns included in this abstract - * column. - */ - public abstract List getAllScalarFunctionColumns(); - - /** - * Checks whether the column is valid. Aggregation columns and - * scalar function columns are valid if the aggregation or scalar function - * respectively matches its arguments (inner columns). - * - * @param dataTable The data table. - * - * @throws InvalidQueryException Thrown if the column is not valid. - */ - public abstract void validateColumn(DataTable dataTable) throws InvalidQueryException; - - /** - * Returns the value type of the column. For a simple column, returns the - * value type of the column itself. For an aggregation or scalar function - * column, returns the value type of the column after evaluating the function. - * For example, the value type of year(a1) is NUMBER. - * - * @param dataTable The data table. - * - * @return The value type of the column. - */ - public abstract ValueType getValueType(DataTable dataTable); - - /** - * Returns a string that when parsed by the query parser, should return an - * identical column. - * - * @return A string form of this column. - */ - public abstract String toQueryString(); - - @Override - public abstract boolean equals(Object o); - - @Override - public abstract int hashCode(); -} diff --git a/src/main/java/com/google/visualization/datasource/query/AggregationColumn.java b/src/main/java/com/google/visualization/datasource/query/AggregationColumn.java deleted file mode 100755 index 64d87bc..0000000 --- a/src/main/java/com/google/visualization/datasource/query/AggregationColumn.java +++ /dev/null @@ -1,221 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query; - -import com.google.common.collect.Lists; -import com.google.visualization.datasource.base.InvalidQueryException; -import com.google.visualization.datasource.base.MessagesEnum; -import com.google.visualization.datasource.datatable.DataTable; -import com.google.visualization.datasource.datatable.value.ValueType; - -import com.ibm.icu.util.ULocale; - -import java.util.List; - -/** - * A column that is referred to by an aggregation, for example, min(c1). - * - * @author Yonatan B.Y. - */ -public class AggregationColumn extends AbstractColumn { - /** - * When creating the ID of the column, this separates the column - * on which aggregation is performed and the type of aggregation performed - * on it. - */ - public static final String COLUMN_AGGRGATION_TYPE_SEPARATOR = "-"; - - /** - * The simple column on which the aggregation is performed, e.g., c1 in - * min(c1). - */ - private SimpleColumn aggregatedColumn; - - /** - * The type of aggregation that is performed, e.g., min in min(c1). - */ - private AggregationType aggregationType; - - /** - * Creates a new instance of this class with the given column and - * aggregation type. - * - * @param aggregatedColumn The column. - * @param aggregationType The aggregation type. - */ - public AggregationColumn(SimpleColumn aggregatedColumn, - AggregationType aggregationType) { - this.aggregatedColumn = aggregatedColumn; - this.aggregationType = aggregationType; - } - - /** - * Creates a string to act as ID for this column. Constructed from the - * aggregation type and the column ID, separated by a separator. - * - * @return A string to act as ID for this column. - */ - @Override - public String getId() { - return aggregationType.getCode() + COLUMN_AGGRGATION_TYPE_SEPARATOR - + aggregatedColumn.getId(); - } - - /** - * Returns the column to aggregate. - * - * @return The column to aggregate. - */ - public SimpleColumn getAggregatedColumn() { - return aggregatedColumn; - } - - @Override - public List getAllSimpleColumnIds() { - return Lists.newArrayList(aggregatedColumn.getId()); - } - - /** - * Returns a list of all simple columns. In this case, returns an empty list. - * - * @return A list of all simple columns. - */ - @Override - public List getAllSimpleColumns() { - return Lists.newArrayList(); - } - - /** - * Returns a list of all aggregation columns. In this case, returns only - * itself. - * - * @return A list of all aggregation columns. - */ - @Override - public List getAllAggregationColumns() { - return Lists.newArrayList(this); - } - - /** - * Returns a list of all scalar function columns. In this case, returns an - * empty list. - * - * @return A list of all scalar function columns. - */ - @Override - public List getAllScalarFunctionColumns() { - return Lists.newArrayList(); - } - - /** - * Returns the requested aggregation type. - * - * @return The requested aggregation type. - */ - public AggregationType getAggregationType() { - return aggregationType; - } - - /** - * Checks whether it makes sense to have the aggregation type on - * the aggregated column. The type of the column is taken from the given - * table description. Throws a column exception if the column is invalid. - * - * @param dataTable The data table. - * - * @throws InvalidQueryException Thrown if the column is invalid. - */ - @Override - public void validateColumn(DataTable dataTable) throws InvalidQueryException { - ValueType valueType = dataTable.getColumnDescription(aggregatedColumn.getId()).getType(); - ULocale userLocale = dataTable.getLocaleForUserMessages(); - switch (aggregationType) { - case COUNT: case MAX: case MIN: break; - case AVG: case SUM: - if (valueType != ValueType.NUMBER) { - throw new InvalidQueryException(MessagesEnum.AVG_SUM_ONLY_NUMERIC.getMessage(userLocale)); - } - break; - default: throw new RuntimeException(MessagesEnum.INVALID_AGG_TYPE.getMessageWithArgs( - userLocale, aggregationType.toString())); - } - } - - /** - * Returns the value type of the column. In this case returns the value type - * of the column after evaluating the aggregation function. - * - * @param dataTable The data table. - * - * @return The value type of the column. - */ - @Override - public ValueType getValueType(DataTable dataTable) { - ValueType valueType; - ValueType originalValueType = - dataTable.getColumnDescription(aggregatedColumn.getId()).getType(); - switch (aggregationType) { - case COUNT: - valueType = ValueType.NUMBER; - break; - case AVG: case SUM: case MAX: case MIN: - valueType = originalValueType; - break; - default: throw new RuntimeException(MessagesEnum.INVALID_AGG_TYPE.getMessageWithArgs( - dataTable.getLocaleForUserMessages(), aggregationType.toString())); - } - return valueType; - } - - - @Override - public boolean equals(Object o) { - if (o instanceof AggregationColumn) { - AggregationColumn other = (AggregationColumn) o; - return aggregatedColumn.equals(other.aggregatedColumn) - && aggregationType.equals(other.aggregationType); - } - return false; - } - - @Override - public int hashCode() { - int hash = 1279; // Some arbitrary prime number. - hash = (hash * 17) + aggregatedColumn.hashCode(); - hash = (hash * 17) + aggregationType.hashCode(); - return hash; - } - - /** - * This is for debug and error messages, not for ID generation. - * - * @return A string describing this AggregationColumn. - */ - @Override - public String toString() { - return aggregationType.getCode() + "(" + aggregatedColumn.getId() + ")"; - } - - /** - * {@inheritDoc} - */ - @Override - public String toQueryString() { - // This works because the codes in AggregationType are the same as the - // keywords in the query parser. - return aggregationType.getCode().toUpperCase() + "(" - + aggregatedColumn.toQueryString() + ")"; - } -} diff --git a/src/main/java/com/google/visualization/datasource/query/AggregationType.java b/src/main/java/com/google/visualization/datasource/query/AggregationType.java deleted file mode 100755 index 2192cda..0000000 --- a/src/main/java/com/google/visualization/datasource/query/AggregationType.java +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query; - -import com.google.common.collect.Maps; - -import java.util.Map; - -/** - * Enumeration of all possible aggregation types. - * - * @author Yoav G. - * @author Yonatan B.Y. - */ -public enum AggregationType { - SUM("sum"), - COUNT("count"), - MIN("min"), - MAX("max"), - AVG("avg"); - - /** - * The code for this AggregationType. - */ - private String code; - - /** - * Constructor - * - * @param code The code for this AggregationType. - */ - private AggregationType(String code) { - this.code = code; - } - - /** - * Get this AggregationType code. - * - * @return The AggregationType code. - */ - public String getCode() { - return code; - } - - /** - * Returns the correct AggregationType for a given code. - * - * @param code The code for a type. - * - * @return The correct AggregationType for the given code. - */ - public static AggregationType getByCode(String code) { - return codeToAggregationType.get(code); - } - - /** - * Holds the mapping of type code to instances of this class. - */ - private static Map codeToAggregationType; - - /** - * Initializes the static maps. - */ - static { - codeToAggregationType = Maps.newHashMap(); - for (AggregationType type : AggregationType.values()) { - codeToAggregationType.put(type.code, type); - } - } -} diff --git a/src/main/java/com/google/visualization/datasource/query/ColumnColumnFilter.java b/src/main/java/com/google/visualization/datasource/query/ColumnColumnFilter.java deleted file mode 100755 index 6ab5d41..0000000 --- a/src/main/java/com/google/visualization/datasource/query/ColumnColumnFilter.java +++ /dev/null @@ -1,182 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query; - -import com.google.common.collect.Lists; -import com.google.common.collect.Sets; -import com.google.visualization.datasource.datatable.DataTable; -import com.google.visualization.datasource.datatable.TableRow; -import com.google.visualization.datasource.datatable.value.Value; - -import java.util.List; -import java.util.Set; - -/** - * A filter that compares two column values. - * - * @author Yonatan B.Y. - */ -public class ColumnColumnFilter extends ComparisonFilter { - - /** - * The first column. - */ - private AbstractColumn firstColumn; - - /** - * The second column. This is the column with which the first column is compared. - */ - private AbstractColumn secondColumn; - - /** - * Constructs a new ColumnColumnFilter on two given columns, and an operator. - * - * @param firstColumn The first column. - * @param secondColumn The second column. - * @param operator The comparison operator to use. - */ - public ColumnColumnFilter(AbstractColumn firstColumn, - AbstractColumn secondColumn, Operator operator) { - super(operator); - this.firstColumn = firstColumn; - this.secondColumn = secondColumn; - } - - /** - * Implements isMatch from the QueryFilter interface. This implementation - * retrieves from the row, the data in the required columns, and compares - * the first against the second, using the operator given in the - * constructor. - * - * @param table The table containing this row. - * @param row The row to check. - * - * @return true if this row should be part of the result set, i.e., if the - * operator is true when run on the values in the two columns; false - * otherwise. - */ - @Override - public boolean isMatch(DataTable table, TableRow row) { - DataTableColumnLookup lookup = new DataTableColumnLookup(table); - Value firstValue = firstColumn.getValue(lookup, row); - Value secondValue = secondColumn.getValue(lookup, row); - return isOperatorMatch(firstValue, secondValue); - } - - /** - * Returns all the simple column IDs this filter uses, in this case - * the simple column IDs of firstColumn and secondColumn. - * - * @return All the column IDs this filter uses. - */ - @Override - public Set getAllColumnIds() { - Set columnIds = Sets.newHashSet(firstColumn.getAllSimpleColumnIds()); - columnIds.addAll(secondColumn.getAllSimpleColumnIds()); - return columnIds; - } - - /** - * Returns a list of all scalarFunctionColumns this filter uses, in this case - * the scalarFunctionColumns in the first and second columns (e.g, in the - * filter year(a) = year(date(b)) it will return year(a), year(date(b)) and - * date(b)). - * - * @return A list of all scalarFunctionColumns this filter uses. - */ - @Override - public List getScalarFunctionColumns() { - List scalarFunctionColumns = Lists.newArrayList(); - scalarFunctionColumns.addAll(firstColumn.getAllScalarFunctionColumns()); - scalarFunctionColumns.addAll(secondColumn.getAllScalarFunctionColumns()); - return scalarFunctionColumns; - } - - /** - * {@InheritDoc} - */ - @Override - protected List getAggregationColumns() { - List aggregationColumns = Lists.newArrayList(); - aggregationColumns.addAll(firstColumn.getAllAggregationColumns()); - aggregationColumns.addAll(secondColumn.getAllAggregationColumns()); - return aggregationColumns; - } - - /** - * Returns the first column associated with this ColumnColumnFilter. - * - * @return The first column associated with this ColumnColumnFilter. - */ - public AbstractColumn getFirstColumn() { - return firstColumn; - } - - /** - * Returns the second column associated with this ColumnColumnFilter. - * - * @return The second column associated with this ColumnColumnFilter. - */ - public AbstractColumn getSecondColumn() { - return secondColumn; - } - - /** - * {@inheritDoc} - */ - @Override - public String toQueryString() { - return firstColumn.toQueryString() + " " + operator.toQueryString() - + " " + secondColumn.toQueryString(); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((firstColumn == null) ? 0 : firstColumn.hashCode()); - result = prime * result + ((secondColumn == null) ? 0 : secondColumn.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - ColumnColumnFilter other = (ColumnColumnFilter) obj; - if (firstColumn == null) { - if (other.firstColumn != null) { - return false; - } - } else if (!firstColumn.equals(other.firstColumn)) { - return false; - } - if (secondColumn == null) { - if (other.secondColumn != null) { - return false; - } - } else if (!secondColumn.equals(other.secondColumn)) { - return false; - } - return true; - } -} diff --git a/src/main/java/com/google/visualization/datasource/query/ColumnIsNullFilter.java b/src/main/java/com/google/visualization/datasource/query/ColumnIsNullFilter.java deleted file mode 100755 index 506189d..0000000 --- a/src/main/java/com/google/visualization/datasource/query/ColumnIsNullFilter.java +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query; - -import com.google.common.collect.Sets; -import com.google.visualization.datasource.datatable.DataTable; -import com.google.visualization.datasource.datatable.TableRow; - -import java.util.List; -import java.util.Set; - -/** - * A filter that matches null values. Its isMatch function returns true if - * the value at the column is a null value (as defined by TableCell.isNull()). - * - * @author Yonatan B.Y. - */ -public class ColumnIsNullFilter extends QueryFilter { - - /** - * The ID of the column that should be null. - */ - private AbstractColumn column; - - /** - * Constructs a new instance of this class with the given column ID. - * - * @param column The column that should be null. - */ - public ColumnIsNullFilter(AbstractColumn column) { - this.column = column; - } - - /** - * Returns the column that should be null. - * - * @return The column that should be null. - */ - public AbstractColumn getColumn() { - return column; - } - - /** - * {@inheritDoc} - */ - @Override - public Set getAllColumnIds() { - return Sets.newHashSet(column.getAllSimpleColumnIds()); - } - - /** - * Returns a list of all scalarFunctionColumns this filter uses, in this case - * the scalarFunctionColumns in column (e.g, in the filter 'year(a) is null' - * it will return year(a). - * - * @return A list of all scalarFunctionColumns this filter uses. - */ - @Override - public List getScalarFunctionColumns() { - return column.getAllScalarFunctionColumns(); - } - - /** - * {@inheritDoc} - */ - @Override - protected List getAggregationColumns() { - return column.getAllAggregationColumns(); - } - - /** - * {@inheritDoc} - */ - @Override - public boolean isMatch(DataTable table, TableRow row) { - DataTableColumnLookup lookup = new DataTableColumnLookup(table); - return column.getValue(lookup, row).isNull(); - } - - /** - * {@inheritDoc} - */ - @Override - public String toQueryString() { - return column.toQueryString() + " IS NULL"; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((column == null) ? 0 : column.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - ColumnIsNullFilter other = (ColumnIsNullFilter) obj; - if (column == null) { - if (other.column != null) { - return false; - } - } else if (!column.equals(other.column)) { - return false; - } - return true; - } -} diff --git a/src/main/java/com/google/visualization/datasource/query/ColumnLookup.java b/src/main/java/com/google/visualization/datasource/query/ColumnLookup.java deleted file mode 100755 index e1a9b1c..0000000 --- a/src/main/java/com/google/visualization/datasource/query/ColumnLookup.java +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query; - -/** - * A column lookup. - * Maps columns to their index in a column container (e.g., DateTable). - * - * @author Liron L. - */ -public interface ColumnLookup { - - /** - * Returns the index of the given column. - * - * @param column The given AbstractColumn. - * - * @return The index of the given column. - */ - public int getColumnIndex(AbstractColumn column); - - /** - * Returns whether or not this ColumnLookup contains the given column. - * - * @param column The column to check. - * - * @return True if column exists, false otherwise. - */ - public boolean containsColumn(AbstractColumn column); -} diff --git a/src/main/java/com/google/visualization/datasource/query/ColumnSort.java b/src/main/java/com/google/visualization/datasource/query/ColumnSort.java deleted file mode 100755 index e7a1d67..0000000 --- a/src/main/java/com/google/visualization/datasource/query/ColumnSort.java +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query; - -/** - * A sort definition for a single column. - * This class is immutable. - * - * @author Yoah B.D. - */ -public class ColumnSort { - - /** - * The column by which to sort. - */ - private AbstractColumn column; - - /** - * The requested ordering. - */ - private SortOrder order; - - /** - * Construct and new column sort condition. - * @param column The column by which to sort. - * @param order The requested ordering. - */ - public ColumnSort(AbstractColumn column, SortOrder order) { - this.column = column; - this.order = order; - } - - /** - * Returns the column by which to sort. - * @return The column by which to sort. - */ - public AbstractColumn getColumn() { - return column; - } - - /** - * Returns the requested ordering. - * @return The requested ordering. - */ - public SortOrder getOrder() { - return order; - } - - /** - * Creates a string that when fed to the query parser should return a ColumnSort equal to this - * one. Used mainly for debugging purposes. - * @return A query string. - */ - public String toQueryString() { - return column.toQueryString() + (order == SortOrder.DESCENDING ? " DESC" : ""); - } -} diff --git a/src/main/java/com/google/visualization/datasource/query/ColumnValueFilter.java b/src/main/java/com/google/visualization/datasource/query/ColumnValueFilter.java deleted file mode 100755 index ab4c5c3..0000000 --- a/src/main/java/com/google/visualization/datasource/query/ColumnValueFilter.java +++ /dev/null @@ -1,215 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query; - -import com.google.common.collect.Sets; -import com.google.visualization.datasource.datatable.DataTable; -import com.google.visualization.datasource.datatable.TableRow; -import com.google.visualization.datasource.datatable.value.Value; - -import java.util.List; -import java.util.Set; - -/** - * A filter that compares a column value to a constant value. - * - * @author Yonatan B.Y. - */ -public class ColumnValueFilter extends ComparisonFilter { - - /** - * The column to compare. - */ - private AbstractColumn column; - - /** - * The constant value the column value will be compared to. - */ - private Value value; - - /** - * Whether the column and the value should be reversed, i.e., instead of - * column op value, this will be value op column. - */ - private boolean isComparisonOrderReversed; - - /** - * Constructs a new ColumnValueFilter on a given column, constant value, - * operator, and isComparisonOrderReversed. - * - * @param column The column to compare. - * @param value The constant value the column value is compared to. - * @param operator The comparison operator to use. - * @param isComparisonOrderReversed Whether to reverse the comparison order - * of the operator. - */ - public ColumnValueFilter(AbstractColumn column, Value value, - Operator operator, boolean isComparisonOrderReversed) { - super(operator); - this.column = column; - this.value = value; - this.isComparisonOrderReversed = isComparisonOrderReversed; - } - - /** - * Constructs a new ColumnValueFilter on a given column, constant value and - * operator. - * - * @param column The column to compare. - * @param value The constant value the column value is compared to. - * @param operator The comparison operator to use. - */ - public ColumnValueFilter(AbstractColumn column, Value value, - Operator operator) { - this(column, value, operator, false); - } - - /** - * Implements isMatch from the QueryFilter interface. This implementation - * retrieves from the row, the data in the required column, and compares - * it against the constant value, using the operator given in the - * constructor. - * - * @param table The table containing this row. - * @param row The row to check. - * - * @return true if this row should be part of the result set, i.e., if the - * operator returns true when run on the value in the column, and the - * constant value; false otherwise. - */ - @Override - public boolean isMatch(DataTable table, TableRow row) { - DataTableColumnLookup lookup = new DataTableColumnLookup(table); - Value columnValue = column.getValue(lookup, row); - return isComparisonOrderReversed ? isOperatorMatch(value, columnValue) : - isOperatorMatch(columnValue, value); - } - - /** - * Returns all the columnIds this filter uses, in this case the simple column - * IDs of the filter's column. - * - * @return All the columnIds this filter uses. - */ - @Override - public Set getAllColumnIds() { - return Sets.newHashSet(column.getAllSimpleColumnIds()); - } - - /** - * Returns a list of all scalarFunctionColumns this filter uses, in this case - * the scalarFunctionColumns in the filter's column (e.g, in thefilter - * 'year(a)=2008' it will return year(a). - * - * @return A list of all scalarFunctionColumns this filter uses. - */ - @Override - public List getScalarFunctionColumns() { - return column.getAllScalarFunctionColumns(); - } - - /** - * {@inheritDoc} - */ - @Override - protected List getAggregationColumns() { - return column.getAllAggregationColumns(); - } - - /** - * Returns the column ID associated with this ColumnValueFilter. - * - * @return The column ID associated with this ColumnValueFilter. - */ - public AbstractColumn getColumn() { - return column; - } - - /** - * Returns the value associated with this ColumnValueFilter. - * - * @return The value associated with this ColumnValueFilter. - */ - public Value getValue() { - return value; - } - - /** - * Returns whether or not this operator's comparison order is reversed. This - * means whether the column and the value should be reversed, i.e., instead of - * column op value, this will be value op column. - * - * @return Whether or not the operator's comparison order is reversed. - */ - public boolean isComparisonOrderReversed() { - return isComparisonOrderReversed; - } - - /** - * {@inheritDoc} - */ - @Override - public String toQueryString() { - if (isComparisonOrderReversed) { - return value.toQueryString() + " " + operator.toQueryString() + " " - + column.toQueryString(); - } else { - return column.toQueryString() + " " + operator.toQueryString() + " " - + value.toQueryString(); - } - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((column == null) ? 0 : column.hashCode()); - result = prime * result + (isComparisonOrderReversed ? 1231 : 1237); - result = prime * result + ((value == null) ? 0 : value.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - ColumnValueFilter other = (ColumnValueFilter) obj; - if (column == null) { - if (other.column != null) { - return false; - } - } else if (!column.equals(other.column)) { - return false; - } - if (isComparisonOrderReversed != other.isComparisonOrderReversed) { - return false; - } - if (value == null) { - if (other.value != null) { - return false; - } - } else if (!value.equals(other.value)) { - return false; - } - return true; - } -} diff --git a/src/main/java/com/google/visualization/datasource/query/ComparisonFilter.java b/src/main/java/com/google/visualization/datasource/query/ComparisonFilter.java deleted file mode 100755 index 5bcd6e0..0000000 --- a/src/main/java/com/google/visualization/datasource/query/ComparisonFilter.java +++ /dev/null @@ -1,195 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query; - -import com.google.visualization.datasource.datatable.value.Value; - -import java.util.StringTokenizer; -import java.util.regex.Pattern; -import java.util.regex.PatternSyntaxException; - -/** - * A filter that decides upon a row by comparing two values. The values can be - * either column values or constant values, depending on the concrete class - * extending this one. - * - * @author Yonatan B.Y. - */ -public abstract class ComparisonFilter extends QueryFilter { - - /** - * The set of possible comparison operators for such filters. - */ - public static enum Operator { - EQ("=", true), - NE("!=", true), - LT("<", true), - GT(">", true), - LE("<=", true), - GE(">=", true), - CONTAINS("CONTAINS", false), - STARTS_WITH("STARTS WITH", false), - ENDS_WITH("ENDS WITH", false), - // Note that the operator syntax is: val MATCHES regexp. - MATCHES("MATCHES", false), - LIKE("LIKE", false); - - /** - * Initializes a new instance of this class, with the given boolean - * saying whether or not this instance requires the types to be equal. - * - * @param requiresEqualTypes True if this instance requires the types - * to be equal, false otherwise. - * @param queryStringForm The query string form of this operator. - */ - Operator(String queryStringForm, boolean requiresEqualTypes) { - this.queryStringForm = queryStringForm; - this.requiresEqualTypes = requiresEqualTypes; - } - - /** - * Returns whether or not this instance requires the two types to be equal. - * - * @return Whether or not this instance requires the two types to be equal. - */ - public boolean areEqualTypesRequired() { - return requiresEqualTypes; - } - - /** - * Returns the query string form of this operator. - * - * @return The query string form of this operator. - */ - public String toQueryString() { - return queryStringForm; - } - - /** - * True if this instance requires the two types to be equal. - */ - private boolean requiresEqualTypes; - - /** - * The query string form of this operator, i.e., how this operator should - * appear in a query string, to be parsed by the query parser. - */ - private String queryStringForm; - } - - /** - * The comparison operator for this filter. - */ - protected Operator operator; - - /** - * Constructs a new ComparisonFilter with the given operator. - * - * @param operator The comparison operator for this filter. - */ - protected ComparisonFilter(Operator operator) { - this.operator = operator; - } - - /** - * Returns true if s1 is "like" s2, in the sql-sense, i.e., if s2 has any - * %'s or _'s, they are treated as special characters corresponding to an - * arbitrary sequence of characters in s1 or to an abitrary character in s1 - * respectively. All other characters in s2 need to match exactly to - * characters in s1. You cannot escape these characters, so that you cannot - * match an explicit '%' or '_'. - * @param s1 The first string. - * @param s2 The second string. - * @return True if s1 is "like" s2, in the sql-sense. - */ - private boolean isLike(String s1, String s2) { - StringTokenizer tokenizer = new StringTokenizer(s2, "%_", true); - StringBuilder regexp = new StringBuilder(); - while (tokenizer.hasMoreTokens()) { - String s = tokenizer.nextToken(); - if (s.equals("%")) { - regexp.append(".*"); - } else if (s.equals("_")) { - regexp.append("."); - } else { - regexp.append(Pattern.quote(s)); - } - } - return s1.matches(regexp.toString()); - } - - /** - * Matches the given two values against the operator. E.g., if the operator is - * GT, returns true if v1 > v2. This implementation uses the - * compareTo() method. - * - * @param v1 The first value. - * @param v2 The second value. - * - * @return true if v1 op v2, false otherwise. - */ - protected boolean isOperatorMatch(Value v1, Value v2) { - if (operator.areEqualTypesRequired()) { - if (!v1.getType().equals(v2.getType())) { - return false; - } - } - - switch (operator) { - case EQ: - return (v1.compareTo(v2) == 0); - case NE: - return (v1.compareTo(v2) != 0); - case LT: - return (v1.compareTo(v2) < 0); - case GT: - return (v1.compareTo(v2) > 0); - case LE: - return (v1.compareTo(v2) <= 0); - case GE: - return (v1.compareTo(v2) >= 0); - case CONTAINS: - return v1.toString().contains(v2.toString()); - case STARTS_WITH: - return v1.toString().startsWith(v2.toString()); - case ENDS_WITH: - return v1.toString().endsWith(v2.toString()); - case MATCHES: - try { - return v1.toString().matches(v2.toString()); - } catch (PatternSyntaxException ex) { - return false; // a match against an illegal expression is false - } - case LIKE: - return isLike(v1.toString(), v2.toString()); - } - return false; // should never get here - } - - /** - * Returns the operator associated with this CompoundFilter. - * - * @return The operator associated with this CompoundFilter. - */ - public Operator getOperator() { - return operator; - } - - @Override - public abstract int hashCode(); - - @Override - public abstract boolean equals(Object obj); -} diff --git a/src/main/java/com/google/visualization/datasource/query/CompoundFilter.java b/src/main/java/com/google/visualization/datasource/query/CompoundFilter.java deleted file mode 100755 index 33431f7..0000000 --- a/src/main/java/com/google/visualization/datasource/query/CompoundFilter.java +++ /dev/null @@ -1,217 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Lists; -import com.google.common.collect.Sets; -import com.google.visualization.datasource.datatable.DataTable; -import com.google.visualization.datasource.datatable.TableRow; - -import org.apache.commons.lang.text.StrBuilder; - -import java.util.List; -import java.util.Set; - -/** - * A compound filter. - * This filter is a logical aggregation of other filters. Currently, - * union (OR) and intersection (AND) are supported. An OR complex filter matches if - * any of its sub-filters match. An AND complex filter matches if all of - * its sub-filters match. - * - * @author Yonatan B.Y. - */ -public class CompoundFilter extends QueryFilter { - - /** - * The available types of CompoundFilter. Currently supported are - * AndFilter and OrFilter. - */ - public static enum LogicalOperator { - AND, - OR - } - - /** - * The collection of all sub-filters of this compound filter. - */ - private List subFilters; - - /** - * The type of this compound filter ('and' or 'or'). - */ - private LogicalOperator operator; - - /** - * Constructs a compound filter of the given type, with the given sub-filters. - * - * @param operator The type of this compound filter. - * @param subFilters The collection of all sub-filters of this compound filter. - */ - public CompoundFilter(LogicalOperator operator, - List subFilters) { - this.subFilters = subFilters; - this.operator = operator; - } - - /** - * Implements isMatch (from the QueryFilter interface) by recursively calling - * isMatch on each of the sub-filters, and using the compound filter type to - * determine the result. - * Note: - * 1. This uses short-circuit evaluation, i.e., an OR filter decides on a true - * result the moment it finds a true result among its sub-filters, without - * continuing to check the rest of the sub-filters; and dually for an AND - * filter. - * 2. The sub-filters are evaluated in order. - * 3. If the collection of sub-filters is empty, a RuntimeException is - * thrown. - * - * @param table The table containing this row. - * @param row The row to check. - * - * @return true if this row should be part of the result set, false otherwise. - */ - @Override - public boolean isMatch(DataTable table, TableRow row) { - if (subFilters.isEmpty()) { - throw new RuntimeException("Compound filter with empty subFilters " - + "list"); - } - for (QueryFilter subFilter : subFilters) { - boolean result = subFilter.isMatch(table, row); - if (((operator == LogicalOperator.AND) && !result) || - ((operator == LogicalOperator.OR) && result)) { - return result; - } - } - return (operator == LogicalOperator.AND); - } - - /** - * Returns all the columnIds this filter uses, in this case the union of all - * the results of getAllColumnIds() of all its subfilters. - * - * @return All the columnIds this filter uses. - */ - @Override - public Set getAllColumnIds() { - Set result = Sets.newHashSet(); - for (QueryFilter subFilter : subFilters) { - result.addAll(subFilter.getAllColumnIds()); - } - return result; - } - - /** - * Returns a list of all scalarFunctionColumns this filter uses, in this case - * the union of all the results of getScalarFunctionColumns() of all its - * sub-filters. - * - * @return A list of all scalarFunctionColumns this filter uses. - */ - @Override - public List getScalarFunctionColumns() { - List result = Lists.newArrayList(); - for (QueryFilter subFilter : subFilters) { - result.addAll(subFilter.getScalarFunctionColumns()); - } - return result; - } - - /** - * {@InheritDoc} - */ - @Override - protected List getAggregationColumns() { - List result = Lists.newArrayList(); - for (QueryFilter subFilter : subFilters) { - result.addAll(subFilter.getAggregationColumns()); - } - return result; - } - - /** - * Returns the list of sub-filters associated with this CompoundFilter. - * - * @return The list of sub-filters associated with this CompoundFilter. - */ - public List getSubFilters() { - return ImmutableList.copyOf(subFilters); - } - - /** - * Returns the logical operator associated with this CompoundFilter. - * - * @return The logical operator associated with this CompoundFilter. - */ - public LogicalOperator getOperator() { - return operator; - } - - /** - * {@inheritDoc} - */ - @Override - public String toQueryString() { - List subFilterStrings = Lists.newArrayList(); - for (QueryFilter filter : subFilters) { - subFilterStrings.add("(" + filter.toQueryString() + ")"); - } - // This works because the names in LogicalOperator are exactly the same as - // in the query language. - return new StrBuilder() - .appendWithSeparators(subFilterStrings, " " + operator.name() + " ").toString(); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((operator == null) ? 0 : operator.hashCode()); - result = prime * result + ((subFilters == null) ? 0 : subFilters.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - CompoundFilter other = (CompoundFilter) obj; - if (operator == null) { - if (other.operator != null) { - return false; - } - } else if (!operator.equals(other.operator)) { - return false; - } - if (subFilters == null) { - if (other.subFilters != null) { - return false; - } - } else if (!subFilters.equals(other.subFilters)) { - return false; - } - return true; - } -} diff --git a/src/main/java/com/google/visualization/datasource/query/DataTableColumnLookup.java b/src/main/java/com/google/visualization/datasource/query/DataTableColumnLookup.java deleted file mode 100755 index e1e5398..0000000 --- a/src/main/java/com/google/visualization/datasource/query/DataTableColumnLookup.java +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query; - -import com.google.visualization.datasource.datatable.DataTable; - -/** - * An adapter between a data table and a column lookup. - * The table does not have to contain rows; only the columns data is used. - * - * @author Liron L. - */ -public class DataTableColumnLookup implements ColumnLookup { - - /** - * The table. - */ - private DataTable table; - - /** - * Creates a new DataTableColumnLookup with the given data table. - * - * @param table The given TableDescription. - */ - public DataTableColumnLookup(DataTable table) { - this.table = table; - } - - @Override - public int getColumnIndex(AbstractColumn column) { - return table.getColumnIndex(column.getId()); - } - - @Override - public boolean containsColumn(AbstractColumn column) { - return table.containsColumn(column.getId()); - } -} diff --git a/src/main/java/com/google/visualization/datasource/query/GenericColumnLookup.java b/src/main/java/com/google/visualization/datasource/query/GenericColumnLookup.java deleted file mode 100755 index b3ffe4d..0000000 --- a/src/main/java/com/google/visualization/datasource/query/GenericColumnLookup.java +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query; - -import com.google.common.collect.Maps; - -import java.util.Map; - -/** - * This class represents a generic column lookup. It maps an abstract - * column to its index in a table description. - * - * @author Liron L. - */ -public class GenericColumnLookup implements ColumnLookup { - - /** - * A map from the column to its index in the table description. - */ - private Map columnIndexByColumn; - - /** - * Create a GenericColumnLookup (with an empty map). - */ - public GenericColumnLookup() { - columnIndexByColumn = Maps.newHashMap(); - } - - /** - * Clear all data of this GenericColumnLookup. - */ - public void clear() { - columnIndexByColumn.clear(); - } - - /** - * Sets the index of the given column to the given number. - * - * @param col The column to set the index of. - * @param index The index to set for the column. - */ - public void put(AbstractColumn col, int index) { - columnIndexByColumn.put(col, index); - } - - /** - * Returns the column index in the columns of a row (first is zero). - * - * @param column The column. - * - * @return The column index in the columns of a row (first is zero). - */ - public int getColumnIndex(AbstractColumn column) { - return columnIndexByColumn.get(column); - } - - @Override - public boolean containsColumn(AbstractColumn column) { - return columnIndexByColumn.containsKey(column); - } -} diff --git a/src/main/java/com/google/visualization/datasource/query/NegationFilter.java b/src/main/java/com/google/visualization/datasource/query/NegationFilter.java deleted file mode 100755 index 518e85f..0000000 --- a/src/main/java/com/google/visualization/datasource/query/NegationFilter.java +++ /dev/null @@ -1,135 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query; - -import com.google.visualization.datasource.datatable.DataTable; -import com.google.visualization.datasource.datatable.TableRow; - -import java.util.List; -import java.util.Set; - -/** - * A negation filter. - * Holds a sub-filter and negates its result, acting like the NOT operator. - * - * @author Yonatan B.Y. - */ -public class NegationFilter extends QueryFilter { - - /** - * The sub-filter of this negation filter. - */ - private QueryFilter subFilter; - - /** - * Constructs a negation filter, with the given sub-filter. - * - * @param subFilter The sub-filter of this negation filter. - */ - public NegationFilter(QueryFilter subFilter) { - this.subFilter = subFilter; - } - - /** - * Implements isMatch (from the QueryFilter interface) by recursively calling - * isMatch on the sub-filter and negating the result. - * - * @param table The table containing this row. - * @param row The row to check. - * - * @return true if this row should be part of the result set, false otherwise. - */ - @Override - public boolean isMatch(DataTable table, TableRow row) { - return !subFilter.isMatch(table, row); - } - - /** - * Returns all the columnIds this filter uses, in this case exactly all the - * columnIds that the sub-filter uses. - * - * @return All the columnIds this filter uses. - */ - @Override - public Set getAllColumnIds() { - return subFilter.getAllColumnIds(); - } - - /** - * Returns a list of all scalarFunctionColumns this filter uses, in this case - * the scalarFunctionColumns its sub-filter uses. - * - * @return A list of all scalarFunctionColumns this filter uses. - */ - @Override - public List getScalarFunctionColumns() { - return subFilter.getScalarFunctionColumns(); - } - - /** - * {@InheritDoc} - */ - @Override - protected List getAggregationColumns() { - return subFilter.getAggregationColumns(); - } - - /** - * Returns the sub-filter associated with this NegationFilter. - * - * @return The sub-filter associated with this NegationFilter. - */ - public QueryFilter getSubFilter() { - return subFilter; - } - - /** - * {@inheritDoc} - */ - @Override - public String toQueryString() { - return "NOT (" + subFilter.toQueryString() + ")"; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((subFilter == null) ? 0 : subFilter.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - NegationFilter other = (NegationFilter) obj; - if (subFilter == null) { - if (other.subFilter != null) { - return false; - } - } else if (!subFilter.equals(other.subFilter)) { - return false; - } - return true; - } -} diff --git a/src/main/java/com/google/visualization/datasource/query/Query.java b/src/main/java/com/google/visualization/datasource/query/Query.java deleted file mode 100755 index 7aba9aa..0000000 --- a/src/main/java/com/google/visualization/datasource/query/Query.java +++ /dev/null @@ -1,1167 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query; - -import com.google.common.collect.Lists; -import com.google.common.collect.Sets; -import com.google.visualization.datasource.base.InvalidQueryException; -import com.google.visualization.datasource.base.MessagesEnum; - -import com.ibm.icu.util.ULocale; - -import org.apache.commons.lang.text.StrBuilder; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.util.List; -import java.util.Set; - -/** - * Holds the query data and clauses. This class is the result of parsing the query - * string that comes from the user. - * The clauses that can be included in a query are: select, filter, sort, group by, pivot, options, - * labels, format, limit, offset and skipping. - * For more details see the - * - * query language reference - * . - * A Query can be executed by the query engine - * (see: {@link com.google.visualization.datasource.DataSourceHelper#applyQuery}). - * It can be split in 2 Query objects based on the Capabilities value - * (see: {@link com.google.visualization.datasource.DataSourceHelper#splitQuery}). - * - * Note on errors: Since this class handles a user generated query, all errors - * (of type INVALID_QUERY) should provide a descriptive error message for both - * the user. - * - * @author Itai R. - * @author Yonatan B.Y. - */ -public class Query { - - /** - * Log. - */ - private static final Log log = LogFactory.getLog(Query.class.getName()); - - /** - * Checks the given list for duplicates. Throws an exception if a duplicate - * is found, giving as a message a description containing information on which - * item was found to be duplicate, and in which clause it occurred (the - * clause name is given). - * - * @param selectionColumns The list to check for duplicates. - * @param clauseName The clause name to report in the exception message. - * @param userLocale The user locale. - * - * @throws InvalidQueryException Thrown if a duplicate was found. - */ - private static void checkForDuplicates(List - selectionColumns, String clauseName, ULocale userLocale) throws InvalidQueryException { - for (int i = 0; i < selectionColumns.size(); i++) { - T col = selectionColumns.get(i); - for (int j = i + 1; j < selectionColumns.size(); j++) { - if (col.equals(selectionColumns.get(j))) { - String[] args = {col.toString(), clauseName}; - String messageToLogAndUser = MessagesEnum.COLUMN_ONLY_ONCE.getMessageWithArgs(userLocale, - args); - log.error(messageToLogAndUser); - throw new InvalidQueryException(messageToLogAndUser); - } - } - } - } - - /** - * The required sort order. - */ - private QuerySort sort = null; - - /** - * The required selection. - * If the selection is null, or is empty, the original - * selection that was defined in the report is used. - */ - protected QuerySelection selection = null; - - /** - * The required filter. - * If the filter is null, then the results are not filtered at all. - */ - private QueryFilter filter = null; - - /** - * The required grouping. - */ - private QueryGroup group = null; - - /** - * The required pivoting. - */ - private QueryPivot pivot = null; - - /** - * The number of rows to skip when selecting only a subset of the rows using - * skipping clause, e.g., skipping 4. - * If a skipping clause, "skip k", is added to the query, the resulting table - * will be consisted of the first row of every k rows of the table returned by - * the earlier part of the query, when k corresponds to rowSkipping value. - * For example, if rowSkipping = 10 the returned table will consist of rows 0, 10... - * The default value is 0, meaning no skipping should be performed. - */ - private int rowSkipping = 0; - - /** - * Max number of rows to return to caller. - * If the caller specified this parameter, and the data table returned from - * the data source contains more than this number of rows, then the result is - * truncated, and the query result contains a warning with this reason. - * If this value is set to -1, which can only be done internally, this is ignored. - * (0 is a legal value, denoting no rows should be retrieved). - */ - private int rowLimit = -1; - - /** - * The number of rows that should be removed from the beginning of the - * data table. - * Together with the row limit parameter, this enables pagination. - * The default value is 0, (skip 0 rows) - which means start from the - * first row. - */ - private int rowOffset = 0; - - /** - * Additional options for the query. - */ - private QueryOptions options = null; - - /** - * Column labels as specified in the query. - */ - private QueryLabels labels = null; - - /** - * Column formatting patterns as specified in the query. - */ - private QueryFormat userFormatOptions = null; - - /** - * The user locale, Used to create localized messages. - */ - private ULocale localeForUserMessages = null; - - /** - * Constructs a new, empty, query. - */ - public Query() { - } - - /** - * Set the required sort of the query result. - * - * @param sort The required sort of the query result. - */ - public void setSort(QuerySort sort) { - this.sort = sort; - } - - /** - * Returns the required sort of the query result. - * - * @return The required sort of the query result. - */ - public QuerySort getSort() { - return sort; - } - - /** - * Returns true if the query has a non empty sort-by section. - * - * @return True if the query has a non empty sort-by section. - */ - public boolean hasSort() { - return (sort != null) && (!sort.isEmpty()); - } - - /** - * Set the required selection of the query result. - * - * @param selection The required selection of the query result. - */ - public void setSelection(QuerySelection selection) { - this.selection = selection; - } - - /** - * Returns the required selection of the query result. - * - * @return The required selection of the query result. - */ - public QuerySelection getSelection() { - return selection; - } - - /** - * Returns true if there is a non-trivial selection, i.e. if not all columns - * should be selected. - * - * @return True if there is a non-trivial selection. - */ - public boolean hasSelection() { - return (selection != null) && (!selection.isEmpty()); - } - - /** - * Set the required filter of this query. - * - * @param filter The required filter of this query. - */ - public void setFilter(QueryFilter filter) { - this.filter = filter; - } - - /** - * Returns the required filter of this query. - * - * @return The required filter of this query. - */ - public QueryFilter getFilter() { - return filter; - } - - /** - * Returns whether or not this query has a filter defined. - * - * @return true if this query has a filter defined. - */ - public boolean hasFilter() { - return (filter != null); - } - - /** - * Sets the required group of the query result. - * - * @param group The required group of the query result. - */ - public void setGroup(QueryGroup group) { - this.group = group; - } - - /** - * Sets the required pivot of the query result. - * - * @param pivot The required pivot of the query result. - */ - public void setPivot(QueryPivot pivot) { - this.pivot = pivot; - } - - /** - * Returns the required group of the query result. - * - * @return The required group of the query result. - */ - public QueryGroup getGroup() { - return group; - } - - /** - * Returns true if the query has a group-by section. - * - * @return True if the query has a group-by section. - */ - public boolean hasGroup() { - return group != null && !group.getColumnIds().isEmpty(); - } - - /** - * Returns the required pivot of the query result. - * - * @return The required pivot of the query result. - */ - public QueryPivot getPivot() { - return pivot; - } - - /** - * Returns true if the query has a pivot-by section. - * - * @return True if the query has a pivot-by section. - */ - public boolean hasPivot() { - return pivot != null && !pivot.getColumnIds().isEmpty(); - } - - /** - * Returns the number of rows to skip when selecting only a subset of - * the rows using skipping clause, e.g., skipping 4. - * The default value is 0, meaning no skipping should be performed. - * - * @return The number of rows to skip between each row selection. - */ - public int getRowSkipping() { - return rowSkipping; - } - - /** - * Sets the number of rows to skip when selecting only a subset of - * the rows using skipping clause, e.g., skipping 4. - * The default value is 0, meaning no skipping should be performed. - * - * If there is is an attempt to set the skipping value to non positive value, - * then an InvalidQueryException is thrown. - * - * @param rowSkipping The number of rows to skip between each row selection. - * 0 value means no skipping. - * - * @throws InvalidQueryException Thrown if an invalid value is specified. - */ - public void setRowSkipping(int rowSkipping) throws InvalidQueryException { - if (rowSkipping < 0) { - String messageToLogAndUser = MessagesEnum.INVALID_SKIPPING.getMessageWithArgs( - localeForUserMessages, Integer.toString(rowSkipping)); - log.error(messageToLogAndUser); - throw new InvalidQueryException(messageToLogAndUser); - } - this.rowSkipping = rowSkipping; - } - - /** - * Sets the number of rows to skip when selecting only a subset of - * the row, based on another query. - * - * @param originalQuery The query from which the row skipping should be taken. - */ - public void copyRowSkipping(Query originalQuery) { - rowSkipping = originalQuery.getRowSkipping(); - } - - /** - * Returns true if this query has a row skipping set. A value of 0 means no - * skipping. - * - * @return True if this query has a row skipping set. - */ - public boolean hasRowSkipping() { - return rowSkipping > 0; - } - - /** - * Returns the maximum number of rows to return to the caller. - * If the caller specified this parameter, and the data table returned from - * the data source contains more than this number of rows, then the result is - * truncated, and the query result contains a warning with this reason. - * If this value is set to -1 it is just ignored, but this can only be done - * internally. - * - * @return The maximum number of rows to return to the caller. - */ - public int getRowLimit() { - return rowLimit; - } - - /** - * Sets the max number of rows to return to the caller. - * If the caller specified this parameter, and the data table returned from - * the data source contains more than this number of rows, then the result is - * truncated, and the query result contains a warning with this reason. - * By default, this is set to -1, which means that no limit is requested. - * - * If there is is an attempt to set the limit value to any negative number - * smaller than -1 (which means no limit), then an InvalidQueryException is - * thrown. - * - * @param rowLimit The max number of rows to return. - * - * @throws InvalidQueryException Thrown if an invalid value is specified. - */ - public void setRowLimit(int rowLimit) throws InvalidQueryException { - if (rowLimit < -1) { - String messageToLogAndUser = "Invalid value for row limit: " + rowLimit; - log.error(messageToLogAndUser); - throw new InvalidQueryException(messageToLogAndUser); - } - this.rowLimit = rowLimit; - } - - /** - * Sets the max number of rows to return to the caller, based on another - * query. - * - * @param originalQuery The query from which the row limit should be taken. - */ - public void copyRowLimit(Query originalQuery) { - rowLimit = originalQuery.getRowLimit(); - } - - /** - * Returns true if this query has a row limit set. A value of -1 means no - * limit so in case of -1 this function returns true. - * - * @return True if this query has a row limit set. - */ - public boolean hasRowLimit() { - return rowLimit > -1; - } - - /** - * Returns the number of rows that should be removed from the beginning of the - * data table. - * Together with the row limit parameter, this enables pagination. - * The default value is 0, (skip 0 rows) - which means to start from the - * first row. - * - * @return The number of rows to skip from the beginning of the table. - */ - public int getRowOffset() { - return rowOffset; - } - - /** - * Sets the number of rows that should be removed from the beginning of the - * data table. - * Together with the row limit parameter, this enables pagination. - * The default value is 0, (skip 0 rows) - which means to start from the - * first row. - * - * If there is is an attempt to set the offset value to any negative number, - * then an InvalidQueryException is thrown. - * - * @param rowOffset The number of rows to skip from the beginning of the - * table. - * - * @throws InvalidQueryException Thrown if an invalid value is specified. - */ - public void setRowOffset(int rowOffset) throws InvalidQueryException { - if (rowOffset < 0) { - String messageToLogAndUser = MessagesEnum.INVALID_OFFSET.getMessageWithArgs( - localeForUserMessages, Integer.toString(rowOffset)); - log.error(messageToLogAndUser); - throw new InvalidQueryException(messageToLogAndUser); - } - this.rowOffset = rowOffset; - } - - /** - * Sets the number of rows to skip, based on another query. - * - * @param originalQuery The query from which the row offset should be taken. - */ - public void copyRowOffset(Query originalQuery) { - rowOffset = originalQuery.getRowOffset(); - } - - /** - * Returns true if this query has a row offset set. A value of 0 means no - * offset so in case of 0 this function returns true. - * - * @return True if this query has a row offset set. - */ - public boolean hasRowOffset() { - return rowOffset > 0; - } - - /** - * Returns the query formatting options. - * - * @return The query formatting options. - */ - public QueryFormat getUserFormatOptions() { - return userFormatOptions; - } - - /** - * Sets the user formatting options map. - * @param userFormatOptions A map of patterns to column IDs. - */ - public void setUserFormatOptions(QueryFormat userFormatOptions) { - this.userFormatOptions = userFormatOptions; - } - - /** - * Returns true if this query has user format options defined. - * - * @return True if this query has user format options defined. - */ - public boolean hasUserFormatOptions() { - return (userFormatOptions != null) - && (!userFormatOptions.getColumns().isEmpty()); - } - - /** - * Returns the query labels. - * - * @return The query labels. - */ - public QueryLabels getLabels() { - return labels; - } - - /** - * Sets the query labels. - * @param labels A map of labels to column IDs. - */ - public void setLabels(QueryLabels labels) { - this.labels = labels; - } - - /** - * Returns true if this query has labels defined. - * - * @return True if this query has labels defined. - */ - public boolean hasLabels() { - return (labels != null) - && (!labels.getColumns().isEmpty()); - } - - /** - * Returns the options for this query. - * - * @return The options for this query. - */ - public QueryOptions getOptions() { - return options; - } - - /** - * Sets the required options for this query. - * - * @param options The required options. - */ - public void setOptions(QueryOptions options) { - this.options = options; - } - - /** - * Returns true if this query has any nondefault options set. - * - * @return True if this query has any nondefault options set. - */ - public boolean hasOptions() { - return (options != null) - && (!options.isDefault()); - } - - /** - * Returns true if the query is empty, i.e. has no clauses or all the clauses are empty. - * - * @return true if the query is empty. - */ - public boolean isEmpty() { - return (!hasSort() && !hasSelection() && !hasFilter() && !hasGroup() && !hasPivot() - && !hasRowSkipping() && !hasRowLimit() && !hasRowOffset() - && !hasUserFormatOptions() && !hasLabels() && !hasOptions()); - } - - - /** - * Sets the user locale for creating localized messages. - * @param userLocale the user locale. - */ - public void setLocaleForUserMessages(ULocale localeForUserMessges) { - this.localeForUserMessages = localeForUserMessges; - } - - /** - * Copies all information from the given query to this query. - * - * @param query The query to copy from. - */ - public void copyFrom(Query query) { - setSort(query.getSort()); - setSelection(query.getSelection()); - setFilter(query.getFilter()); - setGroup(query.getGroup()); - setPivot(query.getPivot()); - copyRowSkipping(query); - copyRowLimit(query); - copyRowOffset(query); - setUserFormatOptions(query.getUserFormatOptions()); - setLabels(query.getLabels()); - setOptions(query.getOptions()); - } - - /** - * Validates the query. Runs a sanity check on the query, verifies that there are no - * duplicates, and that the query follows a basic set of rules required for its execution. - * - * Specifically, verifies the following: - * - There are no duplicate columns in the clauses. - * - No column appears both as a selection and as an aggregation. - * - When aggregation is used, checks that all selected columns are valid (a column is valid if - * it is either grouped-by, or is a scalar function column the arguments of which are all - * valid columns). - * - No column is both grouped-by, and aggregated in, the select clause. - * - No column both appears as pivot, and aggregated in, the select clause. - * - No grouping/pivoting is used when there is no aggregation in the select clause. - * - If aggregation is used in the select clause, no column is ordered-by that is not in the - * select clause. - * - No column appears both as a group-by and a pivot. - * - If pivoting is used, the order by clause does not contain aggregation columns. - * - The order-by clause does not contain aggregation columns that were not defined in the select - * clause. - * - * @throws InvalidQueryException - */ - public void validate() throws InvalidQueryException { - // Set up some variables. - List groupColumnIds = - hasGroup() ? group.getColumnIds() : Lists.newArrayList(); - List groupColumns = hasGroup() ? group.getColumns() : - Lists.newArrayList(); - List pivotColumnIds = - hasPivot() ? pivot.getColumnIds() : Lists.newArrayList(); - List selectionColumns = hasSelection() - ? selection.getColumns() : Lists.newArrayList(); - List selectionAggregated = - hasSelection() ? selection.getAggregationColumns() : - Lists.newArrayList(); - List selectionSimple = hasSelection() - ? selection.getSimpleColumns() : Lists.newArrayList(); - List selectedScalarFunctionColumns = hasSelection() - ? selection.getScalarFunctionColumns() - : Lists.newArrayList(); - selectedScalarFunctionColumns.addAll(selectedScalarFunctionColumns); - List sortColumns = hasSort() ? sort.getColumns() : - Lists.newArrayList(); - List sortAggregated = hasSort() - ? sort.getAggregationColumns() - : Lists.newArrayList(); - - // Check for duplicates. - checkForDuplicates(selectionColumns, "SELECT", localeForUserMessages); - checkForDuplicates(sortColumns, "ORDER BY", localeForUserMessages); - checkForDuplicates(groupColumnIds, "GROUP BY", localeForUserMessages); - checkForDuplicates(pivotColumnIds, "PIVOT", localeForUserMessages); - - // Cannot have aggregations in either group by, pivot, or where. - if (hasGroup()) { - for (AbstractColumn column : group.getColumns()) { - if (!column.getAllAggregationColumns().isEmpty()) { - String messageToLogAndUser = MessagesEnum.CANNOT_BE_IN_GROUP_BY.getMessageWithArgs( - localeForUserMessages, column.toQueryString()); - log.error(messageToLogAndUser); - throw new InvalidQueryException(messageToLogAndUser); - } - } - } - if (hasPivot()) { - for (AbstractColumn column : pivot.getColumns()) { - if (!column.getAllAggregationColumns().isEmpty()) { - String messageToLogAndUser = MessagesEnum.CANNOT_BE_IN_PIVOT.getMessageWithArgs( - localeForUserMessages, column.toQueryString()); - log.error(messageToLogAndUser); - throw new InvalidQueryException(messageToLogAndUser); - } - } - } - if (hasFilter()) { - List filterAggregations = filter.getAggregationColumns(); - if (!filterAggregations.isEmpty()) { - String messageToLogAndUser = MessagesEnum.CANNOT_BE_IN_WHERE.getMessageWithArgs( - localeForUserMessages, filterAggregations.get(0).toQueryString());; - log.error(messageToLogAndUser); - throw new InvalidQueryException(messageToLogAndUser); - } - } - - // A column cannot appear both as an aggregation column and as a regular - // column in the selection. - for (SimpleColumn column1 : selectionSimple) { - String id = column1.getColumnId(); - for (AggregationColumn column2 : selectionAggregated) { - if (id.equals(column2.getAggregatedColumn().getId())) { - String messageToLogAndUser = MessagesEnum.SELECT_WITH_AND_WITHOUT_AGG.getMessageWithArgs( - localeForUserMessages, id); - log.error(messageToLogAndUser); - throw new InvalidQueryException(messageToLogAndUser); - } - } - } - - // When aggregation is used, check that all selected columns are valid - // (a column is valid if it is either grouped-by, or is a - // scalar function column whose arguments are all valid columns). - if (!selectionAggregated.isEmpty()) { - for (AbstractColumn col : selectionColumns) { - checkSelectedColumnWithGrouping(groupColumns, col); - } - } - - // Cannot group by a column that appears in an aggregation. - if (hasSelection() && hasGroup()) { - for (AggregationColumn column : selectionAggregated) { - String id = column.getAggregatedColumn().getId(); - if (groupColumnIds.contains(id)) { - String messageToLogAndUser = MessagesEnum.COL_AGG_NOT_IN_SELECT.getMessageWithArgs( - localeForUserMessages, id); - log.error(messageToLogAndUser); - throw new InvalidQueryException(messageToLogAndUser); - } - } - } - - // Cannot use grouping or pivoting when no aggregations are defined in the - // selection. - if (hasGroup() && selectionAggregated.isEmpty()) { - String messageToLogAndUser = MessagesEnum.CANNOT_GROUP_WITNOUT_AGG.getMessage( - localeForUserMessages); - log.error(messageToLogAndUser); - throw new InvalidQueryException(messageToLogAndUser); - } - if (hasPivot() && selectionAggregated.isEmpty()) { - String messageToLogAndUser = MessagesEnum.CANNOT_PIVOT_WITNOUT_AGG.getMessage( - localeForUserMessages); - log.error(messageToLogAndUser); - throw new InvalidQueryException(messageToLogAndUser); - } - - // Cannot order by a column that is not in the selection when aggregations - // are defined. - if (hasSort() && !selectionAggregated.isEmpty()) { - for (AbstractColumn column : sort.getColumns()) { - String messageToLogAndUser = MessagesEnum.COL_IN_ORDER_MUST_BE_IN_SELECT.getMessageWithArgs( - localeForUserMessages, column.toQueryString()); - checkColumnInList(selection.getColumns(), column, - messageToLogAndUser); - } - } - - // Cannot pivot by a column that appears in an aggregation. - if (hasPivot()) { - for (AggregationColumn column : selectionAggregated) { - String id = column.getAggregatedColumn().getId(); - if (pivotColumnIds.contains(id)) { - String messageToLogAndUser = MessagesEnum.AGG_IN_SELECT_NO_PIVOT.getMessageWithArgs( - localeForUserMessages, id); - log.error(messageToLogAndUser); - throw new InvalidQueryException(messageToLogAndUser); - } - } - } - - // Cannot have a column appear in both group by and pivot. - if (hasGroup() && hasPivot()) { - for (String id : groupColumnIds) { - if (pivotColumnIds.contains(id)) { - String messageToLogAndUser = MessagesEnum.NO_COL_IN_GROUP_AND_PIVOT.getMessageWithArgs( - localeForUserMessages, id); - log.error(messageToLogAndUser); - throw new InvalidQueryException(messageToLogAndUser); - } - } - } - - // Cannot order by aggregation column when pivoting is used. - if (hasPivot() && !sortAggregated.isEmpty()) { - AggregationColumn column = sortAggregated.get(0); - String messageToLogAndUser = MessagesEnum.NO_AGG_IN_ORDER_WHEN_PIVOT.getMessageWithArgs( - localeForUserMessages, column.getAggregatedColumn().getId()); - log.error(messageToLogAndUser); - throw new InvalidQueryException(messageToLogAndUser); - } - - // Cannot order by aggregation columns that weren't defined in the - // selection. - for (AggregationColumn column : sortAggregated) { - String messageToLogAndUser = MessagesEnum.AGG_IN_ORDER_NOT_IN_SELECT.getMessageWithArgs( - localeForUserMessages, column.toQueryString()); - checkColumnInList(selectionAggregated, column, messageToLogAndUser); - } - - Set labelColumns = (hasLabels() - ? labels.getColumns() : Sets.newHashSet()); - Set formatColumns = (hasUserFormatOptions() - ? userFormatOptions.getColumns() : Sets.newHashSet()); - - if (hasSelection()) { - for (AbstractColumn col : labelColumns) { - if (!selectionColumns.contains(col)) { - String messageToLogAndUser = MessagesEnum.LABEL_COL_NOT_IN_SELECT.getMessageWithArgs( - localeForUserMessages, col.toQueryString()); - log.error(messageToLogAndUser); - throw new InvalidQueryException(messageToLogAndUser); - } - } - for (AbstractColumn col : formatColumns) { - if (!selectionColumns.contains(col)) { - String messageToLogAndUser = MessagesEnum.FORMAT_COL_NOT_IN_SELECT.getMessageWithArgs( - localeForUserMessages, col.toQueryString()); - log.error(messageToLogAndUser); - throw new InvalidQueryException(messageToLogAndUser); - } - } - } - } - - /** - * Returns all simple column IDs in use in all parts of the query. - * - * @return All simple column IDs in use in all parts of the query. - */ - public Set getAllColumnIds() { - Set result = Sets.newHashSet(); - if (hasSelection()) { - for (AbstractColumn col : selection.getColumns()) { - result.addAll(col.getAllSimpleColumnIds()); - } - } - if (hasSort()) { - for (AbstractColumn col : sort.getColumns()) { - result.addAll(col.getAllSimpleColumnIds()); - } - } - if (hasGroup()) { - result.addAll(getGroup().getSimpleColumnIds()); - } - if (hasPivot()) { - result.addAll(getPivot().getSimpleColumnIds()); - } - if (hasFilter()) { - result.addAll(getFilter().getAllColumnIds()); - } - if (hasLabels()) { - for (AbstractColumn col : labels.getColumns()) { - result.addAll(col.getAllSimpleColumnIds()); - } - } - if (hasUserFormatOptions()) { - for (AbstractColumn col : userFormatOptions.getColumns()) { - result.addAll(col.getAllSimpleColumnIds()); - } - } - - return result; - } - - /** - * Returns all aggregation columns used in all parts of this query. - * - * @return All aggregation columns used in all parts of this query. - */ - public Set getAllAggregations() { - Set result = Sets.newHashSet(); - if (hasSelection()) { - result.addAll(selection.getAggregationColumns()); - } - if (hasSort()) { - for (AbstractColumn col : sort.getColumns()) { - if (col instanceof AggregationColumn) { - result.add((AggregationColumn) col); - } - } - } - - if (hasLabels()) { - for (AbstractColumn col : labels.getColumns()) { - if (col instanceof AggregationColumn) { - result.add((AggregationColumn) col); - } - } - } - if (hasUserFormatOptions()) { - for (AbstractColumn col : userFormatOptions.getColumns()) { - if (col instanceof AggregationColumn) { - result.add((AggregationColumn) col); - } - } - } - return result; - } - - /** - * Returns all scalar function columns in this query. - * - * @return All scalar function columns in this query. - */ - public Set getAllScalarFunctionsColumns() { - Set mentionedScalarFunctionColumns = - Sets.newHashSet(); - if (hasSelection()) { - mentionedScalarFunctionColumns.addAll( - selection.getScalarFunctionColumns()); - } - if (hasFilter()) { - mentionedScalarFunctionColumns.addAll(filter.getScalarFunctionColumns()); - } - if (hasGroup()) { - mentionedScalarFunctionColumns.addAll(group.getScalarFunctionColumns()); - } - if (hasPivot()) { - mentionedScalarFunctionColumns.addAll(pivot.getScalarFunctionColumns()); - } - if (hasSort()) { - mentionedScalarFunctionColumns.addAll(sort.getScalarFunctionColumns()); - } - if (hasLabels()) { - mentionedScalarFunctionColumns.addAll(labels.getScalarFunctionColumns()); - } - if (hasUserFormatOptions()) { - mentionedScalarFunctionColumns.addAll(userFormatOptions.getScalarFunctionColumns()); - } - return mentionedScalarFunctionColumns; - } - - - /** - * Checks that the given column is valid, i.e., is in the given list of - * columns, or is a scalar function column and all its inner columns are - * valid (i.e., in the list). - * - * @param columns The given list of columns. - * @param column The given column. - * @param messageToLogAndUser The error message for the exception that is - * thrown when the column is not in the list. - * - * @throws InvalidQueryException Thrown when the column is invalid. - */ - private void checkColumnInList(List columns, - AbstractColumn column, String messageToLogAndUser) - throws InvalidQueryException { - if (columns.contains(column)) { - return; - } else if (column instanceof ScalarFunctionColumn) { - List innerColumns = - ((ScalarFunctionColumn) column).getColumns(); - for (AbstractColumn innerColumn : innerColumns) { - checkColumnInList(columns, innerColumn, messageToLogAndUser); - } - } else { - log.error(messageToLogAndUser); - throw new InvalidQueryException(messageToLogAndUser); - } - } - - /** - * Checks the selection of the given column is valid, given the group - * columns. A column is valid in this sense if it is either grouped-by, or is - * a scalar function column whose arguments are all valid columns. - * - * @param groupColumns The group columns. - * @param col The selected column. - * - * @throws InvalidQueryException Thrown when the given column is a simple - * column that is not grouped by. - */ - private void checkSelectedColumnWithGrouping( - List groupColumns, AbstractColumn col) - throws InvalidQueryException { - if (col instanceof SimpleColumn) { - if (!groupColumns.contains(col)) { - String messageToLogAndUser = MessagesEnum.ADD_COL_TO_GROUP_BY_OR_AGG.getMessageWithArgs( - localeForUserMessages, col.getId()); - log.error(messageToLogAndUser); - throw new InvalidQueryException(messageToLogAndUser); - } - } else if (col instanceof ScalarFunctionColumn) { - // A selected scalar function column is valid if it is grouped by, or if - // its inner columns are all valid. - if (!groupColumns.contains(col)) { - List innerColumns = - ((ScalarFunctionColumn) col).getColumns(); - for (AbstractColumn innerColumn : innerColumns) { - checkSelectedColumnWithGrouping(groupColumns, innerColumn); - } - } - } - // An aggregation column is always valid (the inner aggregated column - // validity is checked elsewhere). - } - - @Override - public int hashCode() { - final int prime = 37; - int result = 1; - result = prime * result + ((filter == null) ? 0 : filter.hashCode()); - result = prime * result + ((group == null) ? 0 : group.hashCode()); - result = prime * result + ((labels == null) ? 0 : labels.hashCode()); - result = prime * result + ((options == null) ? 0 : options.hashCode()); - result = prime * result + ((pivot == null) ? 0 : pivot.hashCode()); - result = prime * result + rowSkipping; - result = prime * result + rowLimit; - result = prime * result + rowOffset; - result = prime * result + ((selection == null) ? 0 : selection.hashCode()); - result = prime * result + ((sort == null) ? 0 : sort.hashCode()); - result = prime * result + ((userFormatOptions == null) ? 0 : userFormatOptions.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - Query other = (Query) obj; - if (filter == null) { - if (other.filter != null) { - return false; - } - } else if (!filter.equals(other.filter)) { - return false; - } - if (group == null) { - if (other.group != null) { - return false; - } - } else if (!group.equals(other.group)) { - return false; - } - if (labels == null) { - if (other.labels != null) { - return false; - } - } else if (!labels.equals(other.labels)) { - return false; - } - if (options == null) { - if (other.options != null) { - return false; - } - } else if (!options.equals(other.options)) { - return false; - } - if (pivot == null) { - if (other.pivot != null) { - return false; - } - } else if (!pivot.equals(other.pivot)) { - return false; - } - if (rowSkipping != other.rowSkipping) { - return false; - } - if (rowLimit != other.rowLimit) { - return false; - } - if (rowOffset != other.rowOffset) { - return false; - } - if (selection == null) { - if (other.selection != null) { - return false; - } - } else if (!selection.equals(other.selection)) { - return false; - } - if (sort == null) { - if (other.sort != null) { - return false; - } - } else if (!sort.equals(other.sort)) { - return false; - } - if (userFormatOptions == null) { - if (other.userFormatOptions != null) { - return false; - } - } else if (!userFormatOptions.equals(other.userFormatOptions)) { - return false; - } - return true; - } - - /** - * Creates a comma separated string of the query strings of the given columns. - * - * @param l The list of columns. - * - * @return A comma separated string of the query strings of the given columns. - */ - /* package */ static String columnListToQueryString(List l) { - StrBuilder builder = new StrBuilder(); - List stringList = Lists.newArrayList(); - for (AbstractColumn col : l) { - stringList.add(col.toQueryString()); - } - builder.appendWithSeparators(stringList, ", "); - return builder.toString(); - } - - /** - * Creates a query-language representation of the given string, i.e., delimits it with either - * double-quotes (") or single-quotes ('). Throws a runtime exception if the given string - * contains both double-quotes and single-quotes and so cannot be expressed in the query - * language. - * - * @param s The string to create a query-language representation for. - * - * @return The query-language representation of the given string. - */ - /* package */ static String stringToQueryStringLiteral(String s) { - if (s.contains("\"")) { - if (s.contains("'")) { - throw new RuntimeException("Cannot represent string that contains both double-quotes (\") " - + " and single quotes (')."); - } else { - return "'" + s + "'"; - } - } else { - return "\"" + s + "\""; - } - } - - /** - * Returns a string that when fed to the query parser will yield an identical Query. - * Used mainly for debugging purposes. - * - * @return The query string. - */ - public String toQueryString() { - List clauses = Lists.newArrayList(); - if (hasSelection()) { - clauses.add("SELECT " + selection.toQueryString()); - } - if (hasFilter()) { - clauses.add("WHERE " + filter.toQueryString()); - } - if (hasGroup()) { - clauses.add("GROUP BY " + group.toQueryString()); - } - if (hasPivot()) { - clauses.add("PIVOT " + pivot.toQueryString()); - } - if (hasSort()) { - clauses.add("ORDER BY " + sort.toQueryString()); - } - if (hasRowSkipping()) { - clauses.add("SKIPPING " + rowSkipping); - } - if (hasRowLimit()) { - clauses.add("LIMIT " + rowLimit); - } - if (hasRowOffset()) { - clauses.add("OFFSET " + rowOffset); - } - if (hasLabels()) { - clauses.add("LABEL " + labels.toQueryString()); - } - if (hasUserFormatOptions()) { - clauses.add("FORMAT " + userFormatOptions.toQueryString()); - } - if (hasOptions()) { - clauses.add("OPTIONS " + options.toQueryString()); - } - StrBuilder result = new StrBuilder(); - result.appendWithSeparators(clauses, " "); - return result.toString(); - } -} diff --git a/src/main/java/com/google/visualization/datasource/query/QueryFilter.java b/src/main/java/com/google/visualization/datasource/query/QueryFilter.java deleted file mode 100755 index b9c0822..0000000 --- a/src/main/java/com/google/visualization/datasource/query/QueryFilter.java +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query; - -import com.google.visualization.datasource.datatable.DataTable; -import com.google.visualization.datasource.datatable.TableRow; - -import java.util.List; -import java.util.Set; - -/** - * A query filter. - * Any class that implements this interface can act as a filter, i.e., be the - * part of a query that decides for a given TableRow if that row is part of the - * result set. - * - * @author Yonatan B.Y. - */ -public abstract class QueryFilter { - - /** - * Checks if this row should be part of the result set. - * - * @param table The table containing this row. - * @param row The row to check. - * - * @return true if this row should be part of the result set, false otherwise. - */ - public abstract boolean isMatch(DataTable table, TableRow row); - - /** - * Returns all the columnIds this filter uses. - * - * @return All the columnIds this filter uses. - */ - public abstract Set getAllColumnIds(); - - /** - * Returns a list of all scalarFunctionColumns this filter uses. - * - * @return A list of all scalarFunctionColumns this filter uses. - */ - public abstract List getScalarFunctionColumns(); - - /** - * Returns a list of all aggregation columns this filter uses. This is kept for future use, as - * currently filters are not allowed to have aggregation columns. This is still used currently - * for validation purposes. - * - * @return A list of all aggregation columns this filter uses. - */ - protected abstract List getAggregationColumns(); - - /** - * Returns a string that, when parsed by the query parser, should return an - * identical filter. The string returned does not contain the WHERE keyword. - * - * @return A string form of this filter. - */ - public abstract String toQueryString(); -} diff --git a/src/main/java/com/google/visualization/datasource/query/QueryFormat.java b/src/main/java/com/google/visualization/datasource/query/QueryFormat.java deleted file mode 100755 index b750f0a..0000000 --- a/src/main/java/com/google/visualization/datasource/query/QueryFormat.java +++ /dev/null @@ -1,183 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query; - -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.visualization.datasource.base.InvalidQueryException; - -import org.apache.commons.lang.text.StrBuilder; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * Describes the formatting options of a Query, as passed on the query - * in the "format" clause. - * - * Format can be specified for each column, but does not have to be. - * If not specified, each column type has a default format. - * - * Each format is a string pattern, as used in the ICU UFormat class. - * @see com.ibm.icu.text.UFormat - * - * @author Itai R. - */ -public class QueryFormat { - - /** - * Log. - */ - private static final Log log = LogFactory.getLog(QueryFormat.class.getName()); - - /** - * A map of all of the columns that require non-default patterns, and the - * pattern specified for them. - * Columns with default patterns are not in the map. - */ - private Map columnPatterns; - - /** - * Default empty constructor, with no patterns (patterns can be added later). - */ - public QueryFormat() { - columnPatterns = Maps.newHashMap(); - } - - /** - * Adds a column pattern. - * Validates that the column ID is not already specified. - * - * @param column The column to which the pattern is assigned. - * @param pattern The assigned pattern. - * - * @throws InvalidQueryException Thrown if the column is already specified. - */ - public void addPattern(AbstractColumn column, String pattern) throws InvalidQueryException { - if (columnPatterns.keySet().contains(column)) { - String messageToLogAndUser = "Column [" + column.toString() + "] is " - + "specified more than once in FORMAT."; - log.error(messageToLogAndUser); - throw new InvalidQueryException(messageToLogAndUser); - } - columnPatterns.put(column, pattern); - } - - /** - * Returns the pattern of the specified column, or null if no pattern was - * specified. - * - * @param column The column for which the pattern is required. - * - * @return The pattern, or null if no pattern was specified for this column. - */ - public String getPattern(AbstractColumn column) { - return columnPatterns.get(column); - } - - /** - * Returns an immutable set of the column IDs for which a pattern was - * specified. - * - * @return An immutable set of the column IDs for which a pattern was - * specified. - */ - public Set getColumns() { - return ImmutableSet.copyOf(columnPatterns.keySet()); - } - - /** - * Returns all the columns that are ScalarFunctionColumns including scalar - * functions columns that are inside other scalar function columns - * (e.g., sum(year(a), year(b))). - * - * @return all the columns that are ScalarFunctionColumns. - */ - public List getScalarFunctionColumns() { - List result = Lists.newArrayList(); - for (AbstractColumn col : columnPatterns.keySet()) { - for (ScalarFunctionColumn innerCol : col.getAllScalarFunctionColumns()) { - if (!result.contains(innerCol)) { - result.add(innerCol); - } - } - } - return result; - } - - /** - * Returns all the columns that are AggregationColumns. - * - * @return All the columns that are AggregationColumns. - */ - public List getAggregationColumns() { - List result = Lists.newArrayList(); - for (AbstractColumn col : columnPatterns.keySet()) { - result.addAll(col.getAllAggregationColumns()); - } - return result; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((columnPatterns == null) ? 0 : columnPatterns.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - QueryFormat other = (QueryFormat) obj; - if (columnPatterns == null) { - if (other.columnPatterns != null) { - return false; - } - } else if (!columnPatterns.equals(other.columnPatterns)) { - return false; - } - return true; - } - - /** - * Returns a string that when fed into the query parser, produces a QueryFormat equal to this one. - * The string returned does not contain the FORMAT keyword. - * - * @return The query string. - */ - public String toQueryString() { - StrBuilder builder = new StrBuilder(); - List stringList = Lists.newArrayList(); - for (AbstractColumn col : columnPatterns.keySet()) { - String pattern = columnPatterns.get(col); - stringList.add(col.toQueryString() + " " + Query.stringToQueryStringLiteral(pattern)); - } - builder.appendWithSeparators(stringList, ", "); - return builder.toString(); - } -} diff --git a/src/main/java/com/google/visualization/datasource/query/QueryGroup.java b/src/main/java/com/google/visualization/datasource/query/QueryGroup.java deleted file mode 100755 index 6ce07e6..0000000 --- a/src/main/java/com/google/visualization/datasource/query/QueryGroup.java +++ /dev/null @@ -1,155 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Lists; - -import java.util.List; - -/** - * Grouping definition for a query. - * Grouping is defined as a list of column IDs to group by. - * - * @author Yoav G. - * @author Yonatan B.Y. - * @author Liron L. - */ -public class QueryGroup { - - /** - * The list of group-by columns. - */ - private List columns; - - /** - * Constructs a query group with empty lists. - */ - public QueryGroup() { - columns = Lists.newArrayList(); - } - - /** - * Add a column to group by. - * - * @param column The column to add. - */ - public void addColumn(AbstractColumn column) { - columns.add(column); - } - - /** - * Returns the list of group-by IDs. This list is immutable. - * - * @return The list of group-by IDs. This list is immutable. - */ - public List getColumnIds() { - List columnIds = Lists.newArrayList(); - for (AbstractColumn col : columns) { - columnIds.add(col.getId()); - } - return ImmutableList.copyOf(columnIds); - } - - /** - * Returns a list of all simple columns' IDs in this group. - * - * @return A list of all simple columns' IDs in this group. - */ - public List getSimpleColumnIds() { - List columnIds = Lists.newArrayList(); - for (AbstractColumn col : columns) { - columnIds.addAll(col.getAllSimpleColumnIds()); - } - return columnIds; - } - - /** - * Returns the list of group-by columns. This list is immutable. - * - * @return The list of group-by columns. This list is immutable. - */ - public List getColumns() { - return ImmutableList.copyOf(columns); - } - - /** - * Returns the list of simple columns included in the group-by section. - * - * @return The list of simple columns included in the group-by section. - */ - public List getSimpleColumns() { - List simpleColumns = Lists.newArrayList(); - for (AbstractColumn col : columns) { - simpleColumns.addAll(col.getAllSimpleColumns()); - } - return simpleColumns; - } - - /** - * Returns the list of scalar function columns included in the group-by - * section. - * - * @return The list of scalar function columns included in the group-by - * section - */ - public List getScalarFunctionColumns() { - List scalarFunctionColumns = Lists.newArrayList(); - for (AbstractColumn col : columns) { - scalarFunctionColumns.addAll(col.getAllScalarFunctionColumns()); - } - return scalarFunctionColumns; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((columns == null) ? 0 : columns.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - QueryGroup other = (QueryGroup) obj; - if (columns == null) { - if (other.columns != null) { - return false; - } - } else if (!columns.equals(other.columns)) { - return false; - } - return true; - } - - /** - * Returns a string that when fed to the query parser would produce an equal QueryGroup. - * The string is returned without the GROUP BY keywords. - * - * @return The query string. - */ - public String toQueryString() { - return Query.columnListToQueryString(columns); - } -} diff --git a/src/main/java/com/google/visualization/datasource/query/QueryLabels.java b/src/main/java/com/google/visualization/datasource/query/QueryLabels.java deleted file mode 100755 index bc4f2bd..0000000 --- a/src/main/java/com/google/visualization/datasource/query/QueryLabels.java +++ /dev/null @@ -1,177 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query; - -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.visualization.datasource.base.InvalidQueryException; - -import org.apache.commons.lang.text.StrBuilder; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * Describes the labels of a Query, as passed in the query under - * the "label" clause. - * - * A label can optionally be specified for each column. - * If not specified, each column type has a default label. - * - * @author Itai R. - */ -public class QueryLabels { - /** - * Log. - */ - private static final Log log = LogFactory.getLog(QueryLabels.class.getName()); - - /** - * A map of all of the columns that require non-default labels, and the - * label specified for them. - * Columns with default labels are not in the map. - */ - private Map columnLabels; - - /** - * Default empty constructor, with no labels. Labels can be added later. - */ - public QueryLabels() { - columnLabels = Maps.newHashMap(); - } - - /** - * Adds a column label. - * Validates that the column ID is not already specified. - * - * @param column The column to which the label is assigned. - * @param label The assigned label. - * - * @throws InvalidQueryException Thrown if the column is already specified. - */ - public void addLabel(AbstractColumn column, String label) throws InvalidQueryException { - if (columnLabels.keySet().contains(column)) { - String messageToLogAndUser = "Column [" + column.toString() + "] is " - + "specified more than once in LABEL."; - log.error(messageToLogAndUser); - throw new InvalidQueryException(messageToLogAndUser); - } - columnLabels.put(column, label); - } - - /** - * Returns the label of the specified column, or null if no label was - * specified. - * - * @param column The column for which the label is required. - * - * @return The label, or null if no label was specified for this column. - */ - public String getLabel(AbstractColumn column) { - return columnLabels.get(column); - } - - /** - * Returns an immutable set of the columns for which a label was specified. - * - * @return An immutable set of the columns for which a label was specified. - */ - public Set getColumns() { - return ImmutableSet.copyOf(columnLabels.keySet()); - } - - /** - * Returns all the columns that are ScalarFunctionColumns including scalar - * functions columns that are inside other scalar function columns - * (e.g., sum(year(a), year(b))). - * - * @return all the columns that are ScalarFunctionColumns. - */ - public List getScalarFunctionColumns() { - List result = Lists.newArrayList(); - for (AbstractColumn col : columnLabels.keySet()) { - for (ScalarFunctionColumn innerCol : col.getAllScalarFunctionColumns()) { - if (!result.contains(innerCol)) { - result.add(innerCol); - } - } - } - return result; - } - - /** - * Returns all the columns that are AggregationColumns. - * - * @return All the columns that are AggregationColumns. - */ - public List getAggregationColumns() { - List result = Lists.newArrayList(); - for (AbstractColumn col : columnLabels.keySet()) { - result.addAll(col.getAllAggregationColumns()); - } - return result; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((columnLabels == null) ? 0 : columnLabels.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - QueryLabels other = (QueryLabels) obj; - if (columnLabels == null) { - if (other.columnLabels != null) { - return false; - } - } else if (!columnLabels.equals(other.columnLabels)) { - return false; - } - return true; - } - - /** - * Returns a string that when fed into the query parser, produces a QueryLabels equal to this one. - * The string returned does not contain the LABEL keyword. - * - * @return The query string. - */ - public String toQueryString() { - StrBuilder builder = new StrBuilder(); - List stringList = Lists.newArrayList(); - for (AbstractColumn col : columnLabels.keySet()) { - String label = columnLabels.get(col); - stringList.add(col.toQueryString() + " " + Query.stringToQueryStringLiteral(label)); - } - builder.appendWithSeparators(stringList, ", "); - return builder.toString(); - } -} diff --git a/src/main/java/com/google/visualization/datasource/query/QueryOptions.java b/src/main/java/com/google/visualization/datasource/query/QueryOptions.java deleted file mode 100755 index afd04b9..0000000 --- a/src/main/java/com/google/visualization/datasource/query/QueryOptions.java +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query; - -/** - * Options definition for a query. - * Holds options for the query that fall under the options clause. - * - * @author Yonatan B.Y. - */ -public class QueryOptions { - - /** - * Should be set to indicate not to return the values, but only the column - * labels and types (table description). - */ - private boolean noValues; - - /** - * Should be set to indicate not to format the values, but to return only the - * raw data. By default returns both raw and formatted values. - */ - private boolean noFormat; - - /** - * Constructs query options with all boolean options set to false. - */ - public QueryOptions() { - noValues = false; - noFormat = false; - } - - /** - * Returns the value of the noValues option. - * - * @return The value of the noValues option. - */ - public boolean isNoValues() { - return noValues; - } - - /** - * Sets the value of the noValues option. - * - * @param noValues The new value of the noValues option. - */ - public void setNoValues(boolean noValues) { - this.noValues = noValues; - } - - /** - * Returns the value of the noFormat option. - * - * @return The value of the noFormat option. - */ - public boolean isNoFormat() { - return noFormat; - } - - /** - * Sets the value of the noFormat option. - * - * @param noFormat The new value of the noFormat option. - */ - public void setNoFormat(boolean noFormat) { - this.noFormat = noFormat; - } - - /** - * Returns true if all options are set to their default values. - * - * @return True if all options are set to their default values. - */ - public boolean isDefault() { - return !noFormat && !noValues; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + (noFormat ? 1231 : 1237); - result = prime * result + (noValues ? 1231 : 1237); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - QueryOptions other = (QueryOptions) obj; - if (noFormat != other.noFormat) { - return false; - } - if (noValues != other.noValues) { - return false; - } - return true; - } - - /** - * Returns a string that when fed to the query parser should return a QueryOptions equal to this - * one. Used mainly for debugging purposes. The string returned does not contain the - * OPTIONS keyword. - * - * @return The query string. - */ - public String toQueryString() { - return (noValues ? "NO_VALUES" : "") + (noFormat ? "NO_FORMAT" : ""); - } -} diff --git a/src/main/java/com/google/visualization/datasource/query/QueryPivot.java b/src/main/java/com/google/visualization/datasource/query/QueryPivot.java deleted file mode 100755 index 55aa83d..0000000 --- a/src/main/java/com/google/visualization/datasource/query/QueryPivot.java +++ /dev/null @@ -1,152 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Lists; - -import java.util.List; - -/** - * Pivoting definition for a query. - * Pivoting is defined as a list of column IDs to pivot. - * - * @author Yoav G. - * @author Yonatan B.Y. - */ -public class QueryPivot { - - /** - * The list of pivot columns. - */ - private List columns; - - /** - * Constructs a query pivot with empty lists. - */ - public QueryPivot() { - columns = Lists.newArrayList(); - } - - /** - * Adds a column to pivot. - * - * @param column The column to add. - */ - public void addColumn(AbstractColumn column) { - columns.add(column); - } - - /** - * Returns the list of pivot column IDs. This list is immutable. - * - * @return The list of pivot column IDs. This list is immutable. - */ - public List getColumnIds() { - List columnIds = Lists.newArrayList(); - for (AbstractColumn col : columns) { - columnIds.add(col.getId()); - } - return ImmutableList.copyOf(columnIds); - } - - /** - * Returns a list of all simple columns' IDs in this pivot. - * - * @return A list of all simple columns' IDs in this pivot. - */ - public List getSimpleColumnIds() { - List columnIds = Lists.newArrayList(); - for (AbstractColumn col : columns) { - columnIds.addAll(col.getAllSimpleColumnIds()); - } - return columnIds; - } - - /** - * Returns the list of pivot columns. This list is immutable. - * - * @return The list of pivot columns. This list is immutable. - */ - public List getColumns() { - return ImmutableList.copyOf(columns); - } - - /** - * Returns the list of pivot simple columns. - * - * @return The list of pivot simple columns. - */ - public List getSimpleColumns() { - List simpleColumns = Lists.newArrayList(); - for (AbstractColumn col : columns) { - simpleColumns.addAll(col.getAllSimpleColumns()); - } - return simpleColumns; - } - - /** - * Returns the list of pivot scalar function columns. - * - * @return The list of pivot scalar function columns. - */ - public List getScalarFunctionColumns() { - List scalarFunctionColumns = Lists.newArrayList(); - for (AbstractColumn col : columns) { - scalarFunctionColumns.addAll(col.getAllScalarFunctionColumns()); - } - return scalarFunctionColumns; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((columns == null) ? 0 : columns.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - QueryPivot other = (QueryPivot) obj; - if (columns == null) { - if (other.columns != null) { - return false; - } - } else if (!columns.equals(other.columns)) { - return false; - } - return true; - } - - /** - * Returns a string that when fed to the query parser would produce an equal QueryPivot. - * The string is returned without the PIVOT keywors. - * - * @return The query string. - */ - public String toQueryString() { - return Query.columnListToQueryString(columns); - } -} diff --git a/src/main/java/com/google/visualization/datasource/query/QuerySelection.java b/src/main/java/com/google/visualization/datasource/query/QuerySelection.java deleted file mode 100755 index 34e6e6f..0000000 --- a/src/main/java/com/google/visualization/datasource/query/QuerySelection.java +++ /dev/null @@ -1,162 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Lists; - -import java.util.List; - -/** - * Selection definition for a query. - * Selection is defined as a list of column IDs. It can also include aggregations for - * grouping/pivoting and scalar functions. - * - * - * @author Itai R. - */ -public class QuerySelection { - - /** - * The list of columns to select. - */ - private List columns; - - /** - * Construct an empty selection list. - */ - public QuerySelection() { - columns = Lists.newArrayList(); - } - - /** - * Copy constructor. - * - * @param source The source query selection from which to construct. - */ - public QuerySelection(QuerySelection source) { - columns = Lists.newArrayList(source.columns); - } - - /** - * Returns true if the selection list is empty. - * - * @return True if the selection list is empty. - */ - public boolean isEmpty() { - return columns.isEmpty(); - } - - /** - * Adds a column to the column list. - * - * @param column The column to select. - */ - public void addColumn(AbstractColumn column) { - columns.add(column); - } - - /** - * Returns the list of columns. This list is immutable. - * @return The list of columns. This list is immutable. - */ - public List getColumns() { - return ImmutableList.copyOf(columns); - } - - /** - * Returns all the columns that are AggregationColumns including aggregation - * columns that are inside scalar function columns (e.g., year(min(a1))). - * - * @return All the columns that are AggregationColumns. - */ - public List getAggregationColumns() { - List result = Lists.newArrayList(); - for (AbstractColumn col : columns) { - result.addAll(col.getAllAggregationColumns()); - } - return result; - } - - /** - * Returns all the columns that are SimpleColumns including those inside - * scalar function columns (e.g, year(a1)). Does not return simple columns - * inside aggregation columns (e.g., sum(a1)). - * - * @return All the columns that are SimpleColumns. - */ - public List getSimpleColumns() { - List result = Lists.newArrayList(); - for (AbstractColumn col : columns) { - result.addAll(col.getAllSimpleColumns()); - } - return result; - } - - /** - * Returns all the columns that are ScalarFunctionColumns including scalar - * functions columns that are inside other scalar function columns - * (e.g., sum(year(a), year(b))). - * - * @return all the columns that are ScalarFunctionColumns. - */ - public List getScalarFunctionColumns() { - List result = Lists.newArrayList(); - for (AbstractColumn col : columns) { - result.addAll(col.getAllScalarFunctionColumns()); - } - return result; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((columns == null) ? 0 : columns.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - QuerySelection other = (QuerySelection) obj; - if (columns == null) { - if (other.columns != null) { - return false; - } - } else if (!columns.equals(other.columns)) { - return false; - } - return true; - } - - /** - * Returns a string that when fed to the query parser would produce an equal QuerySelection. - * The string is returned without the SELECT keyword. - * - * @return The query string. - */ - public String toQueryString() { - return Query.columnListToQueryString(columns); - } -} diff --git a/src/main/java/com/google/visualization/datasource/query/QuerySort.java b/src/main/java/com/google/visualization/datasource/query/QuerySort.java deleted file mode 100755 index 1752d49..0000000 --- a/src/main/java/com/google/visualization/datasource/query/QuerySort.java +++ /dev/null @@ -1,182 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Lists; - -import org.apache.commons.lang.text.StrBuilder; - -import java.util.List; - -/** - * Sorting definition for a query. - * Sort is defined as a list of column sorts where the first is the primary sort order, - * the second is the secondary sort order, etc. - * - * @author Yoah B.D. - */ -public class QuerySort { - - /** - * The list of columns by which to sort. - */ - private List sortColumns; - - /** - * Constructs an empty sort list. - */ - public QuerySort() { - sortColumns = Lists.newArrayList(); - } - - /** - * Returns true if the sort list is empty. - * - * @return True if the sort list is empty. - */ - public boolean isEmpty() { - return sortColumns.isEmpty(); - } - - /** - * Adds a column sort condition. - * Validates that the column ID is not already specified in the sort. - * - * @param columnSort The column sort condition. - */ - public void addSort(ColumnSort columnSort) { - sortColumns.add(columnSort); - } - - /** - * Adds a column sort condition. - * Validates that the column ID is not already specified in the sort. - * - * @param column The column to sort by. - * @param order The requested ordering. - */ - public void addSort(AbstractColumn column, SortOrder order) { - addSort(new ColumnSort(column, order)); - } - - /** - * Returns the list of sort columns. This list is immutable. - * - * @return The list of sort columns. This list is immutable. - */ - public List getSortColumns() { - return ImmutableList.copyOf(sortColumns); - } - - /** - * Returns a list of columns held by this query sort. - * - * @return A list of columns held by this query sort. - */ - public List getColumns() { - List result = - Lists.newArrayListWithExpectedSize(sortColumns.size()); - for (ColumnSort columnSort : sortColumns) { - result.add(columnSort.getColumn()); - } - return result; - } - - /** - * Returns all the columns that are AggregationColumns including aggregation - * columns that are inside scalar function columns (e.g., year(min(a1))). - * - * @return All the columns that are AggregationColumns. - */ - public List getAggregationColumns() { - List result = Lists.newArrayList(); - for (ColumnSort columnSort : sortColumns) { - AbstractColumn col = columnSort.getColumn(); - for (AggregationColumn innerCol : col.getAllAggregationColumns()) { - if (!result.contains(innerCol)) { - result.add(innerCol); - } - } - } - return result; - } - - /** - * Returns all the columns that are ScalarFunctionColumns including scalar - * functions columns that are inside other scalar function columns - * (e.g., sum(year(a), year(b))). - * - * @return all the columns that are ScalarFunctionColumns. - */ - public List getScalarFunctionColumns() { - List result = Lists.newArrayList(); - for (ColumnSort columnSort : sortColumns) { - AbstractColumn col = columnSort.getColumn(); - for (ScalarFunctionColumn innerCol : col.getAllScalarFunctionColumns()) { - if (!result.contains(innerCol)) { - result.add(innerCol); - } - } - } - return result; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((sortColumns == null) ? 0 : sortColumns.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - QuerySort other = (QuerySort) obj; - if (sortColumns == null) { - if (other.sortColumns != null) { - return false; - } - } else if (!sortColumns.equals(other.sortColumns)) { - return false; - } - return true; - } - - /** - * Returns a string that when fed to the query parser would produce an equal QuerySort. - * The string returned does not contain the ORDER BY keywords. - * - * @return The query string. - */ - public String toQueryString() { - StrBuilder builder = new StrBuilder(); - List stringList = Lists.newArrayList(); - for (ColumnSort colSort : sortColumns) { - stringList.add(colSort.toQueryString()); - } - builder.appendWithSeparators(stringList, ", "); - return builder.toString(); - } -} diff --git a/src/main/java/com/google/visualization/datasource/query/ScalarFunctionColumn.java b/src/main/java/com/google/visualization/datasource/query/ScalarFunctionColumn.java deleted file mode 100755 index 0af9a00..0000000 --- a/src/main/java/com/google/visualization/datasource/query/ScalarFunctionColumn.java +++ /dev/null @@ -1,291 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query; - -import com.google.common.collect.Lists; -import com.google.visualization.datasource.base.InvalidQueryException; -import com.google.visualization.datasource.datatable.DataTable; -import com.google.visualization.datasource.datatable.TableCell; -import com.google.visualization.datasource.datatable.TableRow; -import com.google.visualization.datasource.datatable.value.Value; -import com.google.visualization.datasource.datatable.value.ValueType; -import com.google.visualization.datasource.query.scalarfunction.ScalarFunction; - -import org.apache.commons.lang.text.StrBuilder; - -import java.util.List; - -/** - * A scalar function column (e.g. year(Date1)). The values in a scalar function column are the - * result of executing the function on the columns that are given as parameters, so for example - * year(Date1) column values will have the year of the corresponding value in Date1 column. - * - * @author Liron L. - */ -public class ScalarFunctionColumn extends AbstractColumn { - - /** - * A separator between function type and the columns on which it operates. - * Used for creating the column ID. - */ - public static final String COLUMN_FUNCTION_TYPE_SEPARATOR = "_"; - - /** - * When creating the ID of the column, this is used as a separator between the columns - * on which the function is performed. - */ - public static final String COLUMN_COLUMN_SEPARATOR = ","; - - /** - * A list of the columns on which the function is performed. - */ - private List columns; - - /** - * The function performed. - */ - private ScalarFunction scalarFunction; - - /** - * Creates a new instance of this class with the given columns list and - * function type. - * - * @param columns The list of columns on which the function is performed. - * @param scalarFunction The function type. - */ - public ScalarFunctionColumn(List columns, - ScalarFunction scalarFunction) { - this.columns = columns; - this.scalarFunction = scalarFunction; - } - - /** - * Returns the ID of the scalar function column. THe ID is constructed from the - * function's name and the IDs of the inner columns on which the function is - * performed. - * - * @return The ID of the scalar function column. - */ - @Override - public String getId() { - List colIds = Lists.newArrayList(); - for (AbstractColumn col : columns) { - colIds.add(col.getId()); - } - return new StrBuilder(scalarFunction.getFunctionName()).append(COLUMN_FUNCTION_TYPE_SEPARATOR) - .appendWithSeparators(colIds, COLUMN_COLUMN_SEPARATOR).toString(); - } - - /** - * Returns a list of the inner simple column IDs of the scalar function - * column (i.e., the columns on which the function is performed). - * - * @return A list of the inner simple column IDs. - */ - @Override - public List getAllSimpleColumnIds() { - List columnIds = Lists.newArrayList(); - for (AbstractColumn column : columns) { - columnIds.addAll(column.getAllSimpleColumnIds()); - } - return columnIds; - } - - /** - * Returns the function of the scalar function column. - * - * @return The function of the scalar function column. - */ - public ScalarFunction getFunction() { - return scalarFunction; - } - - /** - * Returns a list of the columns on which the function is performed. - * - * @return A list of the columns on which the function is performed. - */ - public List getColumns() { - return columns; - } - - /** - * Returns the cell of the column in the given row. If the given column - * lookup contains this column, returns the cell in the given row using the - * lookup. Otherwise, recursively gets the inner column values and uses them to - * evaluate the value and create a cell based on that value. The base of the - * recursion is a simple column, aggregation column or another scalar function - * column that exists in the column lookup (i.e., its value was already calculated). - * - * @param row The given row. - * @param lookup The column lookup. - * - * @return The cell of the column in the given row. - */ - @Override - public TableCell getCell(ColumnLookup lookup, TableRow row) { - if (lookup.containsColumn(this)) { - int columnIndex = lookup.getColumnIndex(this); - return row.getCells().get(columnIndex); - } - // If the given column lookup does not contain this column, get the inner - // column values of this column and use them as parameters to evaluate the - // scalar function value in the given row. - List functionParameters = Lists.newArrayListWithCapacity(columns.size()); - for (AbstractColumn column : columns) { - functionParameters.add(column.getValue(lookup, row)); - } - return new TableCell(scalarFunction.evaluate(functionParameters)); - } - - /** - * Returns a list of all simple columns. This includes simple columns that are - * inside scalar function columns (e.g, year(a1)), but does not include simple - * columns that are inside aggregation columns (e.g., sum(a1)). - * - * @return A list of all simple columns. - */ - @Override - public List getAllSimpleColumns() { - List simpleColumns = - Lists.newArrayListWithCapacity(columns.size()); - for (AbstractColumn column : columns) { - simpleColumns.addAll(column.getAllSimpleColumns()); - } - return simpleColumns; - } - - /** - * Returns a list of all aggregation columns including the columns that are - * inside scalar function columns (e.g., the column year(date(max(d1))) will - * return max(d1)). - * - * @return A list of all aggregation columns. - */ - @Override - public List getAllAggregationColumns() { - List aggregationColumns = - Lists.newArrayListWithCapacity(columns.size()); - for (AbstractColumn column : columns) { - aggregationColumns.addAll(column.getAllAggregationColumns()); - } - return aggregationColumns; - } - - /** - * Returns a list of all scalar function columns. Returns itself and - * other inner scalar function columns (if there are any). - * e.g., the column max(year(a1), year(a2)) will return the 3 columns: - * max(year(a1), year(a2)), year(a1), year(a2). - * - * @return A list of all scalar function columns. - */ - @Override - public List getAllScalarFunctionColumns() { - List scalarFunctionColumns = Lists.newArrayList(this); - for (AbstractColumn column : columns) { - scalarFunctionColumns.addAll(column.getAllScalarFunctionColumns()); - } - return scalarFunctionColumns; - } - - /** - * Checks that the column is valid. Checks the scalar function matches - * its arguments (inner columns) and all its inner columns are valid too. - * Throws a ColumnException if the scalar function has invalid arguments. - * - * @param dataTable The table description. - * - * @throws InvalidQueryException Thrown when the column is invalid. - */ - @Override - public void validateColumn(DataTable dataTable) throws InvalidQueryException { - List types = Lists.newArrayListWithCapacity(columns.size()); - for (AbstractColumn column : columns) { - column.validateColumn(dataTable); - types.add(column.getValueType(dataTable)); - } - // Throws an InvalidColumnException when the function arguments types are - // invalid. - scalarFunction.validateParameters(types); - } - - /** - * Returns the value type of the column after evaluating the scalar function. - * e.g., the value type of year(date1) is NUMBER. - * - * @param dataTable The table description. - * - * @return the value type of the column. - */ - @Override - public ValueType getValueType(DataTable dataTable) { - if (dataTable.containsColumn(this.getId())) { - return dataTable.getColumnDescription(this.getId()).getType(); - } - List types = Lists.newArrayListWithCapacity(columns.size()); - for (AbstractColumn column : columns) { - types.add(column.getValueType(dataTable)); - } - return scalarFunction.getReturnType(types); - } - - @Override - public boolean equals(Object o) { - if (o instanceof ScalarFunctionColumn) { - ScalarFunctionColumn other = (ScalarFunctionColumn) o; - return columns.equals(other.columns) - && scalarFunction.equals(other.scalarFunction); - } - return false; - } - - @Override - public int hashCode() { - int hash = 1279; // Some arbitrary prime number. - for (AbstractColumn column : columns) { - hash = (hash * 17) + column.hashCode(); - } - hash = (hash * 17) + scalarFunction.hashCode(); - return hash; - } - - /** - * {@inheritDoc} - */ - @Override - public String toQueryString() { - List columnQueryStrings = Lists.newArrayList(); - for (AbstractColumn column : columns) { - columnQueryStrings.add(column.toQueryString()); - } - return scalarFunction.toQueryString(columnQueryStrings); - } - - /** - * This is for debug and error messages, not for ID generation. - * - * @return A string describing this AggregationColumn. - */ - @Override - public String toString() { - List colNames = Lists.newArrayList(); - for (AbstractColumn col : columns) { - colNames.add(col.toString()); - } - return new StrBuilder(scalarFunction.getFunctionName()).append("(") - .appendWithSeparators(colNames, COLUMN_COLUMN_SEPARATOR).append(")").toString(); - } -} diff --git a/src/main/java/com/google/visualization/datasource/query/SimpleColumn.java b/src/main/java/com/google/visualization/datasource/query/SimpleColumn.java deleted file mode 100755 index 8c72950..0000000 --- a/src/main/java/com/google/visualization/datasource/query/SimpleColumn.java +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query; - -import com.google.common.collect.Lists; -import com.google.visualization.datasource.datatable.DataTable; -import com.google.visualization.datasource.datatable.value.ValueType; - -import java.util.List; - -/** - * A column referred to by an explicit string ID. - * - * @author Yonatan B.Y. - */ -public class SimpleColumn extends AbstractColumn { - - /** - * The explicit string ID of the column. - */ - private String columnId; - - /** - * Creates a new instance of this class, with the given column ID. - * - * @param columnId The column ID. - */ - public SimpleColumn(String columnId) { - this.columnId = columnId; - } - - /** - * Returns the column ID. - * - * @return The column ID. - */ - public String getColumnId() { - return columnId; - } - - @Override - public String getId() { - return columnId; - } - - @Override - public List getAllSimpleColumnIds() { - return Lists.newArrayList(columnId); - } - - @Override - public boolean equals(Object o) { - if (o instanceof SimpleColumn) { - SimpleColumn other = (SimpleColumn) o; - return columnId.equals(other.columnId); - } - return false; - } - - @Override - public int hashCode() { - int hash = 1279; // Some arbitrary prime number. - hash = (hash * 17) + columnId.hashCode(); - return hash; - } - - @Override - public String toString() { - return columnId; - } - - /** - * Returns a list of all simple columns. In this case, returns only itself. - * - * @return A list of all simple columns. - */ - @Override - public List getAllSimpleColumns() { - return Lists.newArrayList(this); - } - - /** - * Returns a list of all aggregation columns. In this case, returns an empty - * list. - * - * @return A list of all aggregation columns. - */ - @Override - public List getAllAggregationColumns() { - return Lists.newArrayList(); - } - - /** - * Returns a list of all scalar function columns. In this case, returns an - * empty list. - * - * @return A list of all scalar function columns. - */ - @Override - public List getAllScalarFunctionColumns() { - return Lists.newArrayList(); - } - - /** - * Checks if the column is valid. In this case always does nothing. - * - * @param dataTable The data table. - */ - @Override - public void validateColumn(DataTable dataTable) { - } - - /** - * Returns the value type of the column. In this case returns the value type - * of the column itself. - * - * @param dataTable The data table. - * - * @return the value type of the column. - */ - @Override - public ValueType getValueType(DataTable dataTable) { - return dataTable.getColumnDescription(columnId).getType(); - } - - @Override - public String toQueryString() { - if (columnId.contains("`")) { - throw new RuntimeException("Column ID cannot contain backtick (`)"); - } - return "`" + columnId + "`"; - } -} diff --git a/src/main/java/com/google/visualization/datasource/query/SortOrder.java b/src/main/java/com/google/visualization/datasource/query/SortOrder.java deleted file mode 100755 index 7bc867d..0000000 --- a/src/main/java/com/google/visualization/datasource/query/SortOrder.java +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query; - -/** - * Sort order. - * - * @author Yoah B.D. - */ -public enum SortOrder { - ASCENDING, - DESCENDING -} diff --git a/src/main/java/com/google/visualization/datasource/query/engine/AggregationNode.java b/src/main/java/com/google/visualization/datasource/query/engine/AggregationNode.java deleted file mode 100755 index c1c6f87..0000000 --- a/src/main/java/com/google/visualization/datasource/query/engine/AggregationNode.java +++ /dev/null @@ -1,179 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query.engine; - -import com.google.common.collect.Maps; -import com.google.visualization.datasource.datatable.DataTable; -import com.google.visualization.datasource.datatable.value.Value; -import com.google.visualization.datasource.query.AggregationType; - -import java.util.Map; -import java.util.NoSuchElementException; -import java.util.Set; - -/** - * An aggregation node is a node in an aggregation tree. This node holds a value, equal to the - * value in the corresponding group-by column. It also holds: value aggregators (one for each - * aggregation column), a reference to its parent in the tree, and a set of references to its - * children. Each child is associated with a unique value, which corresponds to the value held - * in the child node. See {@link AggregationTree} for more details. - * - * @author Yoav G. - */ -public class AggregationNode { - - /** - * The parent of this node in the aggregation tree. - */ - private AggregationNode parent; - - /** - * The value of this node. This value is unique among the siblings of this - * node (in the aggregation tree), and is used for navigation. Note that the value is the same - * as the value used as a key to point to this AggregationNode in the parent's {@link #children} - * map. - */ - private Value value; - - /** - * Maps a column id to its aggregator. The column id should belong to the list of aggregation - * columns. - */ - private Map columnAggregators = Maps.newHashMap(); - - /** - * Maps a value to a child of this node (which is also an aggregation node). ‎The value is the - * same as the {@link #value} that will be stored in the child, i.e., - * children.get(X).getValue() should equal X. - */ - private Map children = Maps.newHashMap(); - - /** - * Construct a new aggregation node. - * - * @param columnsToAggregate A set of ids of the columns to aggregate (aggregation columns). - * @param table The table. - */ - public AggregationNode(Set columnsToAggregate, DataTable table) { - // Add a column value aggregator for each aggregation column. - for (String columnId : columnsToAggregate) { - columnAggregators.put(columnId, new ValueAggregator( - table.getColumnDescription(columnId).getType())); - } - } - - /** - * Aggregates values using the value aggregators of this node. - * - * @param valuesByColumn Maps a column id to the value that needs be aggregated (for that column). - */ - public void aggregate(Map valuesByColumn) { - for (String columnId : valuesByColumn.keySet()) { - columnAggregators.get(columnId).aggregate(valuesByColumn.get(columnId)); - } - } - - /** - * Returns the aggregation value of a specific column and type. - * - * @param columnId The requested column id. - * @param type The requested aggregation type. - * - * @return The aggregation values of a specific column. - */ - public Value getAggregationValue(String columnId, AggregationType type) { - ValueAggregator valuesAggregator = columnAggregators.get(columnId); - if (valuesAggregator == null) { - throw new IllegalArgumentException("Column " + columnId + - " is not aggregated"); - } - return valuesAggregator.getValue(type); - } - - /** - * Returns the child of this node defined by a specific value. - * - * @param v The value. - * - * @return The child of this node defined by a specific value. - */ - public AggregationNode getChild(Value v) { - AggregationNode result = children.get(v); - if (result == null) { - throw new NoSuchElementException("Value " + v + " is not a child."); - } - return result; - } - - /** - * Returns true if a node contains a child (identified by value) and false - * otherwise. - * - * @param v The value of the child. - * - * @return True if this node contains a child (identified by value) and false - * otherwise. - */ - public boolean containsChild(Value v) { - return children.containsKey(v); - } - - /** - * Adds a new child. - * - * @param key The value defining the new child. - * @param columnsToAggregate The ids of the columns to aggregate. - * @param table The table. - */ - public void addChild(Value key, Set columnsToAggregate, DataTable table) { - - if (children.containsKey(key)) { - throw new IllegalArgumentException("A child with key: " + key + - " already exists."); - } - AggregationNode node = new AggregationNode(columnsToAggregate, table); - node.parent = this; - node.value = key; - children.put(key, node); - } - - /** - * Returns a copy of the map of children of this node. - * - * @return A copy of the map of children of this node. - */ - public Map getChildren() { - return Maps.newHashMap(children); - } - - /** - * Returns the value of this node. This is also the key of this node in the - * children set of this parent. - * - * @return The value of this node. - */ - protected Value getValue() { - return value; - } - - /** - * Returns the parent of this node in the aggregation tree. - * - * @return The parent of this node. - */ - protected AggregationNode getParent() { - return parent; - } -} diff --git a/src/main/java/com/google/visualization/datasource/query/engine/AggregationPath.java b/src/main/java/com/google/visualization/datasource/query/engine/AggregationPath.java deleted file mode 100755 index c42e632..0000000 --- a/src/main/java/com/google/visualization/datasource/query/engine/AggregationPath.java +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query.engine; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Lists; -import com.google.visualization.datasource.datatable.value.Value; - -import java.util.Collections; -import java.util.List; - -/** - * An ordered list of values representing a path in an aggregation tree, from the root to a node. - * Only the values are stored, not the nodes themselves. - * - * @author Yoav G. - */ - -public class AggregationPath { - - /** - * The list of values forming the path. Each value, in turn, is used to - * navigate down from the current node to one of its children. - */ - private List values; - - /** - * Construct an empty path. - */ - public AggregationPath() { - values = Lists.newArrayList(); - } - - /** - * Adds a value to this path. - * - * @param value The value to add. - */ - public void add(Value value) { - values.add(value); - } - - /** - * Returns the list of values. This list is immutable. - * - * @return The list of values. This list is immutable. - */ - - public List getValues() { - return ImmutableList.copyOf(values); - } - - /** - * Reverses this path. - */ - public void reverse() { - Collections.reverse(values); - } -} diff --git a/src/main/java/com/google/visualization/datasource/query/engine/AggregationTree.java b/src/main/java/com/google/visualization/datasource/query/engine/AggregationTree.java deleted file mode 100755 index b9961d4..0000000 --- a/src/main/java/com/google/visualization/datasource/query/engine/AggregationTree.java +++ /dev/null @@ -1,155 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query.engine; - -import com.google.common.collect.Sets; -import com.google.visualization.datasource.datatable.DataTable; -import com.google.visualization.datasource.datatable.value.Value; - -import java.util.Map; -import java.util.Set; - -/** - * An aggregation tree is the logical data structure that represents table grouping information. - * Each level of the tree (besides the root-level) is associated with an aggregation column. - * Each node of the tree is associated with a value (of some cell in the column defining its level). - * Each node contains aggregation information, i.e., information about the minimum, maximum, - * count, average and sum on the aggregated columns. A leaf node holds this aggregation information - * for the corresponding "path" of values. For example, if the group-by columns are {Name, Revenue}, - * then the tree consists of 3 levels: the root level, holding only the root, then a level with - * nodes representing different values of Name, and then a level with nodes holding different - * values of Revenue. Then the leaf node which is at the path {"Joe", 100} from the root will hold - * the aggregation information for all rows in the table for which the value of Name is "Joe" and - * the value of Revenue is 100. The non-leaf node which is at the path {"Joe"} will contain the - * aggregation information for all rows in which the name is "Joe", without any consideration - * of the value of the Revenue column. The root node contains all aggregation information - * for the entire table. - * - * @author Yoav G. - */ -public class AggregationTree { - - /** - * The root of the tree is associated with the empty path and aggregates - * all data rows. - */ - private AggregationNode root; - - /** - * A set of ids of the columns to aggregate. This set is shared by all the - * nodes in this tree. - */ - private Set columnsToAggregate; - - /** - * The table. Used only for columns information. - */ - private DataTable table; - - /** - * Construct an aggregation tree. - * - * @param columnsToAggregate A set of ids of the columns to aggregate. - * @param table The table. - */ - public AggregationTree(Set columnsToAggregate, DataTable table) { - this.columnsToAggregate = columnsToAggregate; - this.table = table; - root = new AggregationNode(columnsToAggregate, table); - } - - /** - * Aggregates values to all the nodes on a path. The nodes of the path that - * are not in the tree are created and inserted into the tree. - * - * @param valuesToAggregate Maps column ids to values (to aggregate). - * @param path The aggregation path. - */ - public void aggregate(AggregationPath path, Map valuesToAggregate) { - AggregationNode curNode = root; - root.aggregate(valuesToAggregate); - - for (Value curValue : path.getValues()) { - // Add a new child if needed. - if (!curNode.containsChild(curValue)) { - curNode.addChild(curValue, columnsToAggregate, table); - } - curNode = curNode.getChild(curValue); - curNode.aggregate(valuesToAggregate); - } - } - - /** - * Returns the aggregation node at the end of a path. - * - * @param path The aggregation path. - * - * @return The aggregation node at the end of a path. - * - * @throws java.util.NoSuchElementException In case no node lies at the end of the path. - */ - public AggregationNode getNode(AggregationPath path) { - AggregationNode curNode = root; - for (Value curValue : path.getValues()) { - curNode = curNode.getChild(curValue); - } - return curNode; - } - - /** - * Returns a set containing a path for each leaf in the tree. - * - * @return A set containing a path for each leaf in the tree. - */ - public Set getPathsToLeaves() { - Set result = Sets.newHashSet(); - getPathsToLeavesInternal(root, result); - return result; - } - - /** - * Fills a set with the paths to all leaves in the tree. - */ - private void getPathsToLeavesInternal(AggregationNode node, Set result) { - // Perform DFS. - Map children = node.getChildren(); - if (children.isEmpty()) { - // Reached a leaf. - result.add(getPathToNode(node)); - } else { - for (AggregationNode curNode : children.values()) { - getPathsToLeavesInternal(curNode, result); - } - } - } - - /** - * Returns the path in the aggregation tree from the root to an aggregation node. - * - * @param node The aggregation node. - * - * @return The path in the aggregation tree an aggregation node. - */ - private static final AggregationPath getPathToNode(AggregationNode node) { - AggregationPath result = new AggregationPath(); - AggregationNode curNode = node; - while (curNode.getValue() != null) { // Did not reach the root. - result.add(curNode.getValue()); - curNode = curNode.getParent(); - } - result.reverse(); - return result; - } -} diff --git a/src/main/java/com/google/visualization/datasource/query/engine/ColumnIndices.java b/src/main/java/com/google/visualization/datasource/query/engine/ColumnIndices.java deleted file mode 100755 index 239ee09..0000000 --- a/src/main/java/com/google/visualization/datasource/query/engine/ColumnIndices.java +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query.engine; - -import com.google.common.collect.ArrayListMultimap; -import com.google.common.collect.ImmutableList; -import com.google.visualization.datasource.query.AbstractColumn; - -import java.util.List; - -/** - * Holds a mapping between {@link AbstractColumn}s and lists of indices, i.e., holds a list of - * indices for each column. The indices for a column are the indices in the new datatable, generated - * by a grouping/pivoting operation. There may be many indices for one column because a pivoting - * operation creates a few columns for a single original column. - * - * @author Yonatan B.Y. - */ -/* package */ class ColumnIndices { - - /** - * The indices of the columns. - */ - private ArrayListMultimap columnToIndices; - /** - * Creates an empty instance of this class. - */ - public ColumnIndices() { - columnToIndices = ArrayListMultimap.create(); - } - - /** - * Sets the index of the given column to the given number. - * - * @param col The column to set the index of. - * @param index The index to set for the column. - */ - public void put(AbstractColumn col, int index) { - columnToIndices.put(col, index); - } - - /** - * Returns the index of the given column. If there is more than one index for - * the column, a runtime exception is thrown. - * - * @param col The column to look for. - * - * @return The index of the column. - */ - public int getColumnIndex(AbstractColumn col) { - List indices = columnToIndices.get(col); - if (indices.size() != 1) { - throw new RuntimeException("Invalid use of ColumnIndices."); - } - return indices.get(0); - } - - /** - * Returns the indices of the given column. - * - * @param col The column to look for. - * - * @return The indeices of the column. - */ - public List getColumnIndices(AbstractColumn col) { - return ImmutableList.copyOf(columnToIndices.get(col)); - } - - /** - * Clears the entire map. - */ - public void clear() { - columnToIndices.clear(); - } -} diff --git a/src/main/java/com/google/visualization/datasource/query/engine/ColumnTitle.java b/src/main/java/com/google/visualization/datasource/query/engine/ColumnTitle.java deleted file mode 100755 index 4c8d13d..0000000 --- a/src/main/java/com/google/visualization/datasource/query/engine/ColumnTitle.java +++ /dev/null @@ -1,235 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query.engine; - -import com.google.visualization.datasource.datatable.ColumnDescription; -import com.google.visualization.datasource.datatable.DataTable; -import com.google.visualization.datasource.datatable.value.Value; -import com.google.visualization.datasource.datatable.value.ValueType; -import com.google.visualization.datasource.query.AggregationColumn; -import com.google.visualization.datasource.query.AggregationType; - -import org.apache.commons.lang.text.StrBuilder; - -import java.util.List; - -/** - * A "title" (identification) of a column in a pivoted and/or grouped table. - * What identifies a column is the list of values, one value from each of the pivot columns, - * and a ColumnAggregation denoting on which column (of the original table columns) the aggregation - * is performed and what type of aggregation (min, max, average, ...) is performed. - * - * @author Yonatan B.Y. - */ -/* package */ class ColumnTitle { - - /** - * The list of values from the pivot-by columns. - */ - private List values; - - /** - * The column aggregation denoting this column. - */ - public AggregationColumn aggregation; - - /** - * Indication whether this table comes from a query that has more than one - * aggregation. - */ - private boolean isMultiAggregationQuery; - - /** - * When creating the id of the column, this is used as a separator between the values - * in the pivot columns. - */ - public static final String PIVOT_COLUMNS_SEPARATOR = ","; - - /** - * When creating the id of the column, this is used as a separator between the list of - * values and the column aggregation. - */ - public static final String PIVOT_AGGREGATION_SEPARATOR = " "; - - /** - * Creates a new instance of this class, with the given values and column - * aggregation. - * - * @param values The list of values. - * @param aggregationColumn The aggregation column. - * @param isMultiAggregationQuery Whether this table comes from a - * query with more than one aggregation. - */ - public ColumnTitle(List values, - AggregationColumn aggregationColumn, boolean isMultiAggregationQuery) { - this.values = values; - this.aggregation = aggregationColumn; - this.isMultiAggregationQuery = isMultiAggregationQuery; - } - - /** - * Returns the values in this ColumnTitle. - * @return The values in this ColumnTitle. - */ - public List getValues() { - return values; - } - - /** - * Creates a ColumnDescription for this column. The id is created by - * concatenating the values, and the column aggregation, using the separators - * PIVOT_COLUMNS_SEPARATOR, PIVOT_AGGREGATION_SEPARATOR, - * COLUMN_AGGRGATION_TYPE_SEPARATOR. - * - * @param originalTable The original table, from which the original column description - * of the column under aggregation is taken. - * - * @return The ColumnDescription for this column. - */ - public ColumnDescription createColumnDescription(DataTable originalTable) { - ColumnDescription colDesc = originalTable.getColumnDescription( - aggregation.getAggregatedColumn().getId()); - return createAggregationColumnDescription(colDesc); - } - - /** - * Creates a prefix for a pivoted column id, containing all the values of the - * pivoted columns. Returns an empty string if no pivoting was used. - * - * @return A prefix for the pivoted column id. - */ - private String createIdPivotPrefix() { - if (!isPivot()) { - return ""; - } - return new StrBuilder().appendWithSeparators(values, PIVOT_COLUMNS_SEPARATOR) - .append(PIVOT_AGGREGATION_SEPARATOR).toString(); - } - - /** - * Creates a prefix for a pivoted column label, containing all the values of - * the pivoted columns. Returns an empty string if no pivoting was used. - * - * @return A prefix for the pivoted column label. - */ - private String createLabelPivotPart() { - if (!isPivot()) { - return ""; - } - return new StrBuilder().appendWithSeparators(values, PIVOT_COLUMNS_SEPARATOR).toString(); - } - - /** - * Returns true if pivoting was used. - * - * @return True if pivoting was used. - */ - private boolean isPivot() { - return (!values.isEmpty()); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof ColumnTitle)) { - return false; - } - ColumnTitle other = (ColumnTitle) o; - return values.equals(other.values) && - aggregation.equals(other.aggregation); - } - - @Override - public int hashCode() { - int hash = 1279; // Some arbitrary prime number. - hash = (hash * 17) + values.hashCode(); - hash = (hash * 17) + aggregation.hashCode(); - return hash; - } - - /** - * Creates an aggregation column description. - * - * @param originalColumnDescription The original column description. - * - * @return A column description for the aggregation column. - */ - /* package */ ColumnDescription createAggregationColumnDescription( - ColumnDescription originalColumnDescription) { - AggregationType aggregationType = aggregation.getAggregationType(); - String columnId = createIdPivotPrefix() + aggregation.getId(); - ValueType type = originalColumnDescription.getType(); - String aggregationLabelPart = aggregation.getAggregationType().getCode() - + " " + originalColumnDescription.getLabel(); - String pivotLabelPart = createLabelPivotPart(); - String label; - if (isPivot()) { - if (isMultiAggregationQuery) { - label = pivotLabelPart + " " + aggregationLabelPart; - } else { - label = pivotLabelPart; - } - } else { - label = aggregationLabelPart; - } - - ColumnDescription result; - if (canUseSameTypeForAggregation(type, aggregationType)) { - // Create a new column description and copy original formatters. - result = new ColumnDescription(columnId, type, label); - } else { - // Create a new column description if this is a non numeric column and the aggregation - // type is COUNT. - result = new ColumnDescription(columnId, ValueType.NUMBER, label); - } - - return result; - } - - /** - * Checks whether the aggregation values and column values are of the same type. - * - * @param valueType The type of values in the aggregated column. - * @param aggregationType The aggregation type. - * - * @return True if the aggregation values and column values are of the same - * type. - */ - private boolean canUseSameTypeForAggregation(ValueType valueType, - AggregationType aggregationType) { - boolean ans; - if (valueType == ValueType.NUMBER) { - ans = true; - } else { - switch (aggregationType) { - case MIN: - case MAX: - ans = true; - break; - case SUM: - case AVG: - case COUNT: - ans = false; - break; - default: - // Not supposed to be here. - throw new IllegalArgumentException(); - } - } - return ans; - } -} diff --git a/src/main/java/com/google/visualization/datasource/query/engine/GroupingComparators.java b/src/main/java/com/google/visualization/datasource/query/engine/GroupingComparators.java deleted file mode 100755 index 672539d..0000000 --- a/src/main/java/com/google/visualization/datasource/query/engine/GroupingComparators.java +++ /dev/null @@ -1,149 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query.engine; - -import com.google.common.collect.Ordering; -import com.google.visualization.datasource.datatable.value.Value; -import com.google.visualization.datasource.query.AggregationColumn; - -import java.util.Comparator; -import java.util.List; - -/** - * Contains several comparators that are used by the grouping and pivoting - * mechanism. - * - * @author Yonatan B.Y. - */ -/*package*/ class GroupingComparators { - - /** - * Compares a list of values "lexicographically", i.e., if l1 = (x1...xn) and - * l2 = (y1...ym) then compare(l1, l2) will be compare(xi,yi) when i = - * argmin_k(compare(xk, yk) != 0). The result is 0 if no such k exists and - * both lists are of the same size. If the lists are not of the same size and no - * such k exists, then the longer list is considered to be greater. - */ - public static final Comparator> VALUE_LIST_COMPARATOR = - new Comparator>() { - public int compare(List l1, List l2) { - int i; - int localCompare; - for (i = 0; i < Math.min(l1.size(), l2.size()); i++) { - localCompare = l1.get(i).compareTo(l2.get(i)); - if (localCompare != 0) { - return localCompare; - } - } - - // l1 is not over. - if (i < l1.size()) { - localCompare = 1; - } else if (i < l2.size()) { // l2 is not over. - localCompare = -1; - } else {// both lists of the same size. - localCompare = 0; - } - return localCompare; - } - }; - - /** - * Compares RowTitles by comparing their list of values "lexicographically", - * i.e. by using VALUE_LIST_COMPARATOR on them. - */ - public static final Comparator ROW_TITLE_COMPARATOR = - new Comparator() { - public int compare(RowTitle col1, RowTitle col2) { - return VALUE_LIST_COMPARATOR.compare(col1.values, col2.values); - } - }; - - /** - * Return a comparator that compares ColumnTitles by first comparing their - * lists of (pivot) values "lexicographically" (by using - * VALUE_LIST_COMPARATOR) and if these are equal, compares the - * ColumnAggregation within the title, by simply finding their index in the - * given list, and comparing the indices, i.e., two ColumnTitles that have - * the same pivot values, will compare according to which ColumnTitle's - * ColumnAggregation comes first in the given list. If a ColumnTitle's - * ColumnAggregation isn't in the given list, then it shouldn't be - * compared using this comparator and a runtime exception will be thrown. - * - * @param columnAggregations The list that orders the ColumnAggregations. - * - * @return The comparator. - */ - public static Comparator getColumnTitleDynamicComparator( - List columnAggregations) { - return new ColumnTitleDynamicComparator(columnAggregations); - } - - /** - * Private constructor for utility class. - */ - private GroupingComparators() {} - - /** - * A comparator that compares {@link ColumnTitle}s and is parameterized by a - * list of {@link com.google.visualization.datasource.query.AggregationColumn}s. - *

- * It compares ColumnTitles by first comparing their - * lists of (pivot) values "lexicographically" (by using - * {@code VALUE_LIST_COMPARATOR}) and if these are equal, compares the - * ColumnAggregation within the title, by simply finding their index - * in the given list, and comparing the indices, i.e., two ColumnTitles that - * have the same pivot values, will compare according to which ColumnTitle's - * ColumnAggregation comes first in the given list. If a ColumnTitle's - * ColumnAggregation isn't in the given list, then it shouldn't be - * compared using this comparator and a runtime exception will be thrown. - */ - private static class ColumnTitleDynamicComparator - implements Comparator { - - /** - * A comparator for the ColumnAggregations. - */ - private Comparator aggregationsComparator; - - /** - * Creates a new instance of this class with the ordering of the - * ColumnAggregations is in the given list. - * - * @param aggregations The list that gives order to the ColumnAggregations. - */ - public ColumnTitleDynamicComparator(List aggregations) { - aggregationsComparator = Ordering.explicit(aggregations); - } - - /** - * Compares the ColumnTitles according to the logic described in the - * description of this class. - * - * @param col1 The first ColumnTitle - * @param col2 The second ColumnTitle - * - * @return The compare result. - */ - public int compare(ColumnTitle col1, ColumnTitle col2) { - int listCompare = VALUE_LIST_COMPARATOR.compare(col1.getValues(), - col2.getValues()); - if (listCompare != 0) { - return listCompare; - } - return aggregationsComparator.compare(col1.aggregation, col2.aggregation); - } - } -} diff --git a/src/main/java/com/google/visualization/datasource/query/engine/MetaTable.java b/src/main/java/com/google/visualization/datasource/query/engine/MetaTable.java deleted file mode 100755 index 7ea1ff3..0000000 --- a/src/main/java/com/google/visualization/datasource/query/engine/MetaTable.java +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query.engine; - -import com.google.common.collect.Maps; -import com.google.visualization.datasource.datatable.TableCell; - -import java.util.Map; - -/** - * Holds the data of a table after pivoting and grouping, indexed by {@link RowTitle} and - * {@link ColumnTitle}. - * - * @author Yonatan B.Y. - */ -/* package */ class MetaTable { - - /** - * The data. A map that gives, for each row and column, a map of the cell - * associated with that row and that column. - */ - private Map> data; - - /** - * Creates an empty instance. - */ - public MetaTable() { - data = Maps.newHashMap(); - } - - /** - * Puts a new value in the MetaTable. - * - * @param rowTitle The row into which the cell should be inserted. - * @param columnTitle The column into which the cell should be inserted. - * @param cell The cell to insert. - */ - public void put(RowTitle rowTitle, ColumnTitle columnTitle, - TableCell cell) { - Map rowData = data.get(rowTitle); - if (rowData == null) { - rowData = Maps.newHashMap(); - data.put(rowTitle, rowData); - } - rowData.put(columnTitle, cell); - } - - /** - * Retrieves a cell from the MetaTable. - * - * @param rowTitle The row from which to retrieve the cell. - * @param columnTitle The column from which to retrieve the cell. - * - * @return The cell that is at row rowTitle and column columnTitle or null - * if no such cell exists. - */ - public TableCell getCell(RowTitle rowTitle, ColumnTitle columnTitle) { - Map rowData = data.get(rowTitle); - if (rowData == null) { - return null; - } - return rowData.get(columnTitle); - } - - /** - * Retrieves an entire row, in the form of a hashtable that maps a ColumnTitle - * to a TableCell. - * - * @param rowTitle The title of the row to retrieve. - * - * @return The row. - */ - public Map getRow(RowTitle rowTitle) { - return data.get(rowTitle); - } - - /** - * Returns true if this MetaTable is empty, i.e., contains no rows. - * - * @return True if this MetaTable is empty. - */ - public boolean isEmpty() { - return data.isEmpty(); - } -} diff --git a/src/main/java/com/google/visualization/datasource/query/engine/QueryEngine.java b/src/main/java/com/google/visualization/datasource/query/engine/QueryEngine.java deleted file mode 100755 index 8759cc0..0000000 --- a/src/main/java/com/google/visualization/datasource/query/engine/QueryEngine.java +++ /dev/null @@ -1,720 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query.engine; - -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; -import com.google.visualization.datasource.base.ReasonType; -import com.google.visualization.datasource.base.TypeMismatchException; -import com.google.visualization.datasource.base.Warning; -import com.google.visualization.datasource.datatable.ColumnDescription; -import com.google.visualization.datasource.datatable.DataTable; -import com.google.visualization.datasource.datatable.TableCell; -import com.google.visualization.datasource.datatable.TableRow; -import com.google.visualization.datasource.datatable.ValueFormatter; -import com.google.visualization.datasource.datatable.value.Value; -import com.google.visualization.datasource.query.AbstractColumn; -import com.google.visualization.datasource.query.AggregationColumn; -import com.google.visualization.datasource.query.ColumnLookup; -import com.google.visualization.datasource.query.DataTableColumnLookup; -import com.google.visualization.datasource.query.GenericColumnLookup; -import com.google.visualization.datasource.query.Query; -import com.google.visualization.datasource.query.QueryFilter; -import com.google.visualization.datasource.query.QueryFormat; -import com.google.visualization.datasource.query.QueryGroup; -import com.google.visualization.datasource.query.QueryLabels; -import com.google.visualization.datasource.query.QueryPivot; -import com.google.visualization.datasource.query.QuerySelection; -import com.google.visualization.datasource.query.QuerySort; -import com.google.visualization.datasource.query.ScalarFunctionColumn; -import com.google.visualization.datasource.query.SimpleColumn; - -import com.ibm.icu.util.ULocale; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.SortedSet; -import java.util.TreeMap; -import java.util.TreeSet; -import java.util.concurrent.atomic.AtomicReference; - -/** - * A collection of static methods that perform the operations involved in executing a query, - * i.e., selection, sorting, paging (limit and offset), grouping and pivoting, filtering, skipping, - * applying labels, and custom formatting. This also takes care of calculated columns. - * This also takes care of scalar function columns. - * - * @author Yoah B.D. - * @author Yonatan B.Y. - * @author Liron L. - */ -public final class QueryEngine { - - /** - * Empty private constructor, to prevent initialization. - */ - private QueryEngine() {} - - /** - * Creates the columns structure for a new table after pivoting and grouping. - * - * @param groupByColumnIds The column ids to group by. This is used for the - * ColumnDescriptions of the first columns in the table. - * @param columnTitles The ColumnTitles of the aggregation columns in the table, i.e., columns - * that are composed of pivot values and aggregations. - * @param original The original table, from which to get the original ColumnDescriptions. - * @param scalarFunctionColumnTitles The scalar function column titles. i.e., - * columns that are composed of pivot values and scalar function column. - * - * @return The new TableDescription. - */ - private static DataTable createDataTable( - List groupByColumnIds, SortedSet columnTitles, - DataTable original, List scalarFunctionColumnTitles) { - DataTable result = new DataTable(); - for (String groupById : groupByColumnIds) { - result.addColumn(original.getColumnDescription(groupById)); - } - for (ColumnTitle colTitle : columnTitles) { - result.addColumn(colTitle.createColumnDescription(original)); - } - - for (ScalarFunctionColumnTitle scalarFunctionColumnTitle : scalarFunctionColumnTitles) { - result.addColumn(scalarFunctionColumnTitle.createColumnDescription(original)); - } - return result; - } - - /** - * Returns the data that is the result of executing the query. The query is validated against the - * data table before execution and an InvalidQueryException is thrown if it is invalid. - * This function may change the given DataTable. - * - * @param query The query. - * @param table The table to execute the query on. - * - * @return The data that is the result of executing the query. - */ - public static DataTable executeQuery(Query query, DataTable table, ULocale locale) { - ColumnIndices columnIndices = new ColumnIndices(); - List columnsDescription = table.getColumnDescriptions(); - for (int i = 0; i < columnsDescription.size(); i++) { - columnIndices.put(new SimpleColumn(columnsDescription.get(i).getId()), i); - } - - // A map of column lookups by their list of pivot values. This is utilized in - // the grouping and pivoting queries. - TreeMap, ColumnLookup> columnLookups = - new TreeMap, ColumnLookup>(GroupingComparators.VALUE_LIST_COMPARATOR); - try { - table = performFilter(table, query); - table = performGroupingAndPivoting(table, query, columnIndices, columnLookups); - table = performSort(table, query, locale); - table = performSkipping(table, query); - table = performPagination(table, query); - - AtomicReference columnIndicesReference = - new AtomicReference(columnIndices); - table = performSelection(table, query, columnIndicesReference, columnLookups); - columnIndices = columnIndicesReference.get(); - - table = performLabels(table, query, columnIndices); - table = performFormatting(table, query, columnIndices, locale); - } catch (TypeMismatchException e) { - // Should not happen. - } - return table; - } - - /** - * Returns a table consisted of a subset of rows of the input table. - * We select the first out of every k rows in the table according to the - * skipping value in the query. - * If there is no need to do anything, returns the original table. - * - * @param table The original table. - * @param query The query. - * - * @return The skipped table, or the original if no skipping is needed. - */ - private static DataTable performSkipping(DataTable table, Query query) - throws TypeMismatchException { - int rowSkipping = query.getRowSkipping(); - - // Return the original table if no skipping is needed - if (rowSkipping <= 1) { - return table; - } - - // Add the first out of every k rows of the original table to TableRow - int numRows = table.getNumberOfRows(); - List relevantRows = new ArrayList(); - for (int rowIndex = 0; rowIndex < numRows; rowIndex += rowSkipping) { - relevantRows.add(table.getRows().get(rowIndex)); - } - - // Create a table out of the TableRow array - DataTable newTable = new DataTable(); - newTable.addColumns(table.getColumnDescriptions()); - newTable.addRows(relevantRows); - - return newTable; - } - - /** - * Returns a paginated table, based on the row limit and offset parameters. - * If there is no need to do anything, returns the original table. - * - * @param table The original table. - * @param query The query. - * - * @return The paginated table, or the original if no pagination is needed. - */ - private static DataTable performPagination(DataTable table, Query query) - throws TypeMismatchException { - int rowOffset = query.getRowOffset(); - int rowLimit = query.getRowLimit(); - - // Return the original table if no pagination is needed - if (((rowLimit == -1) || (table.getRows().size() <= rowLimit)) && (rowOffset == 0)) { - return table; - } - int numRows = table.getNumberOfRows(); - int fromIndex = Math.max(0, rowOffset); - int toIndex = (rowLimit == -1) ? numRows : Math.min(numRows, rowOffset + rowLimit); - - List relevantRows = table.getRows().subList(fromIndex, toIndex); - DataTable newTable = new DataTable(); - newTable.addColumns(table.getColumnDescriptions()); - newTable.addRows(relevantRows); - - if (toIndex < numRows) { // Data truncated - Warning warning = new Warning(ReasonType.DATA_TRUNCATED, "Data has been truncated due to user" - + "request (LIMIT in query)"); - newTable.addWarning(warning); - } - - return newTable; - } - - /** - * Returns a table sorted according to the query's sort. - * The returned table has the same rows as the original table. - * - * @param table The table to sort. - * @param query The query. - * - * @return The sorted table. - */ - private static DataTable performSort(DataTable table, Query query, ULocale locale) { - if (!query.hasSort()) { - return table; - } - QuerySort sortBy = query.getSort(); - // A table description column lookup is enough because sorting by a column - // that has multiple matching columns after pivoting is impossible. For example, - // it is impossible to sort by an aggregation column when there is a pivot. - DataTableColumnLookup columnLookup = new DataTableColumnLookup(table); - TableRowComparator comparator = new TableRowComparator(sortBy, locale, columnLookup); - Collections.sort(table.getRows(), comparator); - return table; - } - - /** - * Returns a table that has only the rows from the given table that match the filter - * provided by a query. - * - * @param table The table to filter. - * @param query The query. - * - * @return The filtered table. - */ - private static DataTable performFilter(DataTable table, Query query) - throws TypeMismatchException { - if (!query.hasFilter()) { - return table; - } - - List newRowList = Lists.newArrayList(); - QueryFilter filter = query.getFilter(); - for (TableRow inputRow : table.getRows()) { - if (filter.isMatch(table, inputRow)) { - newRowList.add(inputRow); - } - } - table.setRows(newRowList); - return table; - } - - /** - * Returns a table that has only the columns from the given table that are specified by - * the query. - * - * @param table The table from which to select. - * @param query The query. - * @param columnIndicesReference A reference to a ColumnIndices instance, so that - * this function can change the internal ColumnIndices. - * @param columnLookups A map of column lookups by their list of pivot values. - * - * @return The table with selected columns only. - */ - private static DataTable performSelection(DataTable table, Query query, - AtomicReference columnIndicesReference, - Map, ColumnLookup> columnLookups) throws TypeMismatchException { - if (!query.hasSelection()) { - return table; - } - - ColumnIndices columnIndices = columnIndicesReference.get(); - - List selectedColumns = query.getSelection().getColumns(); - List selectedIndices = Lists.newArrayList(); - - // Build the new table description, and update columnIndices - List oldColumnDescriptions = table.getColumnDescriptions(); - List newColumnDescriptions = Lists.newArrayList(); - ColumnIndices newColumnIndices = new ColumnIndices(); - int currIndex = 0; - for (AbstractColumn col : selectedColumns) { - // If the query has pivoting, then AggregationColumns in the SELECT are - // discarded, since they are only there to control the pivoting. - List colIndices = columnIndices.getColumnIndices(col); - selectedIndices.addAll(colIndices); - // If the selected column does not exist in the columnIndices, then it is - // a scalar function column that was not in the original table, and was not - // calculated in the grouping and pivoting stage. - if (colIndices.size() == 0) { - newColumnDescriptions.add(new ColumnDescription(col.getId(), - col.getValueType(table), - ScalarFunctionColumnTitle.getColumnDescriptionLabel(table, col))); - newColumnIndices.put(col, currIndex++); - } else { - for (int colIndex : colIndices) { - newColumnDescriptions.add(oldColumnDescriptions.get(colIndex)); - newColumnIndices.put(col, currIndex++); - } - } - } - columnIndices = newColumnIndices; - columnIndicesReference.set(columnIndices); - - DataTable result = new DataTable(); - result.addColumns(newColumnDescriptions); - - // Calculate the values in the data table rows. - for (TableRow sourceRow : table.getRows()) { - TableRow newRow = new TableRow(); - for (AbstractColumn col : selectedColumns) { - boolean wasFound = false; - Set> pivotValuesSet = columnLookups.keySet(); - for (List values : pivotValuesSet) { - // If the current column-lookup contains the current column and it is - // either a column that contains aggregations or a column that - // contains only group-by columns and was not yet found, get its value - // in the current row. Otherwise continue. If the column contains - // only group-by columns it should appear only once, even though - // it may appear in many column lookups. - if (columnLookups.get(values).containsColumn(col) - && ((col.getAllAggregationColumns().size() != 0) || !wasFound)) { - wasFound = true; - newRow.addCell(sourceRow.getCell(columnLookups.get(values).getColumnIndex(col))); - } - } - // If the column was not found in any of the column lookups - // calculate its value (e.g., scalar function column that was not - // calculated in a previous stage). - if (!wasFound) { - DataTableColumnLookup lookup = new DataTableColumnLookup(table); - newRow.addCell(col.getCell(lookup, sourceRow)); - } - } - result.addRow(newRow); - } - return result; - } - - /** - * Returns true if the query has aggregation columns and the table is not - * empty. - * - * @param query The given query. - * - * @return true if the query has aggregation columns and the table is not - * empty. - */ - private static boolean queryHasAggregation(Query query) { - return (query.hasSelection() - && !query.getSelection().getAggregationColumns().isEmpty()); - } - - /** - * Returns the result of performing the grouping (and pivoting) operations - * on the given table, using the information provided in the query's group - * and pivot. - * - * The new table generated has columns as follows where A is the number of group-by columns, - * B is the number of combinations of values of pivot-by columns, and X is the number of - * aggregations requested: - * - Columns 1..A are the original group-by columns, in the order they are - * given in the group-by list. - * - Columns (A+1)..B are pivot and aggregation columns, where each - * column's id is composed of values of the pivot-by columns in the - * original table, and an aggregation column, with separators between them. - * - * Note that the aggregations requested can be all on the same - * aggregation column or on different aggregation columns. To this - * mechanism, it doesn't matter. - * - * There is a row for each combination of the values of the group-by columns. - * - * The value in the cell at row X and column Y is the result of the requested - * aggregation type described in Y on the set of values in the aggregation - * column (also described in Y) for which the values of the group-by columns - * are as determined by X and the values of the pivot-by columns are as - * determined by the column. - * - * @param table The original table. - * @param query The query. - * @param columnIndices A map, in which this method sets the indices - * of the new columns, if grouping is performed, and then any - * previous values in it are cleared. If grouping is not performed, it is - * left as is. - * - * @return The new table, after grouping and pivoting was performed. - */ - private static DataTable performGroupingAndPivoting(DataTable table, Query query, - ColumnIndices columnIndices, TreeMap, ColumnLookup> columnLookups) - throws TypeMismatchException { - if (!queryHasAggregation(query) || (table.getNumberOfRows() == 0)) { - return table; - } - QueryGroup group = query.getGroup(); - QueryPivot pivot = query.getPivot(); - QuerySelection selection = query.getSelection(); - - List groupByIds = Lists.newArrayList(); - if (group != null) { - groupByIds = group.getColumnIds(); - } - - List pivotByIds = Lists.newArrayList(); - if (pivot != null) { - pivotByIds = pivot.getColumnIds(); // contained in groupByIds - } - - List groupAndPivotIds = Lists.newArrayList(groupByIds); - groupAndPivotIds.addAll(pivotByIds); - - List tmpColumnAggregations = selection.getAggregationColumns(); - List selectedScalarFunctionColumns = selection.getScalarFunctionColumns(); - - // Remove duplicates from tmpColumnAggregations, creating columnAggregations: - List columnAggregations = - Lists.newArrayListWithExpectedSize(tmpColumnAggregations.size()); - for (AggregationColumn aggCol : tmpColumnAggregations) { - if (!columnAggregations.contains(aggCol)) { - columnAggregations.add(aggCol); - } - } - - List aggregationIds = Lists.newArrayList(); - for (AggregationColumn col : columnAggregations) { - aggregationIds.add(col.getAggregatedColumn().getId()); - } - - List groupAndPivotScalarFunctionColumns = Lists.newArrayList(); - if (group != null) { - groupAndPivotScalarFunctionColumns.addAll(group.getScalarFunctionColumns()); - } - if (pivot != null) { - groupAndPivotScalarFunctionColumns.addAll(pivot.getScalarFunctionColumns()); - } - - List newColumnDescriptions = Lists.newArrayList(); - newColumnDescriptions.addAll(table.getColumnDescriptions()); - - // Add to the table description the scalar function columns included in the - // group and pivot. The groups of rows are defined according to the - // values of those columns, and so it is necessary to add them before the - // calculations of the groups, pivots and aggregations. - for (ScalarFunctionColumn column : groupAndPivotScalarFunctionColumns) { - newColumnDescriptions.add(new ColumnDescription(column.getId(), - column.getValueType(table), - ScalarFunctionColumnTitle.getColumnDescriptionLabel(table, column))); - } - - DataTable tempTable = new DataTable(); - tempTable.addColumns(newColumnDescriptions); - - // Calculate the values of the added scalar function columns in each row. - DataTableColumnLookup lookup = new DataTableColumnLookup(table); - for (TableRow sourceRow : table.getRows()) { - TableRow newRow = new TableRow(); - for (TableCell sourceCell : sourceRow.getCells()) { - newRow.addCell(sourceCell); - } - for (ScalarFunctionColumn column : groupAndPivotScalarFunctionColumns) { - newRow.addCell(new TableCell(column.getValue(lookup, sourceRow))); - } - try { - tempTable.addRow(newRow); - } catch (TypeMismatchException e) { - // Should not happen, given that the original table is OK. - } - } - table = tempTable; - - // Calculate the aggregations. - TableAggregator aggregator = new TableAggregator(groupAndPivotIds, - Sets.newHashSet(aggregationIds), table); - Set paths = aggregator.getPathsToLeaves(); - - // These variables will hold the "titles" of the rows and columns. - // They are TreeSets because their order matters. - SortedSet rowTitles = - Sets.newTreeSet(GroupingComparators.ROW_TITLE_COMPARATOR); - SortedSet columnTitles = Sets.newTreeSet( - GroupingComparators.getColumnTitleDynamicComparator(columnAggregations)); - - // A tree set containing all pivot value lists (the set is for the - // uniqueness and the tree for the order). - TreeSet> pivotValuesSet = - Sets.newTreeSet(GroupingComparators.VALUE_LIST_COMPARATOR); - // This MetaTable holds all the data in the table, this data is then - // dumped into the real table. - MetaTable metaTable = new MetaTable(); - for (AggregationColumn columnAggregation : columnAggregations) { - for (AggregationPath path : paths) { - - // A ColumnTitle is composed of all the values for the pivot-by - // columns, and a ColumnAggregation. That is why it is necessary to iterate over all - // ColumnAggregations and create a ColumnTitle for each one. - List originalValues = path.getValues(); - - // Separate originalValues into the rowValues and columnValues. The - // rowValues are the values of the group-by columns and the columnValues - // are the values of the pivot-by columns. - List rowValues = originalValues.subList(0, groupByIds.size()); - RowTitle rowTitle = new RowTitle(rowValues); - rowTitles.add(rowTitle); - - List columnValues = originalValues.subList(groupByIds.size(), originalValues.size()); - pivotValuesSet.add(columnValues); - - ColumnTitle columnTitle = new ColumnTitle(columnValues, - columnAggregation, (columnAggregations.size() > 1)); - columnTitles.add(columnTitle); - metaTable.put(rowTitle, columnTitle, new TableCell(aggregator.getAggregationValue(path, - columnAggregation.getAggregatedColumn().getId(), - columnAggregation.getAggregationType()))); - } - } - - // Create the scalar function column titles for the scalar function columns - // that contain aggregations. - List scalarFunctionColumnTitles = - Lists.newArrayList(); - for (ScalarFunctionColumn scalarFunctionColumn : - selectedScalarFunctionColumns) { - if (scalarFunctionColumn.getAllAggregationColumns().size() != 0) { - for (List columnValues : pivotValuesSet) { - scalarFunctionColumnTitles.add(new ScalarFunctionColumnTitle(columnValues, - scalarFunctionColumn)); - } - } - } - - // Create the new table description. - DataTable result = createDataTable(groupByIds, columnTitles, table, scalarFunctionColumnTitles); - List colDescs = result.getColumnDescriptions(); - - // Fill the columnIndices and columnLookups parameters for the group-by - // columns and the aggregation columns. - columnIndices.clear(); - int columnIndex = 0; - if (group != null) { - List empytListOfValues = Lists.newArrayList(); - columnLookups.put(empytListOfValues, new GenericColumnLookup()); - for (AbstractColumn column : group.getColumns()) { - columnIndices.put(column, columnIndex); - if (!(column instanceof ScalarFunctionColumn)) { - ((GenericColumnLookup) columnLookups.get(empytListOfValues)).put(column, columnIndex); - for (List columnValues : pivotValuesSet) { - if (!columnLookups.containsKey(columnValues)) { - columnLookups.put(columnValues, new GenericColumnLookup()); - } - ((GenericColumnLookup) columnLookups.get(columnValues)).put(column, columnIndex); - } - } - columnIndex++; - } - } - - for (ColumnTitle title : columnTitles) { - columnIndices.put(title.aggregation, columnIndex); - List values = title.getValues(); - if (!columnLookups.containsKey(values)) { - columnLookups.put(values, new GenericColumnLookup()); - } - ((GenericColumnLookup) columnLookups.get(values)).put(title.aggregation, columnIndex); - columnIndex++; - } - - // Dump the data from the metaTable to the result DataTable. - for (RowTitle rowTitle : rowTitles) { - TableRow curRow = new TableRow(); - // Add the group-by columns cells. - for (Value v : rowTitle.values) { - curRow.addCell(new TableCell(v)); - } - Map rowData = metaTable.getRow(rowTitle); - int i = 0; - // Add the aggregation columns cells. - for (ColumnTitle colTitle : columnTitles) { - TableCell cell = rowData.get(colTitle); - curRow.addCell((cell != null) ? cell : new TableCell( - Value.getNullValueFromValueType(colDescs.get(i + rowTitle.values.size()).getType()))); - i++; - } - // Add the scalar function columns cells. - for (ScalarFunctionColumnTitle columnTitle : scalarFunctionColumnTitles) { - curRow.addCell(new TableCell(columnTitle.scalarFunctionColumn. - getValue(columnLookups.get(columnTitle.getValues()), curRow))); - } - result.addRow(curRow); - } - - // Fill the columnIndices and columnLookups parameters for the scalar - // function column titles. This must be done after the calculation of the values - // in the scalar function column cells, or else the scalar function columns - // will not calculate their value recursively, but return the current value. - // See the logic of the getValue() method in ScalarFunctionColumn. - for (ScalarFunctionColumnTitle scalarFunctionColumnTitle - : scalarFunctionColumnTitles) { - columnIndices.put(scalarFunctionColumnTitle.scalarFunctionColumn, - columnIndex); - List values = scalarFunctionColumnTitle.getValues(); - if (!columnLookups.containsKey(values)) { - columnLookups.put(values, new GenericColumnLookup()); - } - ((GenericColumnLookup) columnLookups.get(values)).put( - scalarFunctionColumnTitle.scalarFunctionColumn, columnIndex); - columnIndex++; - } - - return result; - } - - /** - * Apply labels to columns as specified in the user query. - * If a column is specified in the query, but is not part of the data table, - * this is still a valid situation, and the "invalid" column id is ignored. - * - * @param table The original table. - * @param query The query. - * @param columnIndices The map of columns to indices in the table. - * - * @return The table with labels applied. - */ - private static DataTable performLabels(DataTable table, Query query, - ColumnIndices columnIndices) { - - if (!query.hasLabels()) { - return table; - } - - QueryLabels labels = query.getLabels(); - - List columnDescriptions = table.getColumnDescriptions(); - - for (AbstractColumn column : labels.getColumns()) { - String label = labels.getLabel(column); - List indices = columnIndices.getColumnIndices(column); - if (indices.size() == 1) { - columnDescriptions.get(indices.get(0)).setLabel(label); - } else { - String columnId = column.getId(); // Without pivot values. - for (int i : indices) { - ColumnDescription colDesc = columnDescriptions.get(i); - String colDescId = colDesc.getId(); // Includes pivot values. - String specificLabel = - colDescId.substring(0, colDescId.length() - columnId.length()) + label; - columnDescriptions.get(i).setLabel(specificLabel); - } - - } - } - return table; - } - - /** - * Add column formatters according to a given patterns list. Namely, - * a visualization gadget can send a map of patterns by column ids. The following - * method builds the appropriate formatters for these patterns. - * An illegal pattern is recorded for later sending of a warning. - * - * @param table The original table. - * @param query The query. - * @param columnIndices The map of columns to indices in the table. - * @param locale The locale by which to format. - * - * @return The table with formatting applied. - */ - private static DataTable performFormatting(DataTable table, Query query, - ColumnIndices columnIndices, ULocale locale) { - if (!query.hasUserFormatOptions()) { - return table; - } - - QueryFormat queryFormat = query.getUserFormatOptions(); - List columnDescriptions = table.getColumnDescriptions(); - Map indexToFormatter = Maps.newHashMap(); - for (AbstractColumn col : queryFormat.getColumns()) { - String pattern = queryFormat.getPattern(col); - List indices = columnIndices.getColumnIndices(col); - boolean allSucceeded = true; - for (int i : indices) { - ColumnDescription colDesc = columnDescriptions.get(i); - ValueFormatter f = ValueFormatter.createFromPattern(colDesc.getType(), pattern, locale); - if (f == null) { - allSucceeded = false; - } else { - indexToFormatter.put(i, f); - table.getColumnDescription(i).setPattern(pattern); // May override datasource pattern. - } - } - if (!allSucceeded) { - Warning warning = new Warning(ReasonType.ILLEGAL_FORMATTING_PATTERNS, - "Illegal formatting pattern: " + pattern + " requested on column: " + col.getId()); - table.addWarning(warning); - } - } - - for (TableRow row : table.getRows()) { - for (int col : indexToFormatter.keySet()) { - TableCell cell = row.getCell(col); - Value value = cell.getValue(); - ValueFormatter formatter = indexToFormatter.get(col); - String formattedValue = formatter.format(value); - cell.setFormattedValue(formattedValue); - } - } - return table; - } -} diff --git a/src/main/java/com/google/visualization/datasource/query/engine/RowTitle.java b/src/main/java/com/google/visualization/datasource/query/engine/RowTitle.java deleted file mode 100755 index 7813e06..0000000 --- a/src/main/java/com/google/visualization/datasource/query/engine/RowTitle.java +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query.engine; - -import com.google.visualization.datasource.datatable.value.Value; - -import java.util.List; - -/** - * A "title" (identification) of a row in a pivoted and/or grouped table. - * What identifies a row is the list of values, one value from each of the group-by columns. - * - * @author Yonatan B.Y. - */ -/* package */ class RowTitle { - - /** - * The values of the group-by columns that identify the row. - */ - public List values; - - /** - * Creates a new instance with the given list of group-by column values. - * - * @param values The list of group-by column values. - */ - public RowTitle(List values) { - this.values = values; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof RowTitle)) { - return false; - } - RowTitle other = (RowTitle) o; - return values.equals(other.values); - } - - - @Override - public int hashCode() { - return values.hashCode(); - } -} diff --git a/src/main/java/com/google/visualization/datasource/query/engine/ScalarFunctionColumnTitle.java b/src/main/java/com/google/visualization/datasource/query/engine/ScalarFunctionColumnTitle.java deleted file mode 100755 index d795bca..0000000 --- a/src/main/java/com/google/visualization/datasource/query/engine/ScalarFunctionColumnTitle.java +++ /dev/null @@ -1,190 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query.engine; - -import com.google.visualization.datasource.datatable.ColumnDescription; -import com.google.visualization.datasource.datatable.DataTable; -import com.google.visualization.datasource.datatable.value.Value; -import com.google.visualization.datasource.datatable.value.ValueType; -import com.google.visualization.datasource.query.AbstractColumn; -import com.google.visualization.datasource.query.AggregationColumn; -import com.google.visualization.datasource.query.ScalarFunctionColumn; - -import org.apache.commons.lang.text.StrBuilder; - -import java.util.List; - -/** - * A "title" (identification) of a scalar function column in a pivoted and/or grouped table. - * What identifies a column is the list of values, one value from each of the - * pivot columns, and a ScalarFunctionColumn denoting the original column (of the original table - * columns). - * - * @author Liron L. - */ -/* package */ class ScalarFunctionColumnTitle { - - /** - * The list of values from the pivot-by columns. - */ - private List values; - - /** - * The scalar function column denoting this column. - */ - public ScalarFunctionColumn scalarFunctionColumn; - - /** - * When creating the id of the column, this is used as a separator between the values - * in the pivot-by columns. - */ - public static final String PIVOT_COLUMNS_SEPARATOR = ","; - - /** - * When creating the id of the column, this is used as a separator between the list of - * values and the ScalarFunctionColumn. - */ - public static final String PIVOT_SCALAR_FUNCTION_SEPARATOR = " "; - - /** - * Creates a new instance of this class, with the given values and - * ScalarFunctionColumn. - * - * @param values The list of values. - * @param column The ScalarFunctionColumn. - */ - public ScalarFunctionColumnTitle(List values, - ScalarFunctionColumn column) { - this.values = values; - this.scalarFunctionColumn = column; - } - - /** - * Returns the values in this ColumnTitle. - * - * @return The values in this ColumnTitle. - */ - public List getValues() { - return values; - } - - /** - * Creates a ColumnDescription for this column. - * - * @param originalTable The original table, from which the original column description - * of the column is taken. - * - * @return The ColumnDescription for this column. - */ - public ColumnDescription createColumnDescription(DataTable originalTable) { - String columnId = createIdPivotPrefix() + scalarFunctionColumn.getId(); - ValueType type = scalarFunctionColumn.getValueType(originalTable); - String label = createLabelPivotPart() + " " + - getColumnDescriptionLabel(originalTable, scalarFunctionColumn); - ColumnDescription result = new ColumnDescription(columnId, type, label); - - return result; - } - - /** - * Creates a prefix for a pivoted column id, containing all the values of the - * pivoted columns. Returns the empty string if no pivoting was used. - * - * @return A prefix for the pivoted column id. - */ - private String createIdPivotPrefix() { - if (!isPivot()) { - return ""; - } - return new StrBuilder().appendWithSeparators(values, PIVOT_COLUMNS_SEPARATOR) - .append(PIVOT_SCALAR_FUNCTION_SEPARATOR).toString(); - } - - /** - * Creates a prefix for a pivoted column label, containing all the values of - * the pivoted columns. Returns an empty string if no pivoting was used. - * - * @return A prefix for the pivoted column label. - */ - private String createLabelPivotPart() { - if (!isPivot()) { - return ""; - } - return new StrBuilder().appendWithSeparators(values, PIVOT_COLUMNS_SEPARATOR).toString(); - } - - /** - * Returns true if pivoting was used. - * - * @return True if pivoting was used. - */ - private boolean isPivot() { - return (!values.isEmpty()); - } - - /** - * Returns the label of the column description. - * - * @param originalTable The original table, from which the original column description of the - * column is taken. - * - * @return The label of the column description. - */ - public static String getColumnDescriptionLabel(DataTable originalTable, AbstractColumn column) { - StringBuilder label = new StringBuilder(); - if (originalTable.containsColumn(column.getId())) { - label.append(originalTable.getColumnDescription(column.getId()).getLabel()); - } else { - if (column instanceof AggregationColumn) { - AggregationColumn aggColumn = (AggregationColumn) column; - label.append(aggColumn.getAggregationType().getCode()).append(" "). - append(originalTable.getColumnDescription( - aggColumn.getAggregatedColumn().getId()).getLabel()); - } else { - ScalarFunctionColumn scalarFunctionColumn = (ScalarFunctionColumn) column; - List columns = scalarFunctionColumn.getColumns(); - label.append(scalarFunctionColumn.getFunction().getFunctionName()).append("("); - for (AbstractColumn abstractColumn : columns) { - label.append(getColumnDescriptionLabel(originalTable, abstractColumn)); - } - label.append(")"); - } - } - return label.toString(); - } - - @Override - public boolean equals(Object o) { - if (o instanceof ScalarFunctionColumnTitle) { - ScalarFunctionColumnTitle other = (ScalarFunctionColumnTitle) o; - return (values.equals(other.values) - && scalarFunctionColumn.equals(other.scalarFunctionColumn)); - } - return false; - } - - @Override - public int hashCode() { - int result = 31; - if (scalarFunctionColumn != null) { - result += scalarFunctionColumn.hashCode(); - } - result *= 31; - if (values != null) { - result += values.hashCode(); - } - return result; - } -} diff --git a/src/main/java/com/google/visualization/datasource/query/engine/TableAggregator.java b/src/main/java/com/google/visualization/datasource/query/engine/TableAggregator.java deleted file mode 100755 index c7dc42d..0000000 --- a/src/main/java/com/google/visualization/datasource/query/engine/TableAggregator.java +++ /dev/null @@ -1,152 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query.engine; - -import com.google.common.collect.Maps; -import com.google.visualization.datasource.datatable.DataTable; -import com.google.visualization.datasource.datatable.TableRow; -import com.google.visualization.datasource.datatable.value.Value; -import com.google.visualization.datasource.query.AggregationType; - -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * Aggregates a DataTable according to specific row groups. The groups are defined by an ordered - * list of group-by columns. For instance, if the list is {"Name", "Revenue"} then each unique - * pair of values of these columns (e.g., {"John", 300}, {"John", 19}, {"Sarah", 2222}) defines a - * group, where the group includes all of the rows that share the values defined by the pair (for - * example all the rows where value("Name") = "John" and value("Cost") = 300). In addition there is - * a group for each unique name ({"John"}, {"Sarah"}) and an additional group that contains all the - * rows in the table. - * The groups described above are kept in an aggregation tree. The root of the tree contains - * aggregation information for the group of all rows. Each level of the tree (except for the root - * level) is associated with an aggregation column. Each node of the tree is associated with a - * value (of some cell in the column defining the node's level). A path in the tree from the root - * to a node is represented by an ordered list of values, and is associated with the group of data - * rows identified by this list. In our example the tree contains one path of length 0 ({}), two - * paths of length 1 ({"John"}, {"Sarah"}), and three paths of length two ({"John", 300}, - * {"John", 19}, {"Sarah", 2222}). - * - * The aggregation data stored is all aggregation data possible for the columns to aggregate (also - * called aggregation columns): the minimum, maximum, count, average, and sum, each of these - * where applicable. - * - * @author Yoav G. - */ - -public class TableAggregator { - - /** - * An ordered list of columns to group by. - */ - private List groupByColumns; - - /** - * A set of columns to aggregate. - */ - private Set aggregateColumns; - - /** - * An aggregation tree is the logical data structure to use for grouping. - */ - private AggregationTree tree; - - /** - * Constructs a table aggregator and aggregates the table. - * - * @param groupByColumns An ordered list of columns to group by. - * @param aggregateColumns A set of columns to aggregate. - * @param table The table. - */ - public TableAggregator(List groupByColumns, Set aggregateColumns, - DataTable table) { - - this.groupByColumns = groupByColumns; - this.aggregateColumns = aggregateColumns; - - tree = new AggregationTree(aggregateColumns, table); - - // Iterate over all rows and aggregate each row via the aggregation tree. - for (TableRow row : table.getRows()) { - tree.aggregate(getRowPath(row, table, groupByColumns.size() - 1), - getValuesToAggregate(row, table)); - } - } - - /** - * Creates a path for the aggregation tree defined by a table row. - * - * @param row The table row. - * @param table The table. - * @param depth The depth of the desired path. - * - * @return A path for the aggregation tree defined by the table row. - */ - public AggregationPath getRowPath(TableRow row, DataTable table, int depth) { - AggregationPath result = new AggregationPath(); - // The tree path is generated by looking for the values of the group-by - // columns in the table row (in the correct order). - for (int i = 0; i <= depth; i++) { - String columnId = groupByColumns.get(i); - Value curValue = row.getCell(table.getColumnIndex(columnId)).getValue(); - result.add(curValue); - } - return result; - } - - /** - * Returns a set containing the paths to all the leaves in the tree. - * - * @return A set containing the paths to all the leaves in the tree. - */ - public Set getPathsToLeaves() { - return tree.getPathsToLeaves(); - } - - /** - * Creates a map from column id to value according to the aggregation columns. - * - * @param row The table row. - * @param table The table. - * - * @return A map from column id to value according to the aggregation columns. - */ - private Map getValuesToAggregate(TableRow row, DataTable table) { - Map result = Maps.newHashMap(); - // The map is generated by looking for the values of the aggregation columns - // in the table row. - for (String columnId : aggregateColumns) { - Value curValue = row.getCell(table.getColumnIndex(columnId)).getValue(); - result.put(columnId, curValue); - } - return result; - } - - /** - * Returns the aggregation value of a specific column and type. - * - * @param path The aggregation path. - * @param columnId The requested column id. - * @param type The requested aggregation type. - * - * @return The aggregation values of a specific column. - */ - public Value getAggregationValue(AggregationPath path, String columnId, - AggregationType type) { - return tree.getNode(path).getAggregationValue(columnId, type); - } -} diff --git a/src/main/java/com/google/visualization/datasource/query/engine/TableRowComparator.java b/src/main/java/com/google/visualization/datasource/query/engine/TableRowComparator.java deleted file mode 100755 index 5b8b4e3..0000000 --- a/src/main/java/com/google/visualization/datasource/query/engine/TableRowComparator.java +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query.engine; - -import com.google.visualization.datasource.datatable.TableRow; -import com.google.visualization.datasource.datatable.value.Value; -import com.google.visualization.datasource.query.AbstractColumn; -import com.google.visualization.datasource.query.ColumnLookup; -import com.google.visualization.datasource.query.ColumnSort; -import com.google.visualization.datasource.query.QuerySort; -import com.google.visualization.datasource.query.SortOrder; -import com.ibm.icu.util.ULocale; - -import java.util.Comparator; -import java.util.List; - -/** - * A comparator comparing two {@link TableRow}s according to the query's ORDER BY, i.e., - * {@link QuerySort}. - * - * @author Yoah B.D. - */ -/*package*/ class TableRowComparator implements Comparator { - - /** - * The columns to order by, in sequence of importance. - */ - private AbstractColumn[] sortColumns; - - /** - * The sort order of the columns to order by, in sequence of importance. Will - * be of same size as sortColumnIndex. - */ - private SortOrder[] sortColumnOrder; - - /** - * A value comparator. - */ - private Comparator valueComparator; - - /** - * The column lookup. - */ - private ColumnLookup columnLookup; - - /** - * Construct a new TableRowComparator. - * - * @param sort The ordering criteria. - * @param locale The locale defining the order relation of text values. - * @param lookup The column lookup. - */ - public TableRowComparator(QuerySort sort, ULocale locale, ColumnLookup lookup) { - valueComparator = Value.getLocalizedComparator(locale); - columnLookup = lookup; - List columns = sort.getSortColumns(); - sortColumns = new AbstractColumn[columns.size()]; - sortColumnOrder = new SortOrder[columns.size()]; - for (int i = 0; i < columns.size(); i++) { - ColumnSort columnSort = columns.get(i); - sortColumns[i] = columnSort.getColumn(); - sortColumnOrder[i] = columnSort.getOrder(); - } - } - - /** - * Compares two arguments for order. Returns a negative integer, zero, or - * a positive integer if the first argument is less than, equal to, or greater - * than the second. - * - * @param r1 the first row to be compared. - * @param r2 the second row to be compared. - * - * @return a negative integer, zero, or a positive integer as the first - * argument is less than, equal to, or greater than the second. - */ - public int compare(TableRow r1, TableRow r2) { - for (int i = 0; i < sortColumns.length; i++) { - AbstractColumn col = sortColumns[i]; - int cc = valueComparator.compare(col.getValue(columnLookup, r1), - col.getValue(columnLookup, r2)); - if (cc != 0) { - return (sortColumnOrder[i] == SortOrder.ASCENDING) ? cc : -cc; - } - } - return 0; - } -} diff --git a/src/main/java/com/google/visualization/datasource/query/engine/ValueAggregator.java b/src/main/java/com/google/visualization/datasource/query/engine/ValueAggregator.java deleted file mode 100755 index 7fdc53e..0000000 --- a/src/main/java/com/google/visualization/datasource/query/engine/ValueAggregator.java +++ /dev/null @@ -1,165 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query.engine; - -import com.google.visualization.datasource.datatable.value.NumberValue; -import com.google.visualization.datasource.datatable.value.Value; -import com.google.visualization.datasource.datatable.value.ValueType; -import com.google.visualization.datasource.query.AggregationType; - -/** - * Aggregates a set of values. Adds one value at a time to the aggregated set. - * This allows getting the values of: minimum, maximum, sum, count and average for the aggregated - * set. Each one of these values is available only where appropriate (for instance, you cannot - * average on text values). - * The set of values itself is not stored. - * Only non-null values are considered for aggregation. - * - * @author Yoav G. - */ - -/*package*/ class ValueAggregator { - - /** - * The column type of the values to be aggregated. - */ - private ValueType valueType; - - /** - * The maximum value found so far. - */ - private Value max; - - /** - * The minimum value found so far. - */ - private Value min; - - /** - * The sum of all aggregated values. Updated only for NumberValue. - */ - private double sum = 0; - - /** - * The number of non null values aggregated. - */ - private int count = 0; - - /** - * Constructs a new column value aggregator. - * - * @param valueType The column type of this aggregator. This type defines - * the type of all values to be aggregated. - */ - public ValueAggregator(ValueType valueType) { - this.valueType = valueType; - min = max = Value.getNullValueFromValueType(valueType); - } - - /** - * Aggregates an additional value. If this value is not null it is counted, - * summed, and compared against the current maximum and minimum values to - * consider replacing them. - * - * @param value The value to aggregate. - */ - public void aggregate(Value value) { - if (!value.isNull()) { - count++; - if (valueType == ValueType.NUMBER) { - sum += ((NumberValue) value).getValue(); - } - if (count == 1) { // First non null element. - max = min = value; - } else { - max = max.compareTo(value) >= 0 ? max : value; - min = min.compareTo(value) <= 0 ? min : value; - } - } else if (count == 0) { - min = max = value; - } - } - - /** - * Returns the sum of all (non null) aggregated values. - * - * @return The sum of all (non null) aggregated values. - * - * @throws UnsupportedOperationException In case the column type does not - * support sum. - */ - private double getSum() { - if (valueType != ValueType.NUMBER) { - throw new UnsupportedOperationException(); - } - return sum; - } - - /** - * Returns the average (or null if no non-null values were aggregated). - * - * @return The average (or null if no non-null values were aggregated). - * - * @throws UnsupportedOperationException If the column type does not support average. - */ - private Double getAverage() { - if (valueType != ValueType.NUMBER) { - throw new UnsupportedOperationException(); - } - return count > 0 ? sum / count : null; - } - - /** - * Returns a single value. - * Note: The aggregation of a zero number of rows returns a null value for - * all aggregation types except from count. The type of Null value is numeric - * for sum and average and identical to its column values for min and max. - * - * @param type The type of aggregation requested. - * - * @return The requested value. - */ - public Value getValue(AggregationType type) { - Value v; - switch (type) { - case AVG: - v = (count != 0) ? new NumberValue(getAverage()) : NumberValue.getNullValue(); - break; - case COUNT: - v = new NumberValue(count); - break; - case MAX: - v = max; - // If there are zero rows replace with the same type null value. - if (count == 0) { - v = Value.getNullValueFromValueType(v.getType()); - } - break; - case MIN: - v = min; - // If there are zero rows replace with the same type null value. - if (count == 0) { - v = Value.getNullValueFromValueType(v.getType()); - } - break; - case SUM: - v = (count != 0) ? new NumberValue(getSum()) : NumberValue.getNullValue(); - break; - default: - throw new RuntimeException("Invalid AggregationType"); - } - return v; - } -} diff --git a/src/main/java/com/google/visualization/datasource/query/parser/GenericsHelper.java b/src/main/java/com/google/visualization/datasource/query/parser/GenericsHelper.java deleted file mode 100755 index 0fc0008..0000000 --- a/src/main/java/com/google/visualization/datasource/query/parser/GenericsHelper.java +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query.parser; - -import com.google.common.collect.Lists; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - - -/** - * Helper functions to assist the generated parser to deal with generic types. Unfortunately, - * javacc is not good at handling generic types, such as List, inside - * the .jj file. One solution is to use ArrayLists in the .jj file and then convert them - * using this class. This class uses unsafe operations, which is unavoidable. - * - * @author Yonatan B.Y. - */ -/* package */ class GenericsHelper { - private GenericsHelper() - {} - - /** - * Transforms, in an unsafe way, a typed List from a raw ArrayList. - * - * @param list The ArrayList to transform. - * - * @return The new List containing all the elements in list. - */ - /* package */ static List makeTypedList(ArrayList list) { - List result = Lists.newArrayListWithExpectedSize(list.size()); - for (T obj : list) { - result.add(obj); - } - return result; - } - - /** - * Transforms a typed List from a raw array. - * - * @param array The array to transform. - * - * @return The new List containing all the elements in array. - */ - /* package */ static List makeAbstractColumnList(T[] array) { - List result = Lists.newArrayListWithExpectedSize(array.length); - result.addAll(Arrays.asList(array)); - return result; - } -} diff --git a/src/main/java/com/google/visualization/datasource/query/parser/ParserUtils.java b/src/main/java/com/google/visualization/datasource/query/parser/ParserUtils.java deleted file mode 100755 index d0c53be..0000000 --- a/src/main/java/com/google/visualization/datasource/query/parser/ParserUtils.java +++ /dev/null @@ -1,214 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query.parser; - -import com.google.visualization.datasource.base.InvalidQueryException; -import com.google.visualization.datasource.datatable.value.DateTimeValue; -import com.google.visualization.datasource.datatable.value.DateValue; -import com.google.visualization.datasource.datatable.value.TimeOfDayValue; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -/** - * A utility class for the QueryParser. The functions here are called from the .jj file. - * - * Note on errors: Since this class handles a user generated query, all errors detected cause both - * logging, and an exception that is thrown to the user. - * - * @author Yonatan B.Y. - */ -/* package */ final class ParserUtils { - - /** - * Log. - */ - private static final Log log = LogFactory.getLog(ParserUtils.class.getName()); - - /** - * The message that should be in the exception thrown when parsing an invalid - * date string, parameterized by the erroneous string itself. - */ - private static final String dateMessage = "Invalid date literal [%1$s]. " - + "Date literals should be of form yyyy-MM-dd."; - - /** - * The message that should be in the exception thrown when parsing an invalid - * timeofday string, parameterized by the erroneous string itself. - */ - private static final String timeOfDayMessage = "Invalid timeofday " - + "literal [%1$s]. Timeofday literals should be of form HH:mm:ss[.SSS]"; - - /** - * The message that should be in the exception thrown when parsing an invalid - * datetime string, parameterized by the erroneous string itself. - */ - private static final String dateTimeMessage = - "Invalid datetime literal [%1$s]. Datetime literals should " - + " be of form yyyy-MM-dd HH:mm:ss[.SSS]"; - - /** - * Parses a string into a date value, for the query parser. The dates parsed are always in the - * format: yyyy-MM-dd. - * - * @param s The string to parse. - * - * @return The parsed date. - * - * @throws InvalidQueryException If the string is not parse-able as a date of format yyyy-MM-dd. - */ - public static DateValue stringToDate(String s) throws InvalidQueryException { - String[] split = s.split("-"); - if (split.length != 3) { - log.error(String.format(dateMessage, s)); - throw new InvalidQueryException(String.format(dateMessage, s)); - } - try { - int year = Integer.parseInt(split[0]); - int month = Integer.parseInt(split[1]); - month--; // normalize 1-12 to 0-11. - int day = Integer.parseInt(split[2]); - return new DateValue(year, month, day); - } catch (NumberFormatException e) { - log.error(String.format(dateMessage, s)); - throw new InvalidQueryException(String.format(dateMessage, s)); - } catch (IllegalArgumentException e) { - log.error(String.format(dateMessage, s)); - throw new InvalidQueryException(String.format(dateMessage, s)); - } - } - - /** - * Parses a string into a time-of-day value, for the query parser. The values parsed are always - * in the format: HH:mm:ss[.SSS]. - * - * @param s The string to parse. - * - * @return The parsed time-of-day. - * - * @throws InvalidQueryException If the string can not be parsed into a time-of-day of format - * HH:mm:ss[.SSS]. - */ - public static TimeOfDayValue stringToTimeOfDay(String s) - throws InvalidQueryException { - String[] split = s.split(":"); - if (split.length != 3) { - log.error(String.format(timeOfDayMessage, s)); - throw new InvalidQueryException(String.format(timeOfDayMessage, s)); - } - try { - int hour = Integer.parseInt(split[0]); - int minute = Integer.parseInt(split[1]); - int second; - if (split[2].contains(".")) { - String[] secondMilliSplit = split[2].split("."); - if (secondMilliSplit.length != 2) { - log.error(String.format(timeOfDayMessage, s)); - throw new InvalidQueryException(String.format(timeOfDayMessage, s)); - } - second = Integer.parseInt(secondMilliSplit[0]); - int milli = Integer.parseInt(secondMilliSplit[1]); - return new TimeOfDayValue(hour, minute, second, milli); - } else { - second = Integer.parseInt(split[2]); - return new TimeOfDayValue(hour, minute, second); - } - } catch (NumberFormatException e) { - log.error(String.format(timeOfDayMessage, s)); - throw new InvalidQueryException(String.format(timeOfDayMessage, s)); - } catch (IllegalArgumentException e) { - log.error(String.format(timeOfDayMessage, s)); - throw new InvalidQueryException(String.format(timeOfDayMessage, s)); - } - } - - /** - * Parses a string into a date-time value, for the query parser. The values parsed are always - * in the format: yyyy-MM-dd HH:mm:ss[.SSS]. - * - * @param s The string to parse. - * - * @return The parsed date-time - * - * @throws InvalidQueryException If the string can not be parsed into a date-time of format - * yyyy-MM-dd HH:mm:ss[.SSS]. - */ - public static DateTimeValue stringToDatetime(String s) - throws InvalidQueryException { - String[] mainSplit = s.split(" "); - if (mainSplit.length != 2) { - log.error(String.format(dateTimeMessage, s)); - throw new InvalidQueryException(String.format(dateTimeMessage, s)); - } - String[] dateSplit = mainSplit[0].split("-"); - String[] timeSplit = mainSplit[1].split(":"); - if ((dateSplit.length != 3) || (timeSplit.length != 3)) { - log.error(String.format(dateTimeMessage, s)); - throw new InvalidQueryException(String.format(dateTimeMessage, s)); - } - try { - int year = Integer.parseInt(dateSplit[0]); - int month = Integer.parseInt(dateSplit[1]); - month--; // normalize 1-12 to 0-11. - int day = Integer.parseInt(dateSplit[2]); - int hour = Integer.parseInt(timeSplit[0]); - int minute = Integer.parseInt(timeSplit[1]); - int second; - int milli = 0; - if (timeSplit[2].contains(".")) { - String[] secondMilliSplit = timeSplit[2].split("\\."); - if (secondMilliSplit.length != 2) { - log.error(String.format(dateTimeMessage, s)); - throw new InvalidQueryException(String.format(dateTimeMessage, s)); - } - second = Integer.parseInt(secondMilliSplit[0]); - milli = Integer.parseInt(secondMilliSplit[1]); - } else { - second = Integer.parseInt(timeSplit[2]); - } - return new DateTimeValue(year, month, day, hour, minute, second, milli); - } catch (NumberFormatException e) { - log.error(String.format(dateTimeMessage, s)); - throw new InvalidQueryException(String.format(dateTimeMessage, s)); - } catch (IllegalArgumentException e) { - log.error(String.format(dateTimeMessage, s)); - throw new InvalidQueryException(String.format(dateTimeMessage, s)); - } - } - - - /** - * Strips the first and last characters from a string. - * Throws a runtime exception if the string is less than 2 characters long. Used for stripping - * quotes (whether single, double, or back-quotes) from, for example, "foo", 'bar', and `baz`. - * - * @param s The string from which to strip the quotes. - * - * @return The stripped string. - */ - public static String stripQuotes(String s) { - if (s.length() < 2) { - throw new RuntimeException("String is of length < 2 on call to " - + "stripQuotes: " + s); - } - return s.substring(1, s.length() - 1); - } - - /** - * Private constructor, to prevent instantiation. - */ - private ParserUtils() { - } -} diff --git a/src/main/java/com/google/visualization/datasource/query/parser/QueryBuilder.java b/src/main/java/com/google/visualization/datasource/query/parser/QueryBuilder.java deleted file mode 100755 index 7ccf8a3..0000000 --- a/src/main/java/com/google/visualization/datasource/query/parser/QueryBuilder.java +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query.parser; - -import com.google.visualization.datasource.base.InvalidQueryException; -import com.google.visualization.datasource.base.MessagesEnum; -import com.google.visualization.datasource.query.Query; - -import com.ibm.icu.util.ULocale; - -import org.apache.commons.lang.StringUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - - -/** - * A singleton class that can parse a user query string, i.e., accept a string such as - * "SELECT dept, max(salary) GROUP BY dept" and return a Query object. This class basically - * wraps the QueryParser class that is auto-generated from the QueryParser.jj specification. - * - * @author Hillel M. - */ -public class QueryBuilder { - - /** - * Log. - */ - private static final Log log = LogFactory.getLog(QueryBuilder.class.getName()); - - /** - * A singleton instance of this class. - */ - private static final QueryBuilder SINGLETON = new QueryBuilder(); - - /** - * Returns the singleton instance of this class. - * - * @return The singleton query builder. - */ - public static QueryBuilder getInstance() { - return SINGLETON; - } - - /** - * Private constructor, to prevent instantiation other than that of the singleton instance. - */ - private QueryBuilder() { - } - - /** - * Parses a user query into a Query object. - * - * @param tqValue The user query string. - * - * @return The parsed Query object. - * - * @throws InvalidQueryException Thrown if the query is invalid. - */ - public Query parseQuery(String tqValue) throws InvalidQueryException { - return parseQuery(tqValue, null); - } - - /** - * Parses a user query into a Query object. - * - * @param tqValue The user query string. - * @param ulocale The user locale. - * - * @return The parsed Query object. - * - * @throws InvalidQueryException Thrown if the query is invalid. - */ - public Query parseQuery(String tqValue, ULocale ulocale) throws InvalidQueryException { - Query query; - if (StringUtils.isEmpty(tqValue)) { - query = new Query(); - } else { - try { - query = QueryParser.parseString(tqValue); - } catch (ParseException ex) { - String messageToUserAndLog = ex.getMessage(); - log.error("Parsing error: " + messageToUserAndLog); - throw new InvalidQueryException(MessagesEnum.PARSE_ERROR.getMessageWithArgs(ulocale, - messageToUserAndLog)); - } - query.setLocaleForUserMessages(ulocale); - query.validate(); - } - return query; - } -} diff --git a/src/main/java/com/google/visualization/datasource/query/parser/QueryOptionEnum.java b/src/main/java/com/google/visualization/datasource/query/parser/QueryOptionEnum.java deleted file mode 100755 index 85c675f..0000000 --- a/src/main/java/com/google/visualization/datasource/query/parser/QueryOptionEnum.java +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query.parser; - -import com.google.visualization.datasource.query.QueryOptions; - -/** - * Helper enum for the auto-generated parser. Holds a single query option (a single element of the - * OPTIONS clause). This is used by the parser, i.e., referenced from the QueryParser.jj file. - * It is needed because queryOptions uses boolean setX() functions, and does not have a datatype - * to hold a single value, and such a datatype is needed for convenience of parsing purposes in - * the .jj parser. You can use the setInQueryOptions() method of this enum, to set the option to - * true in a QueryOptions instance. - * - * @author Yonatan B.Y. - */ -/* package */ enum QueryOptionEnum { - NO_VALUES, - NO_FORMAT; - - /** - * Sets this option to true in the given QueryOptions, leaving its other - * options intact. - * - * @param queryOptions The QueryOptions in which to set the option to true. - */ - public void setInQueryOptions(QueryOptions queryOptions) { - switch (this) { - case NO_VALUES: - queryOptions.setNoValues(true); - break; - case NO_FORMAT: - queryOptions.setNoFormat(true); - break; - } - } -} diff --git a/src/main/java/com/google/visualization/datasource/query/parser/QueryParser.jj b/src/main/java/com/google/visualization/datasource/query/parser/QueryParser.jj deleted file mode 100644 index a894666..0000000 --- a/src/main/java/com/google/visualization/datasource/query/parser/QueryParser.jj +++ /dev/null @@ -1,827 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * Specification for query parser for javacc. - * - * @author Yonatan B.Y. - */ - -options { - STATIC=false; - JAVA_UNICODE_ESCAPE=true; -} - -PARSER_BEGIN(QueryParser) - -package com.google.visualization.datasource.query.parser; - -import com.google.visualization.datasource.base.InvalidQueryException; -import com.google.visualization.datasource.datatable.value.BooleanValue; -import com.google.visualization.datasource.datatable.value.NumberValue; -import com.google.visualization.datasource.datatable.value.TextValue; -import com.google.visualization.datasource.datatable.value.Value; -import com.google.visualization.datasource.query.AbstractColumn; -import com.google.visualization.datasource.query.AggregationColumn; -import com.google.visualization.datasource.query.AggregationType; -import com.google.visualization.datasource.query.ColumnColumnFilter; -import com.google.visualization.datasource.query.ColumnIsNullFilter; -import com.google.visualization.datasource.query.ColumnValueFilter; -import com.google.visualization.datasource.query.ComparisonFilter; -import com.google.visualization.datasource.query.CompoundFilter; -import com.google.visualization.datasource.query.NegationFilter; -import com.google.visualization.datasource.query.Query; -import com.google.visualization.datasource.query.QueryFilter; -import com.google.visualization.datasource.query.QueryFormat; -import com.google.visualization.datasource.query.QueryGroup; -import com.google.visualization.datasource.query.QueryLabels; -import com.google.visualization.datasource.query.QueryOptions; -import com.google.visualization.datasource.query.QueryPivot; -import com.google.visualization.datasource.query.QuerySelection; -import com.google.visualization.datasource.query.QuerySort; -import com.google.visualization.datasource.query.ScalarFunctionColumn; -import com.google.visualization.datasource.query.SortOrder; -import com.google.visualization.datasource.query.SimpleColumn; -import com.google.visualization.datasource.query.scalarfunction.Constant; -import com.google.visualization.datasource.query.scalarfunction.CurrentDateTime; -import com.google.visualization.datasource.query.scalarfunction.DateDiff; -import com.google.visualization.datasource.query.scalarfunction.Difference; -import com.google.visualization.datasource.query.scalarfunction.Lower; -import com.google.visualization.datasource.query.scalarfunction.Modulo; -import com.google.visualization.datasource.query.scalarfunction.Product; -import com.google.visualization.datasource.query.scalarfunction.Quotient; -import com.google.visualization.datasource.query.scalarfunction.ScalarFunction; -import com.google.visualization.datasource.query.scalarfunction.Sum; -import com.google.visualization.datasource.query.scalarfunction.ToDate; -import com.google.visualization.datasource.query.scalarfunction.TimeComponentExtractor; -import com.google.visualization.datasource.query.scalarfunction.Upper; - -import java.io.BufferedReader; -import java.io.Reader; -import java.io.StringReader; -import java.util.ArrayList; - -/** - * Query parser. AUTOGENERATED, see QueryParser.jj - */ -public class QueryParser { - - public static Query parseString(String queryString) - throws ParseException, InvalidQueryException { - Reader r = new BufferedReader(new StringReader(queryString)); - QueryParser parser = new QueryParser(r); - Query query = parser.queryStatement(); - return query; - } -} - - - -PARSER_END(QueryParser) - -SKIP: -{ - " " - | "\t" - | "\n" - | "\r" -} - -// keywords that cannot be used as column ids -TOKEN[IGNORE_CASE]: -{ - - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | -} - -// keywords that can be used as column ids -TOKEN[IGNORE_CASE]: -{ - - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | -} - -// literals -TOKEN: -{ - ( )* > - | )+ > // For use in LIMIT, OFFSET, ... - | )+ "." ()* ) - | ( "." ()+ ) ) - > - | <#ALPHANUMERIC: | > - | <#DIGIT: ["0"-"9"] > - | <#LETTER_OR_UNDERSCORE: ["a"-"z","A"-"Z","_"] > - | - | -} - -// operators -TOKEN: -{ - - | - | - | "> - | - | "> - | ="> - | - | - | - | - | -} - -// The entire query -Query queryStatement() throws InvalidQueryException : -{ - Query query = new Query(); -} -{ - ( - [ selectClause(query) ] - [ whereClause(query) ] - [ groupByClause(query) ] - [ pivotClause(query) ] - [ orderByClause(query) ] - [ skippingClause(query) ] - [ limitClause(query) ] - [ offsetClause(query) ] - [ labelClause(query) ] - [ formatClause(query) ] - [ optionsClause(query) ] - - ) - {return query; } -} - -// The select clause (e.g., SELECT c1, c2) -void selectClause(Query query) throws InvalidQueryException : -{ - QuerySelection selection = new QuerySelection(); - AbstractColumn column; -} -{ - - ( (column = abstractColumnDescriptor() - { selection.addColumn(column); } - ( column = abstractColumnDescriptor() - { selection.addColumn(column); } )* - { query.setSelection(selection); } ) - | ) // do nothing -} - -// The where clause (e.g., WHERE (c1 > 3) AND (NOT(c3 <= c4))) -void whereClause(Query query) throws InvalidQueryException : -{ - QueryFilter filter; -} -{ - - filter = logicalExpression() - { query.setFilter(filter); } -} - -// The group by clause (e.g. GROUP BY c1, c2) -void groupByClause(Query query) throws InvalidQueryException : -{ - QueryGroup group = new QueryGroup(); - AbstractColumn column; -} -{ - - - column = abstractColumnDescriptor() - { group.addColumn(column); } - ( column = abstractColumnDescriptor() - { group.addColumn(column); } )* - { query.setGroup(group); } -} - -// The pivot clause (e.g. PIVOT c1, c2) -void pivotClause(Query query) throws InvalidQueryException : -{ - QueryPivot pivot = new QueryPivot(); - AbstractColumn column; -} -{ - - column = abstractColumnDescriptor() - { pivot.addColumn(column); } - ( column = abstractColumnDescriptor() - { pivot.addColumn(column); } )* - { query.setPivot(pivot); } -} - -// The order by clause (e.g., ORDER BY c1, c2 ASC, c3 DESC) -void orderByClause(Query query) throws InvalidQueryException : -{ - QuerySort sort = new QuerySort(); - AbstractColumn column; - SortOrder order; -} -{ - - - column = abstractColumnDescriptor() - order = sortOrder() - { sort.addSort(column, order); } - ( column = abstractColumnDescriptor() order = sortOrder() - { sort.addSort(column, order); } )* - { query.setSort(sort); } -} - -// The skipping clause (e.g., SKIPPING 10) -void skippingClause(Query query) throws InvalidQueryException : -{ - int skipping; -} -{ - - skipping = integerLiteral() - { query.setRowSkipping(skipping); } -} - -// The limit clause (e.g., LIMIT 100) -void limitClause(Query query) throws InvalidQueryException : -{ - int limit; -} -{ - - limit = integerLiteral() - { query.setRowLimit(limit); } -} - -// The offset clause (e.g., OFFSET 100) -void offsetClause(Query query) throws InvalidQueryException : -{ - int offset; -} -{ - - offset = integerLiteral() - { query.setRowOffset(offset); } -} - -// The label clause (e.g., LABEL c1 "Department", c3 "Salary") -void labelClause(Query query) throws InvalidQueryException : -{ - QueryLabels labels = new QueryLabels(); - AbstractColumn column; - String label; -} -{ - - column = abstractColumnDescriptor() - label = stringLiteral() - { labels.addLabel(column, label); } - ( column = abstractColumnDescriptor() label = stringLiteral() - { labels.addLabel(column, label); } )* - { query.setLabels(labels); } -} - -// The format clause (e.g., FORMAT c1 "#", c3 "dd-MM-YYYY") -void formatClause(Query query) throws InvalidQueryException : -{ - QueryFormat formats = new QueryFormat(); - AbstractColumn column; - String pattern; -} -{ - - column = abstractColumnDescriptor() - pattern = stringLiteral() - { formats.addPattern(column, pattern); } - ( column = abstractColumnDescriptor() pattern = stringLiteral() - { formats.addPattern(column, pattern); } )* - { query.setUserFormatOptions(formats); } -} - -// The options clause (e.g., OPTIONS no_format) -void optionsClause(Query query) : -{ - QueryOptions queryOptions = new QueryOptions(); - QueryOptionEnum optionEnum; -} -{ - - ( - optionEnum = queryOption() - { optionEnum.setInQueryOptions(queryOptions); } - )+ - { query.setOptions(queryOptions); } -} - -// a logical expression, e.g., c1 > c2 or not c1 < 3 and (c3 >= c4) -// currently implemented as simply a call to possibleOrExpression -QueryFilter logicalExpression() throws InvalidQueryException : -{ - QueryFilter filter; -} -{ - filter = possibleOrExpression() - { return filter; } -} - -// A possible OR expression, i.e., an OR of several possible AND expressions. -// It is "possible" because it can also match a single expression without any -// ORs and then it is just returned as is. -QueryFilter possibleOrExpression() throws InvalidQueryException : -{ - ArrayList subFilters = new ArrayList(); - QueryFilter filter; -} -{ - filter = possibleAndExpression() - { subFilters.add(filter); } - ( filter = possibleAndExpression() { subFilters.add(filter); } )* - { - if (subFilters.size() == 1) { - return (QueryFilter)subFilters.get(0); - } else { - return new CompoundFilter( - CompoundFilter.LogicalOperator.OR, - GenericsHelper.makeTypedList(subFilters)); - } - } -} - -// A possible AND expression, i.e., an AND of several possible NOT expressions. -// It is "possible" because it can also match a single expression without any -// ANDs and then it is just returned as is. -QueryFilter possibleAndExpression() throws InvalidQueryException : -{ - ArrayList subFilters = new ArrayList(); - QueryFilter filter; -} -{ - filter = possibleNotExpression() - { subFilters.add(filter); } - ( filter = possibleNotExpression() { subFilters.add(filter); } )* - { - if (subFilters.size() == 1) { - return (QueryFilter)subFilters.get(0); - } else { - return new CompoundFilter( - CompoundFilter.LogicalOperator.AND, - GenericsHelper.makeTypedList(subFilters)); - } - } -} - -// A primary expression, with an optional NOT -QueryFilter possibleNotExpression() throws InvalidQueryException : -{ - QueryFilter subFilter; - QueryFilter filter; -} -{ - - ( ( subFilter = primaryExpression() - { filter = new NegationFilter(subFilter); }) - | (subFilter = primaryExpression() - { filter = subFilter; }) ) - { return filter; } -} - -// A primary expression, i.e., a binary comparison operator between two operands -// or an expression in parentheses. -QueryFilter primaryExpression() throws InvalidQueryException : -{ - QueryFilter filter; -} -{ - ( LOOKAHEAD(primitiveFilter()) (filter = primitiveFilter()) - | ( filter = logicalExpression() ) ) - { return filter; } -} - -// A comparison expression, i.e., a binary comparison operator between two -// operands that may be literals or column ids. Or an IS NULL or IS NOT NULL. -QueryFilter primitiveFilter() throws InvalidQueryException : -{ - QueryFilter filter; - AbstractColumn col1; - AbstractColumn col2; - ComparisonFilter.Operator op; - Value val; -} -{ - ( LOOKAHEAD(literal()) ( val = literal() op = comparisonOperator() - col1 = abstractColumnDescriptor() - { filter = new ColumnValueFilter(col1, val, op, true); } ) - | ( col1 = abstractColumnDescriptor() - ( ( - ( ( - { filter = new ColumnIsNullFilter(col1); } ) - | ( - { filter = new NegationFilter(new ColumnIsNullFilter(col1)); } - ) - ) - ) - | (op = comparisonOperator() - ( LOOKAHEAD(literal()) ( val = literal() - { filter = new ColumnValueFilter(col1, val, op, false); } ) - | ( col2 = abstractColumnDescriptor() - { filter = new ColumnColumnFilter(col1, col2, op); } - ) - ) - ) - ) - ) - ) - { return filter; } -} - -// A comparison operator, i.e., one of <, >, =, !=, <>, <=, >= and maybe others. -ComparisonFilter.Operator comparisonOperator() : -{ - ComparisonFilter.Operator op; -} -{ - ( ( { op = ComparisonFilter.Operator.EQ; }) - | ( { op = ComparisonFilter.Operator.NE; }) - | ( { op = ComparisonFilter.Operator.LT; }) - | ( { op = ComparisonFilter.Operator.LE; }) - | ( { op = ComparisonFilter.Operator.GT; }) - | ( { op = ComparisonFilter.Operator.GE; }) - | ( { op = ComparisonFilter.Operator.CONTAINS; }) - | ( { op = ComparisonFilter.Operator.STARTS_WITH; }) - | ( { op = ComparisonFilter.Operator.ENDS_WITH; }) - | ( { op = ComparisonFilter.Operator.MATCHES; }) - | ( { op = ComparisonFilter.Operator.LIKE; }) ) - { return op; } -} - -// A literal. Corresponds to a value on the server, i.e., can be of one of the -// following types: string, number, boolean, date, timeOfDay, dateTime. -Value literal() throws InvalidQueryException : -{ - Value val; - String str; - double num; - boolean bool; - String dateStr; // Used for date, timeofday and timestamp. -} -{ - ( (str = stringLiteral() { val = new TextValue(str); }) - | (num = decimalLiteral() { val = new NumberValue(num); }) - | (bool = booleanLiteral() { val = BooleanValue.getInstance(bool); }) - | ( dateStr = stringLiteral() - { val = ParserUtils.stringToDate(dateStr); }) - | ( dateStr = stringLiteral() - { val = ParserUtils.stringToTimeOfDay(dateStr); }) - | (( | ) dateStr = stringLiteral() - { val = ParserUtils.stringToDatetime(dateStr); }) ) - { return val; } -} - -// A single query option (e.g., no_format) -QueryOptionEnum queryOption() : -{ - QueryOptionEnum result = null; -} -{ - ( ( { result = QueryOptionEnum.NO_VALUES; }) - | ( { result = QueryOptionEnum.NO_FORMAT; }) ) - { return result; } -} - -// An abstract column descriptor, i.e., either a column id, an aggregation -// function name followed by parentheses with column id (e.g., max(c1)) or a -// scalar function followed by parentheses with abstract columns -// (e.g., curr_time(), year(d1), year(sum(c1)), month(c2)), .... -AbstractColumn abstractColumnDescriptor() throws InvalidQueryException : -{ - AbstractColumn column; - AbstractColumn result = null; -} -{ - ( LOOKAHEAD(2) ( column = arithmeticExpression() { result = column; } ) - | ( column = atomicAbstractColumnDescriptor() { result = column; } ) ) - { return result; } -} - -// An atomic abstract column descriptor, i.e., the same as abstract column, -// except it does not include arithmetic expressions like: c1+c2/c3*(c4+c5). -AbstractColumn atomicAbstractColumnDescriptor() throws InvalidQueryException : -{ - AggregationType aggregationType; - ScalarFunction scalarFunction; - String columnId; - AbstractColumn column; - ArrayList columns = new ArrayList(); - AbstractColumn result = null; - Value value; -} -{ - // The lookahead is to tell between min and min(c1). - ( LOOKAHEAD(2) (aggregationType = aggregationFunction() - columnId = columnId() - { result = new AggregationColumn(new SimpleColumn(columnId), - aggregationType); } ) - | LOOKAHEAD(2) ( scalarFunction = scalarFunction() - (column = abstractColumnDescriptor() { columns.add(column); })? - ( column = abstractColumnDescriptor() - { columns.add(column); })* - { result = new ScalarFunctionColumn( - GenericsHelper.makeTypedList(columns), scalarFunction); } ) - | ( column = abstractColumnDescriptor() - { result = column; } ) - | ( value = literal() - { result = new ScalarFunctionColumn(new ArrayList(), - new Constant(value)); } ) - | ( columnId = columnId() { result = new SimpleColumn(columnId); } ) ) - { return result; } -} - -// An arithmetic expression, e.g., c1 + c2 / c1 * 3 - (c3 + c4). -AbstractColumn arithmeticExpression() throws InvalidQueryException : -{ - AbstractColumn column; -} -{ - column = possibleSecondOrderArithmeticExpression() - { return column; } -} - -// A possible sum or subtraction expression of possible multiplication or division expressions. -// It is "possible" because it can also match a single expression without any -// multiplications and divisions, and then it is just returned as is. -AbstractColumn possibleSecondOrderArithmeticExpression() throws - InvalidQueryException : -{ - AbstractColumn column; - AbstractColumn column1; -} -{ - column = possibleFirstOrderArithmeticExpression() - ( - ( ( column1 = possibleFirstOrderArithmeticExpression() { - column = - new ScalarFunctionColumn(GenericsHelper.makeAbstractColumnList( - new AbstractColumn[] {column, column1}), Sum.getInstance() );} ) - | ( column1 = possibleFirstOrderArithmeticExpression() { - column = - new ScalarFunctionColumn(GenericsHelper.makeAbstractColumnList( - new AbstractColumn[]{column, column1}), - Difference.getInstance()); } ) ) )* - { return column; } -} - -// A possible multiplication division or modulo expression of atomic abstract column descriptors. -AbstractColumn possibleFirstOrderArithmeticExpression() throws - InvalidQueryException : -{ - AbstractColumn column; - AbstractColumn column1; -} -{ - column = atomicAbstractColumnDescriptor() - ( - ( ( column1 = atomicAbstractColumnDescriptor() { - column = - new ScalarFunctionColumn(GenericsHelper.makeAbstractColumnList( - new AbstractColumn[] {column, column1}), Product.getInstance() );} ) - | ( column1 = atomicAbstractColumnDescriptor() { - column = - new ScalarFunctionColumn(GenericsHelper.makeAbstractColumnList( - new AbstractColumn[]{column, column1}), - Quotient.getInstance()); } ) - | ( column1 = atomicAbstractColumnDescriptor() { - column = - new ScalarFunctionColumn(GenericsHelper.makeAbstractColumnList( - new AbstractColumn[]{column, column1}), - Modulo.getInstance()); } ) ) )* - { return column; } -} - -// An aggregation function, e.g., "max", "avg", ... -AggregationType aggregationFunction() : -{ - AggregationType result = null; -} -{ - ( ( { result = AggregationType.MIN; } ) - | ( { result = AggregationType.MAX; } ) - | ( { result = AggregationType.COUNT; } ) - | ( { result = AggregationType.AVG; } ) - | ( { result = AggregationType.SUM; } ) ) - { return result; } -} - -// A scalar function, e.g., "datediff", "upper". -ScalarFunction scalarFunction() : -{ - ScalarFunction result = null; -} -{ - ( ( { result = TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.YEAR); } ) - | ( { result = TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.MONTH); } ) - | ( { result = TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.DAY); } ) - | ( { result = TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.HOUR); } ) - | ( { result = TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.MINUTE); } ) - | ( { result = TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.SECOND); } ) - | ( { result = TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.MILLISECOND); } ) - | ( { result = CurrentDateTime.getInstance(); } ) - | ( { result = DateDiff.getInstance(); } ) - | ( { result = Lower.getInstance(); } ) - | ( { result = Upper.getInstance(); } ) - | ( { result = TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.QUARTER); } ) - | ( { result = TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.DAY_OF_WEEK); } ) - | ( { result = ToDate.getInstance(); } ) ) - { return result; } -} - -// A single column id. This may be a simple id (e.g. c1), a quoted id -// (e.g. `my column`) or a non-reserved keyword (e.g. max) -String columnId() : -{ - Token t; - String result = null; -} -{ - ( (t = { result = t.image; }) - | (t = { result = ParserUtils.stripQuotes(t.image); }) - | (result = nonReservedKeyword()) ) - { return result; } -} - -// A non-reserved keyword (e.g. min) -String nonReservedKeyword() : -{ - Token t; -} -{ - ( t = - | t = - | t = - | t = - | t = - | t = - | t = - | t = - | t = - | t = - | t = - | t = - | t = - | t = - | t = - | t = - | t = - | t = - | t = - | t = - | t = - | t = - | t = - | t = - | t = - | t = - | t = - | t = - | t = ) - { return t.image; } -} - -// A sort order (e.g., DESC). This can match the empty option and returns -// ASCENDING in that case. -SortOrder sortOrder() : -{} -{ - ( { return SortOrder.ASCENDING; }) - | ( { return SortOrder.DESCENDING; }) - | ({ return SortOrder.ASCENDING; }) // empty option -} - -// An integer literal (like 4, 0, -3) -int integerLiteral() : -{ - Token t1; - Token t2; - String s; -} -{ - ( (t1 = { s = t1.image; } ) - | (t1 = t2 = { s = t1.image + t2.image; } ) ) - { return Integer.parseInt(s); } -} - -// A String literal, returned without its surrounding quotes or double quotes. -String stringLiteral() : -{ - Token t; -} -{ - t = - { return ParserUtils.stripQuotes(t.image); } -} - -// A decimal (numeric, of type double) literal. -double decimalLiteral() : -{ - Token t1; - Token t2; - String s; -} -{ - ( (t1 = { s = t1.image; } ) - | (t1 = {s = t1.image; } ) - | (t1 = ( (t2 = ) | (t2 = ) ) - { s = t1.image + t2.image; } ) ) - { return Double.parseDouble(s); } -} - -// A boolean literal, either true or false. -boolean booleanLiteral() : -{ - boolean b; -} -{ - ( ( { b = true; }) - | ( { b = false; }) ) - { return b; } -} - -// This is to avoid TokenMgrErrors. This will cause a regular parsing exception -// to be thrown when an unexpected char is encountered. -< * > TOKEN : -{ - < UNEXPECTED_CHAR : ~[] > -} diff --git a/src/main/java/com/google/visualization/datasource/query/scalarfunction/Constant.java b/src/main/java/com/google/visualization/datasource/query/scalarfunction/Constant.java deleted file mode 100755 index 7605b56..0000000 --- a/src/main/java/com/google/visualization/datasource/query/scalarfunction/Constant.java +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query.scalarfunction; - -import com.google.visualization.datasource.base.InvalidQueryException; -import com.google.visualization.datasource.datatable.value.Value; -import com.google.visualization.datasource.datatable.value.ValueType; - -import java.util.List; - -/** - * A constant function, i.e., a 0-ary function that always returns the same value, given at - * construction time. The value can be of any supported {@link ValueType}. - * - * @author Liron L. - */ -public class Constant implements ScalarFunction { - - /** - * The value of this constant. - */ - private Value value; - - /** - * Constructs a new constant function that always returns the given value. - * - * @param value The value to constantly return. - */ - public Constant(Value value) { - this.value = value; - } - - /** - * {@inheritDoc} - */ - public String getFunctionName() { - return value.toQueryString(); - } - - /** - * Executes the scalar function constant(). The values parameter is ignored. - * Returns the value supplied at construction time. - * - * @param values Ignored. - * - * @return The value supplied at construction time. - */ - public Value evaluate(List values) { - return value; - } - - /** - * Returns the return type of the function. This matches the type of the value - * supplied at construction time. The types parameter is ignored. - * - * @param types Ignored. - * - * @return The return type of this function. - */ - public ValueType getReturnType(List types) { - return value.getType(); - } - - /** - * Validates that there are no parameters given for the function. Throws a - * ScalarFunctionException otherwise. - * - * @param types A list with parameters types. Should be empty for this type of function. - * - * @throws InvalidQueryException Thrown if the parameters are invalid. - */ - public void validateParameters(List types) - throws InvalidQueryException { - if (types.size() != 0) { - throw new InvalidQueryException("The constant function should not get " - + "any parameters"); - } - } - - @Override - public boolean equals(Object o) { - if (o instanceof Constant) { - Constant other = (Constant) o; - return value.equals(other.value); - } - return false; - } - - @Override - public int hashCode() { - return (value == null) ? 0 : value.hashCode(); - } - - /** - * {@inheritDoc} - */ - public String toQueryString(List argumentsQueryStrings) { - return value.toQueryString(); - } -} diff --git a/src/main/java/com/google/visualization/datasource/query/scalarfunction/CurrentDateTime.java b/src/main/java/com/google/visualization/datasource/query/scalarfunction/CurrentDateTime.java deleted file mode 100755 index 1131beb..0000000 --- a/src/main/java/com/google/visualization/datasource/query/scalarfunction/CurrentDateTime.java +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query.scalarfunction; - -import com.google.visualization.datasource.base.InvalidQueryException; -import com.google.visualization.datasource.datatable.value.DateTimeValue; -import com.google.visualization.datasource.datatable.value.Value; -import com.google.visualization.datasource.datatable.value.ValueType; - -import com.ibm.icu.util.GregorianCalendar; -import com.ibm.icu.util.TimeZone; - -import java.util.List; - -/** - * A 0-ary function that returns the current datetime. The return type is always DateTime. - * - * @author Liron L. - */ -public class CurrentDateTime implements ScalarFunction { - - /** - * The name of this function. - */ - private static final String FUNCTION_NAME = "now"; - - /** - * A singleton instance of this class. - */ - private static final CurrentDateTime INSTANCE = new CurrentDateTime(); - - /** - * Private constructor, to prevent instantiation other than by the singleton. - */ - private CurrentDateTime() {} - - /** - * Returns the singleton instance of this class. - * - * @return The singleton instance of this class. - */ - public static CurrentDateTime getInstance() { - return INSTANCE; - } - - /** - * {@inheritDoc} - */ - public String getFunctionName() { - return FUNCTION_NAME; - } - - /** - * Evaluates this scalar function. Returns a DateTime with the current time. - * - * @param values Ignored. - * - * @return A DateTime value with the current time. - */ - public Value evaluate(List values) { - return new DateTimeValue(new GregorianCalendar( - TimeZone.getTimeZone("GMT"))); - } - - /** - * Returns the return type of the function. In this case, DATETIME. - * - * @param types Ignored. - * - * @return The type of the returned value: DATETIME. - */ - public ValueType getReturnType(List types) { - return ValueType.DATETIME; - } - - /** - * Validates that there are no parameters given for the function. Throws a - * ScalarFunctionException otherwise. - * - * @param types A list with parameters types. Should be empty for this type of function. - * - * @throws InvalidQueryException Thrown if the parameters are invalid. - */ - public void validateParameters(List types) - throws InvalidQueryException { - if (types.size() != 0) { - throw new InvalidQueryException("The " + FUNCTION_NAME + " function should not get " - + "any parameters"); - } - } - - /** - * {@inheritDoc} - */ - public String toQueryString(List argumentsQueryStrings) { - return FUNCTION_NAME + "()"; - } -} diff --git a/src/main/java/com/google/visualization/datasource/query/scalarfunction/DateDiff.java b/src/main/java/com/google/visualization/datasource/query/scalarfunction/DateDiff.java deleted file mode 100755 index 0b16763..0000000 --- a/src/main/java/com/google/visualization/datasource/query/scalarfunction/DateDiff.java +++ /dev/null @@ -1,167 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query.scalarfunction; - -import com.google.visualization.datasource.base.InvalidQueryException; -import com.google.visualization.datasource.datatable.value.DateTimeValue; -import com.google.visualization.datasource.datatable.value.DateValue; -import com.google.visualization.datasource.datatable.value.NumberValue; -import com.google.visualization.datasource.datatable.value.Value; -import com.google.visualization.datasource.datatable.value.ValueType; -import com.ibm.icu.util.Calendar; -import com.ibm.icu.util.GregorianCalendar; -import com.ibm.icu.util.TimeZone; - -import java.util.Date; -import java.util.List; - -/** - * The binary scalar function datediff(). - * Returns the difference in days between two dates or date time values. - * - * @author Liron L. - */ -public class DateDiff implements ScalarFunction { - - /** - * The name of the function. - */ - private static final String FUNCTION_NAME = "dateDiff"; - - /** - * A singleton instance of this class. - */ - private static final DateDiff INSTANCE = new DateDiff(); - - /** - * A private constructor, to prevent instantiation other than by the singleton. - */ - private DateDiff() {} - - /** - * Returns the singleton instance of this class. - * - * @return The singleton instance of this class. - */ - public static DateDiff getInstance() { - return INSTANCE; - } - - /** - * {@inheritDoc} - */ - public String getFunctionName() { - return FUNCTION_NAME; - } - - /** - * Executes this scalar function on the given values. Returns values[0] - values[1] expressed - * as a number value denoting the number of days from one date to the other. Both values can be - * of type date or date-time. Only the date parts of date-time values are used in the calculation. - * Thus the returned number is always an integer. - * The method does not validate the parameters, the user must check the - * parameters before calling this method. - * - * @param values A list of values on which the scalar function will be performed. - * - * @return Value holding the difference, in whole days, between the two given Date/DateTime - * values, or a null value (of type number) if one of the values is null. - */ - public Value evaluate(List values) { - Value firstValue = values.get(0); - Value secondValue = values.get(1); - - // If one of the values is null, return a null number value. - if (firstValue.isNull() || secondValue.isNull()) { - return NumberValue.getNullValue(); - } - Date firstDate = getDateFromValue(firstValue); - Date secondDate = getDateFromValue(secondValue); - - GregorianCalendar calendar = - new GregorianCalendar(TimeZone.getTimeZone("GMT")); - calendar.setTime(secondDate); - return new NumberValue(calendar.fieldDifference(firstDate, Calendar.DATE)); - } - - /** - * Converts the given value to date. The value must be of type date or datetime. - * - * @param value The given value. - * - * @return Date object with the same value as the given value. - */ - private Date getDateFromValue(Value value) { - Calendar calendar; - if (value.getType() == ValueType.DATE) { - calendar = ((DateValue) value).getObjectToFormat(); - } else { // datetime - calendar = ((DateTimeValue) value).getObjectToFormat(); - } - return calendar.getTime(); - } - - /** - * Returns the return type of the function. In this case, NUMBER. The method - * does not validate the parameters, the user must check the parameters - * before calling this method. - * - * @param types A list of the types of the scalar function parameters. - * - * @return The type of the returned value: Number. - */ - public ValueType getReturnType(List types) { - return ValueType.NUMBER; - } - - /** - * Validates that there are only 2 parameters given for this function, and that their types are - * either DATE or DATETIME. Throws a ScalarFunctionException if the parameters are invalid. - * - * @param types A list with parameters types. - * - * @throws InvalidQueryException Thrown if the parameters are invalid. - */ - public void validateParameters(List types) throws InvalidQueryException { - if (types.size() != 2) { - throw new InvalidQueryException("Number of parameters for the dateDiff " - + "function is wrong: " + types.size()); - } else if ((!isDateOrDateTimeValue(types.get(0))) - || (!isDateOrDateTimeValue(types.get(1)))) { - throw new InvalidQueryException("Can't perform the function 'dateDiff' " - + "on values that are not a Date or a DateTime values"); - } - } - - /** - * Returns true if the given type is Date or DateTime. - * - * @param type The given type. - * - * @return True if the given type is Date or DateTime. - */ - private boolean isDateOrDateTimeValue(ValueType type) { - return ((type == ValueType.DATE) || (type == ValueType.DATETIME)); - } - - - /** - * {@inheritDoc} - */ - public String toQueryString(List argumentsQueryStrings) { - return FUNCTION_NAME + "(" + argumentsQueryStrings.get(0) + ", " + argumentsQueryStrings.get(1) - + ")"; - } -} diff --git a/src/main/java/com/google/visualization/datasource/query/scalarfunction/Difference.java b/src/main/java/com/google/visualization/datasource/query/scalarfunction/Difference.java deleted file mode 100755 index 87054f7..0000000 --- a/src/main/java/com/google/visualization/datasource/query/scalarfunction/Difference.java +++ /dev/null @@ -1,124 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query.scalarfunction; - -import com.google.visualization.datasource.base.InvalidQueryException; -import com.google.visualization.datasource.datatable.value.NumberValue; -import com.google.visualization.datasource.datatable.value.Value; -import com.google.visualization.datasource.datatable.value.ValueType; - - -import java.util.List; - -/** - * The binary scalar function difference(). - * Returns the difference between two number values. - * - * @author Liron L. - */ -public class Difference implements ScalarFunction { - - /** - * The name of this function. - */ - private static final String FUNCTION_NAME = "difference"; - - /** - * A singleton instance of this class. - */ - private static final Difference INSTANCE = new Difference(); - - /** - * A private constructor. - */ - private Difference() {} - - /** - * Returns the singleton instance of this class. - * - * @return The singleton instance of this class. - */ - public static Difference getInstance() { - return INSTANCE; - } - - /** - * {@inheritDoc} - */ - public String getFunctionName() { - return FUNCTION_NAME; - } - - /** - * Executes the scalar function difference() on the given values. Returns the - * difference between the given values. All values are number values. - * The method does not validate the parameters, the user must check the - * parameters before calling this method. - * - * @param values A list of the values on which the scalar function will be performed. - * - * @return Value with the difference of all given values, or number null value - * if one of the values is null. - */ - public Value evaluate(List values) { - if (values.get(0).isNull() || values.get(1).isNull()) { - return NumberValue.getNullValue(); - } - double difference = ((NumberValue) values.get(0)).getValue() - - ((NumberValue) values.get(1)).getValue(); - return new NumberValue(difference); - } - - /** - * Returns the return type of the function. In this case, NUMBER. The method - * does not validate the parameters, the user must check the parameters - * before calling this method. - * - * @param types A list of the types of the scalar function parameters. - * - * @return The type of the returned value: Number. - */ - public ValueType getReturnType(List types) { - return ValueType.NUMBER; - } - - /** - * Validates that all function parameters are of type NUMBER, and that there - * are exactly 2 parameters. Throws a ScalarFunctionException otherwise. - * - * @param types A list with parameters types. - * - * @throws InvalidQueryException Thrown if the parameters are invalid. - */ - public void validateParameters(List types) throws InvalidQueryException { - if (types.size() != 2) { - throw new InvalidQueryException("The function " + FUNCTION_NAME - + " requires 2 parmaeters "); - } - for (ValueType type : types) { - if (type != ValueType.NUMBER) { - throw new InvalidQueryException("Can't perform the function " - + FUNCTION_NAME + " on values that are not numbers"); - } - } - } - - /** - * {@inheritDoc} - */ - public String toQueryString(List argumentsQueryStrings) { - return "(" + argumentsQueryStrings.get(0) + " - " + argumentsQueryStrings.get(1) + ")"; - } -} diff --git a/src/main/java/com/google/visualization/datasource/query/scalarfunction/Lower.java b/src/main/java/com/google/visualization/datasource/query/scalarfunction/Lower.java deleted file mode 100755 index 5a22b73..0000000 --- a/src/main/java/com/google/visualization/datasource/query/scalarfunction/Lower.java +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query.scalarfunction; - -import com.google.visualization.datasource.base.InvalidQueryException; -import com.google.visualization.datasource.datatable.value.TextValue; -import com.google.visualization.datasource.datatable.value.Value; -import com.google.visualization.datasource.datatable.value.ValueType; - -import java.util.List; - -/** - * A unary scalar function that changes text to lower case. - * - * @author Yaniv S. - */ -public class Lower implements ScalarFunction { - - /** - * The name of this function. - */ - private static final String FUNCTION_NAME = "lower"; - - /** - * A singleton instance of this class. - */ - private static final Lower INSTANCE = new Lower(); - - /** - * A private constructor, to prevent instantiation other than by the singleton. - */ - private Lower() {} - - /** - * @return The singleton instance of this class. - */ - public static Lower getInstance() { - return INSTANCE; - } - - /** - * {@inheritDoc} - */ - public String getFunctionName() { - return FUNCTION_NAME; - } - - /** - * @param values A list that contains one text value. - * - * @return A lower-case version of the input text value. - */ - public Value evaluate(List values) { - return new TextValue(((TextValue) values.get(0)).getValue().toLowerCase()); - } - - /** - * @return The return type of this function - TEXT. - */ - public ValueType getReturnType(List types) { - return ValueType.TEXT; - } - - /** - * {@inheritDoc} - */ - public void validateParameters(List types) throws InvalidQueryException { - if (types.size() != 1) { - throw new InvalidQueryException(FUNCTION_NAME + - " requires 1 parmaeter"); - } - if (types.get(0) != ValueType.TEXT) { - throw new InvalidQueryException(FUNCTION_NAME + - " takes a text parameter"); - } - } - - /** - * {@inheritDoc} - */ - public String toQueryString(List argumentsQueryStrings) { - return FUNCTION_NAME + "(" + argumentsQueryStrings.get(0) + ")"; - } -} diff --git a/src/main/java/com/google/visualization/datasource/query/scalarfunction/Modulo.java b/src/main/java/com/google/visualization/datasource/query/scalarfunction/Modulo.java deleted file mode 100644 index 3de80bb..0000000 --- a/src/main/java/com/google/visualization/datasource/query/scalarfunction/Modulo.java +++ /dev/null @@ -1,124 +0,0 @@ -// Copyright 2010 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query.scalarfunction; - -import com.google.visualization.datasource.base.InvalidQueryException; -import com.google.visualization.datasource.datatable.value.NumberValue; -import com.google.visualization.datasource.datatable.value.Value; -import com.google.visualization.datasource.datatable.value.ValueType; - -import java.util.List; - -/** - * The binary scalar function modulo(). - * Returns the modulo between two number values. - * - * @author Roee E. - */ -public class Modulo implements ScalarFunction { - - /** - * The name of this function. - */ - private static final String FUNCTION_NAME = "modulo"; - - /** - * A singleton instance of this class. - */ - private static final Modulo INSTANCE = new Modulo(); - - /** - * A private constructor, to prevent instantiation other than by the singleton. - */ - private Modulo() {} - - /** - * Returns the singleton instance of this class. - * - * @return The singleton instance of this class. - */ - public static Modulo getInstance() { - return INSTANCE; - } - - /** - * {@inheritDoc} - */ - public String getFunctionName() { - return FUNCTION_NAME; - } - - /** - * Executes a binary scalar function modulo() between the first and the second - * values in the list. Returns the modulo between the given values. All values - * are number values. The method does not validate the parameters, - * the user must check the parameters before calling this method. - * - * @param values A list of values on which the scalar function is performed. - * - * - * @return Value with the modulo between two given values, or number null value - * if one of the values is null. - */ - public Value evaluate(List values) { - if (values.get(0).isNull() || values.get(1).isNull()) { - return NumberValue.getNullValue(); - } - double modulo = ((NumberValue) values.get(0)).getValue() % - ((NumberValue) values.get(1)).getValue(); - return new NumberValue(modulo); - } - - /** - * Returns the return type of the function. In this case, NUMBER. The method - * does not validate the parameters, the user must check the parameters - * before calling this method. - * - * @param types A list of the types of the scalar function parameters. - * - * @return The type of the returned value: Number. - */ - public ValueType getReturnType(List types) { - return ValueType.NUMBER; - } - - /** - * Validates that all function parameters are of type NUMBER, and that there - * are exactly 2 parameters. Throws a ScalarFunctionException otherwise. - * - * @param types A list with parameters types. - * - * @throws InvalidQueryException Thrown if the parameters are invalid. - */ - public void validateParameters(List types) throws InvalidQueryException { - if (types.size() != 2) { - throw new InvalidQueryException("The function " + FUNCTION_NAME - + " requires 2 parmaeters "); - } - for (ValueType type : types) { - if (type != ValueType.NUMBER) { - throw new InvalidQueryException("Can't perform the function " - + FUNCTION_NAME + " on values that are not numbers"); - } - } - } - - /** - * {@inheritDoc} - */ - public String toQueryString(List argumentsQueryStrings) { - return "(" + argumentsQueryStrings.get(0) + " % " + argumentsQueryStrings.get(1) + ")"; - } -} \ No newline at end of file diff --git a/src/main/java/com/google/visualization/datasource/query/scalarfunction/Product.java b/src/main/java/com/google/visualization/datasource/query/scalarfunction/Product.java deleted file mode 100755 index e6a1d93..0000000 --- a/src/main/java/com/google/visualization/datasource/query/scalarfunction/Product.java +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query.scalarfunction; - -import com.google.visualization.datasource.base.InvalidQueryException; -import com.google.visualization.datasource.datatable.value.NumberValue; -import com.google.visualization.datasource.datatable.value.Value; -import com.google.visualization.datasource.datatable.value.ValueType; - -import java.util.List; - -/** - * The binary scalar function product(). - * Returns the product of two number values. - * - * @author Liron L. - */ -public class Product implements ScalarFunction { - - /** - * The name of this function. - */ - private static final String FUNCTION_NAME = "product"; - - /** - * A singleton instance of this class. - */ - private static final Product INSTANCE = new Product(); - - /** - * A private constructor, to prevent instantiation other than by the singleton. - */ - private Product() {} - - /** - * Returns the singleton instance of this class. - * - * @return The singleton instance of this class. - */ - public static Product getInstance() { - return INSTANCE; - } - - /** - * {@inheritDoc} - */ - public String getFunctionName() { - return FUNCTION_NAME; - } - - /** - * Executes the scalar function product() on the given values. Returns the - * product of the given values. All values are number values. - * The method does not validate the parameters, the user must check the - * parameters before calling this method. - * - * @param values A list of values on which the scalar function is performed. - * - * @return Value with the product of all given values, or number null value - * if one of the values is null. - */ - public Value evaluate(List values) { - if (values.get(0).isNull() || values.get(1).isNull()) { - return NumberValue.getNullValue(); - } - double product = ((NumberValue) values.get(0)).getValue() * - ((NumberValue) values.get(1)).getValue(); - return new NumberValue(product); - } - - /** - * Returns the return type of the function. In this case, NUMBER. The method - * does not validate the parameters, the user must check the parameters - * before calling this method. - * - * @param types A list of the types of the scalar function parameters. - * - * @return The type of the returned value: Number. - */ - public ValueType getReturnType(List types) { - return ValueType.NUMBER; - } - - /** - * Validates that all function parameters are of type NUMBER, and that there - * are exactly 2 parameters. Throws a ScalarFunctionException otherwise. - * - * @param types A list with parameters types. - * - * @throws InvalidQueryException Thrown if the parameters are invalid. - */ - public void validateParameters(List types) throws InvalidQueryException { - if (types.size() != 2) { - throw new InvalidQueryException("The function " + FUNCTION_NAME - + " requires 2 parmaeters "); - } - for (ValueType type : types) { - if (type != ValueType.NUMBER) { - throw new InvalidQueryException("Can't perform the function " - + FUNCTION_NAME + " on values that are not numbers"); - } - } - } - - /** - * {@inheritDoc} - */ - public String toQueryString(List argumentsQueryStrings) { - return "(" + argumentsQueryStrings.get(0) + " * " + argumentsQueryStrings.get(1) + ")"; - } -} diff --git a/src/main/java/com/google/visualization/datasource/query/scalarfunction/Quotient.java b/src/main/java/com/google/visualization/datasource/query/scalarfunction/Quotient.java deleted file mode 100755 index 412aa54..0000000 --- a/src/main/java/com/google/visualization/datasource/query/scalarfunction/Quotient.java +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query.scalarfunction; - -import com.google.visualization.datasource.base.InvalidQueryException; -import com.google.visualization.datasource.datatable.value.NumberValue; -import com.google.visualization.datasource.datatable.value.Value; -import com.google.visualization.datasource.datatable.value.ValueType; - -import java.util.List; - -/** - * The binary scalar function quotient(). - * Returns the quotient of two values. Division by zero returns a null number - * value. - * - * @author Liron L. - */ -public class Quotient implements ScalarFunction { - - /** - * The name of this function. - */ - private static final String FUNCTION_NAME = "quotient"; - - /** - * A singleton instance of this class. - */ - private static final Quotient INSTANCE = new Quotient(); - - /** - * A private constructor, to prevent instantiation other than by the singleton. - */ - private Quotient() {} - - /** - * Returns the singleton instance of this class. - * - * @return The singleton instance of this class. - */ - public static Quotient getInstance() { - return INSTANCE; - } - - /** - * {@inheritDoc} - */ - public String getFunctionName() { - return FUNCTION_NAME; - } - - /** - * Executes the scalar function quotient() on the given values. Returns the - * quotient of the given values. All values are number values. Division by - * zero returns a null number value. - * The method does not validate the parameters, the user must check the - * parameters before calling this method. - * - * @param values A list of values on which the scalar function is performed. - * - * @return Value with the quotient of all given values, or number null value - * if one of the values is null or if one of the denominators is zero. - */ - public Value evaluate(List values) { - if (values.get(0).isNull() || values.get(1).isNull() - || (((NumberValue) values.get(1)).getValue() == 0)) { - return NumberValue.getNullValue(); - } - double quotient = ((NumberValue) values.get(0)).getValue() / - ((NumberValue) values.get(1)).getValue(); - return new NumberValue(quotient); - } - - /** - * Returns the return type of the function. In this case, NUMBER. The method - * does not validate the parameters, the user must check the parameters - * before calling this method. - * - * @param types A list of the types of the scalar function parameters. - * - * @return The type of the returned value: Number. - */ - public ValueType getReturnType(List types) { - return ValueType.NUMBER; - } - - /** - * Validates that all function parameters are of type NUMBER, and that there - * are exactly 2 parameters. Throws a ScalarFunctionException otherwise. - * - * @param types A list with parameters types. - * - * @throws InvalidQueryException Thrown if the parameters are invalid. - */ - public void validateParameters(List types) throws InvalidQueryException { - if (types.size() != 2) { - throw new InvalidQueryException("The function " + FUNCTION_NAME - + " requires 2 parmaeters "); - } - for (ValueType type : types) { - if (type != ValueType.NUMBER) { - throw new InvalidQueryException("Can't perform the function " - + FUNCTION_NAME + " on values that are not numbers"); - } - } - } - - /** - * {@inheritDoc} - */ - public String toQueryString(List argumentsQueryStrings) { - return "(" + argumentsQueryStrings.get(0) + " / " + argumentsQueryStrings.get(1) + ")"; - } -} diff --git a/src/main/java/com/google/visualization/datasource/query/scalarfunction/ScalarFunction.java b/src/main/java/com/google/visualization/datasource/query/scalarfunction/ScalarFunction.java deleted file mode 100755 index 836a845..0000000 --- a/src/main/java/com/google/visualization/datasource/query/scalarfunction/ScalarFunction.java +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query.scalarfunction; - -import com.google.visualization.datasource.base.InvalidQueryException; -import com.google.visualization.datasource.datatable.value.Value; -import com.google.visualization.datasource.datatable.value.ValueType; - -import java.util.List; - -/** - * A scalar function. - * A scalar function can have any arity, including 0, and can also have dynamic arity. - * It must always produce a single value. The return type of such a function may depend on the - * number and types of its arguments but never on their values. An instance of a class that - * implements this interface can be used within a ScalarFunctionColumn. - * - * @author Liron L. - */ -public interface ScalarFunction { - - /** - * Returns the function's name. - * - * @return The function's name. - */ - String getFunctionName(); - - /** - * Executes the scalar function on the given list of values, and returns the - * Value which is the result of the execution the function. - * - * @param values The given list of parameter values for the scalar function. - * - * @return A Value which is the result of the executing the function. - */ - Value evaluate(List values); - - /** - * Returns the return type of the function, given specific types for its parameters. Some - * functions can be polymorphic, i.e., their return type changes according to the types of their - * parameters. - * - * @param types A list of the types of the function's parameters. - * - * @return The return type of the function. - */ - ValueType getReturnType(List types); - - /** - * Validates that the number and types of the function parameters are valid. - * Throws an exception if they are not valid. - * - * @param types The given types of the function's parameters. - * - * @throws InvalidQueryException Thrown when the parameters are invalid. - */ - void validateParameters(List types) throws InvalidQueryException; - - /** - * Returns a string that when given to the query parser will yield a similar scalar function. - * Takes as arguments the query strings of the arguments. - * - * @param argumentQueryStrings The query strings of the actual arguments. - * - * @return The query string. - */ - String toQueryString(List argumentQueryStrings); -} diff --git a/src/main/java/com/google/visualization/datasource/query/scalarfunction/Sum.java b/src/main/java/com/google/visualization/datasource/query/scalarfunction/Sum.java deleted file mode 100755 index 4822970..0000000 --- a/src/main/java/com/google/visualization/datasource/query/scalarfunction/Sum.java +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query.scalarfunction; - -import com.google.visualization.datasource.base.InvalidQueryException; -import com.google.visualization.datasource.datatable.value.NumberValue; -import com.google.visualization.datasource.datatable.value.Value; -import com.google.visualization.datasource.datatable.value.ValueType; - -import java.util.List; - -/** - * The binary scalar function sum(). - * Returns the sum of two number values. - * - * @author Liron L. - */ -public class Sum implements ScalarFunction { - - /** - * The name of this function. - */ - private static final String FUNCTION_NAME = "sum"; - - /** - * A singleton instance of this class. - */ - private static final Sum INSTANCE = new Sum(); - - /** - * A private constructor, to prevent instantiation other than by the singleton. - */ - private Sum() {} - - /** - * Returns the singleton instance of this class. - * - * @return The singleton instance of this class. - */ - public static Sum getInstance() { - return INSTANCE; - } - - /** - * {@inheritDoc} - */ - public String getFunctionName() { - return FUNCTION_NAME; - } - - /** - * Executes the scalar function sum() on the given values. Returns the sum of - * the given values. All values are number values. - * The method does not validate the parameters, the user must check the - * parameters before calling this method. - * - * @param values A list of values on which the scalar function is performed. - * - * @return Value with the sum of all given values, or number null value if one - * of the values is null. - */ - public Value evaluate(List values) { - if (values.get(0).isNull() || values.get(1).isNull()) { - return NumberValue.getNullValue(); - } - double sum = ((NumberValue) values.get(0)).getValue() + - ((NumberValue) values.get(1)).getValue(); - return new NumberValue(sum); - } - - /** - * Returns the return type of the function. In this case, NUMBER. The method - * does not validate the parameters, the user must check the parameters - * before calling this method. - * - * @param types A list of the types of the scalar function parameters. - * - * @return The type of the returned value: Number. - */ - public ValueType getReturnType(List types) { - return ValueType.NUMBER; - } - - /** - * Validates that all function parameters are of type NUMBER, and that there - * are exactly 2 parameters. Throws a ScalarFunctionException otherwise. - * - * @param types A list of parameter types. - * - * @throws InvalidQueryException Thrown if the parameters are invalid. - */ - public void validateParameters(List types) throws InvalidQueryException { - if (types.size() != 2) { - throw new InvalidQueryException("The function " + FUNCTION_NAME - + " requires 2 parmaeters "); - } - for (ValueType type : types) { - if (type != ValueType.NUMBER) { - throw new InvalidQueryException("Can't perform the function " - + FUNCTION_NAME + " on values that are not numbers"); - } - } - } - - /** - * {@inheritDoc} - */ - public String toQueryString(List argumentsQueryStrings) { - return "(" + argumentsQueryStrings.get(0) + " + " + argumentsQueryStrings.get(1) + ")"; - } -} diff --git a/src/main/java/com/google/visualization/datasource/query/scalarfunction/TimeComponentExtractor.java b/src/main/java/com/google/visualization/datasource/query/scalarfunction/TimeComponentExtractor.java deleted file mode 100755 index a883b22..0000000 --- a/src/main/java/com/google/visualization/datasource/query/scalarfunction/TimeComponentExtractor.java +++ /dev/null @@ -1,304 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query.scalarfunction; - -import com.google.common.collect.Maps; -import com.google.visualization.datasource.base.InvalidQueryException; -import com.google.visualization.datasource.datatable.value.DateTimeValue; -import com.google.visualization.datasource.datatable.value.DateValue; -import com.google.visualization.datasource.datatable.value.NumberValue; -import com.google.visualization.datasource.datatable.value.TimeOfDayValue; -import com.google.visualization.datasource.datatable.value.Value; -import com.google.visualization.datasource.datatable.value.ValueType; -import com.ibm.icu.util.GregorianCalendar; - -import java.util.List; -import java.util.Map; - -/** - * A time component extractor. This class encompasses all the unary scalar functions - * that extract a time component from a date/datetime/timeofday value. e.g., - * year, month, second. - * - * @author Liron L. - */ -public class TimeComponentExtractor implements ScalarFunction { - - /** - * An enum of time components that can be extracted from a - * date/datetime/timeofday value. - */ - public static enum TimeComponent { - YEAR("year"), - MONTH("month"), - WEEK("week"), - DAY("day"), - HOUR("hour"), - MINUTE("minute"), - SECOND("second"), - MILLISECOND("millisecond"), - QUARTER("quarter"), - // Returns 1 for Sunday, 2 for Monday, etc. - DAY_OF_WEEK("dayofweek"); - - /** - * The name of this TimeComponent. - */ - private String name; - - /** - * Constructor for the enum. Initializes the name member. - * - * @param name The name of this TimeComponent. - */ - private TimeComponent(String name) { - this.name = name; - } - - /** - * Returns the name of this TimeComponent. - * - * @return The name of this TimeComponent. - */ - public String getName() { - return name; - } - } - - /** - * A mapping of a TimeComponent to a TimeComponentExtractor that extracts this TimeComponent. - * This is used to keep a single instance of every type of extractor. - */ - private static Map timeComponentsPool; - - /** - * Returns an instance of a TimeComponentExtractor that extracts the given - * TimeComponent. - * - * @param timeComponent The TimeComponent to extract. - * - * @return Returns an instance of a TimeComponentExtractor. - */ - public static TimeComponentExtractor getInstance(TimeComponent timeComponent) - { - return timeComponentsPool.get(timeComponent); - } - - /** - * This static block builds the timeComponentsPool that maps TimeComponents to - * TimeComponentExtractors that extract this TimeComponent. - */ - static { - timeComponentsPool = Maps.newHashMap(); - for (TimeComponent component : TimeComponent.values()) { - timeComponentsPool.put(component, new TimeComponentExtractor(component)); - } - } - - /** - * The TimeComponent that this TimeComponentExtractor extracts. - */ - private TimeComponent timeComponent; - - /** - * A private constructor. - * - * @param timeComponent - */ - private TimeComponentExtractor(TimeComponent timeComponent) { - this.timeComponent = timeComponent; - - } - - /** - * Returns the name of this scalar function, in this case the name of the TimeComponentExtractor. - * - * @return the name of this scalar function, in this case the name of the TimeComponentExtractor. - */ - public String getFunctionName() { - return timeComponent.getName(); - } - - /** - * Executes the scalar function that extracts the timeComponent on the given - * values. Returns a NumberValue with the timeComponent of the given - * Date/DateTime/TimeOfDay value. The method does not validate the parameters, - * the user must check the parameters before calling this method. - * - * @param values A list of the values on which the scalar function is performed. - * - * @return Value with the timeComponent value of the given value, or number - * null value if value is null. - */ - public Value evaluate(List values) { - Value value = values.get(0); - ValueType valueType = value.getType(); - int component; - - // If the value is null, return a null number value. - if (value.isNull()) { - return NumberValue.getNullValue(); - } - - switch(timeComponent) { - case YEAR: - if (valueType == ValueType.DATE) { - component = ((DateValue) value).getYear(); - } else { // DATETIME - component = ((DateTimeValue) value).getYear(); - } - break; - case MONTH: - if (valueType == ValueType.DATE) { - component = ((DateValue) value).getMonth(); - } else { // DATETIME - component = ((DateTimeValue) value).getMonth(); - } - break; - case DAY: - if (valueType == ValueType.DATE) { - component = ((DateValue) value).getDayOfMonth(); - } else { // DATETIME - component = ((DateTimeValue) value).getDayOfMonth(); - } - break; - case HOUR: - if (valueType == ValueType.TIMEOFDAY) { - component = ((TimeOfDayValue) value).getHours(); - } else { // DATETIME - component = ((DateTimeValue) value).getHourOfDay(); - } - break; - case MINUTE: - if (valueType == ValueType.TIMEOFDAY) { - component = ((TimeOfDayValue) value).getMinutes(); - } else { // DATETIME - component = ((DateTimeValue) value).getMinute(); - } - break; - case SECOND: - if (valueType == ValueType.TIMEOFDAY) { - component = ((TimeOfDayValue) value).getSeconds(); - } else { // DATETIME - component = ((DateTimeValue) value).getSecond(); - } - break; - case MILLISECOND: - if (valueType == ValueType.TIMEOFDAY) { - component = ((TimeOfDayValue) value).getMilliseconds(); - } else { // DATETIME - component = ((DateTimeValue) value).getMillisecond(); - } - break; - case QUARTER: - if (valueType == ValueType.DATE) { - component = ((DateValue) value).getMonth(); - } else { // DATETIME - component = ((DateTimeValue) value).getMonth(); - } - component = component / 3 + 1; // Add 1 to get 1-4 instead of 0-3. - break; - case DAY_OF_WEEK: - GregorianCalendar calendar = - (GregorianCalendar) ((valueType == ValueType.DATE) ? - ((DateValue) value).getObjectToFormat() : - ((DateTimeValue) value).getObjectToFormat()); - component = calendar.get(GregorianCalendar.DAY_OF_WEEK); - break; - default: - // should not get here since we assume that the given values are valid. - throw new RuntimeException("An invalid time component."); - } - - return new NumberValue(component); - } - - /** - * Returns the return type of the function. In this case, NUMBER. The method - * does not validate the parameters, the user must check the parameters - * before calling this method. - * - * @param types A list of the types of the scalar function parameters. - * - * @return The type of the returned value: Number. - */ - public ValueType getReturnType(List types) { - return ValueType.NUMBER; - } - - /** - * Validates that there is only one parameter given for the function, and - * that its type is DATE or DATETIME if the timeComponent to extract is year, - * month or day, or that it is DATETIME or TIMEOFDAY if the timeComponent is - * hour, minute, second or millisecond. Throws a ScalarFunctionException if - * the parameters are invalid. - * - * @param types A list of parameter types. - * - * @throws InvalidQueryException Thrown if the parameters are invalid. - */ - public void validateParameters(List types) throws InvalidQueryException { - if (types.size() != 1) { - throw new InvalidQueryException("Number of parameters for " - + timeComponent.getName() + "function is wrong: " + types.size()); - } - switch (timeComponent) { - case YEAR: - case MONTH: - case DAY: - case QUARTER: - case DAY_OF_WEEK: - if ((types.get(0) != ValueType.DATE) - && (types.get(0) != ValueType.DATETIME)) { - throw new InvalidQueryException("Can't perform the function " - + timeComponent.getName() + " on a column that is not a Date or" - + " a DateTime column"); - } - break; - case HOUR: - case MINUTE: - case SECOND: - case MILLISECOND: - if ((types.get(0) != ValueType.TIMEOFDAY) - && (types.get(0) != ValueType.DATETIME)) { - throw new InvalidQueryException("Can't perform the function " - + timeComponent.getName() + " on a column that is not a " - + "TimeOfDay or a DateTime column"); - } - break; - } - } - - @Override - public boolean equals(Object o) { - if (o instanceof TimeComponentExtractor) { - TimeComponentExtractor other = (TimeComponentExtractor) o; - return timeComponent.equals(other.timeComponent); - } - return false; - } - - @Override - public int hashCode() { - return (timeComponent == null) ? 0 : timeComponent.hashCode(); - } - - /** - * {@inheritDoc} - */ - public String toQueryString(List argumentsQueryStrings) { - return getFunctionName() + "(" + argumentsQueryStrings.get(0) + ")"; - } -} diff --git a/src/main/java/com/google/visualization/datasource/query/scalarfunction/ToDate.java b/src/main/java/com/google/visualization/datasource/query/scalarfunction/ToDate.java deleted file mode 100755 index 7d99edd..0000000 --- a/src/main/java/com/google/visualization/datasource/query/scalarfunction/ToDate.java +++ /dev/null @@ -1,152 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query.scalarfunction; - -import com.google.visualization.datasource.base.InvalidQueryException; -import com.google.visualization.datasource.datatable.value.DateTimeValue; -import com.google.visualization.datasource.datatable.value.DateValue; -import com.google.visualization.datasource.datatable.value.NumberValue; -import com.google.visualization.datasource.datatable.value.Value; -import com.google.visualization.datasource.datatable.value.ValueType; - -import com.ibm.icu.util.GregorianCalendar; -import com.ibm.icu.util.TimeZone; - -import java.util.Date; -import java.util.List; - -/** - * The unary scalar function toDate(). - * Transforms the given value to date value. - * If the given value is already a date, it's trivial. - * If the given value is a date-time, it extracts its date part. - * If the given value is number, it treats that number as the number of milliseconds since the - * Epoch, and returns the corresponding date. - * - * @author Liron L. - */ -public class ToDate implements ScalarFunction { - - /** - * The name of the function. - */ - private static final String FUNCTION_NAME = "toDate"; - - /** - * A singleton instance of this class. - */ - private static final ToDate INSTANCE = new ToDate(); - - /** - * A private constructor. - */ - private ToDate() {} - - /** - * Returns the singleton instance of this class. - * - * @return The singleton instance of this class. - */ - public static ToDate getInstance() { - return INSTANCE; - } - - /** - * {@inheritDoc} - */ - public String getFunctionName() { - return FUNCTION_NAME; - } - - /** - * Executes the scalar function toDate() on the given values. The list is expected to be - * of length 1, and the value in it should be of an appropiate type. - * The method does not validate the parameters, the user must check the - * parameters before calling this method. - * - * @param values A list with the values that the scalar function is performed on them. - * - * @return A date value with the appropriate date. - */ - public Value evaluate(List values) { - Value value = values.get(0); - Date date; - GregorianCalendar gc = new GregorianCalendar(TimeZone.getTimeZone("GMT")); - - // If the given value is null, return a null date value. - if (value.isNull()) { - return DateValue.getNullValue(); - } - DateValue dateValue; - switch(value.getType()) { - case DATE: - dateValue = (DateValue) value; - break; - case DATETIME: - dateValue = new DateValue((GregorianCalendar) - (((DateTimeValue) value).getObjectToFormat())); - break; - case NUMBER: - date = new Date((long) ((NumberValue) value).getValue()); - gc.setTime(date); - dateValue = new DateValue(gc); - break; - default:// Should never get here. - throw new RuntimeException("Value type was not found: " + value.getType()); - } - return dateValue; - } - - /** - * Returns the return type of the function. In this case, DATE. The method - * does not validate the parameters, the user must check the parameters - * before calling this method. - * - * @param types A list of the types of the scalar function parameters. - * - * @return The type of the returned value: DATE. - */ - public ValueType getReturnType(List types) { - return ValueType.DATE; - } - - /** - * Validates that there is only 1 parameter given for this function, and - * that its type is either DATE, DATETIME or NUMBER. Throws a - * ScalarFunctionException if the parameters are invalid. - * - * @param types A list with parameters types. - * - * @throws InvalidQueryException Thrown if the parameters are invalid. - */ - public void validateParameters(List types) throws InvalidQueryException { - if (types.size() != 1) { - throw new InvalidQueryException("Number of parameters for the date " - + "function is wrong: " + types.size()); - } else if ((types.get(0) != ValueType.DATETIME) - && (types.get(0) != ValueType.DATE) - && (types.get(0) != ValueType.NUMBER)) { - throw new InvalidQueryException("Can't perform the function 'date' " - + "on values that are not date, dateTime or number values"); - } - } - - /** - * {@inheritDoc} - */ - public String toQueryString(List argumentsQueryStrings) { - return FUNCTION_NAME + "(" + argumentsQueryStrings.get(0) + ")"; - } -} diff --git a/src/main/java/com/google/visualization/datasource/query/scalarfunction/Upper.java b/src/main/java/com/google/visualization/datasource/query/scalarfunction/Upper.java deleted file mode 100755 index 1588d25..0000000 --- a/src/main/java/com/google/visualization/datasource/query/scalarfunction/Upper.java +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query.scalarfunction; - -import com.google.visualization.datasource.base.InvalidQueryException; -import com.google.visualization.datasource.datatable.value.TextValue; -import com.google.visualization.datasource.datatable.value.Value; -import com.google.visualization.datasource.datatable.value.ValueType; - -import java.util.List; - -/** - * A unary scalar function that changes text to upper case. - * - * @author Yaniv S. - */ -public class Upper implements ScalarFunction { - - /** - * The name of this function. - */ - private static final String FUNCTION_NAME = "upper"; - - /** - * A singleton instance of this class. - */ - private static final Upper INSTANCE = new Upper(); - - /** - * A private constructor, to prevent instantiation other than by the singleton. - */ - private Upper() {} - - /** - * @return The singleton instance of this class. - */ - public static Upper getInstance() { - return INSTANCE; - } - - /** - * {@inheritDoc} - */ - public String getFunctionName() { - return FUNCTION_NAME; - } - - /** - * @param values A list that contains one text value. - * - * @return An uppercase version of the input text value. - */ - public Value evaluate(List values) { - return new TextValue(((TextValue) values.get(0)).getValue().toUpperCase()); - } - - /** - * @return The return type of this function - TEXT. - */ - public ValueType getReturnType(List types) { - return ValueType.TEXT; - } - - /** - * {@inheritDoc} - */ - public void validateParameters(List types) throws InvalidQueryException { - if (types.size() != 1) { - throw new InvalidQueryException(FUNCTION_NAME + - " requires 1 parmaeter"); - } - if (types.get(0) != ValueType.TEXT) { - throw new InvalidQueryException(FUNCTION_NAME + - " takes a text parameter"); - } - } - - /** - * {@inheritDoc} - */ - public String toQueryString(List argumentsQueryStrings) { - return FUNCTION_NAME + "(" + argumentsQueryStrings.get(0) + ")"; - } -} \ No newline at end of file diff --git a/src/main/java/com/google/visualization/datasource/render/CsvRenderer.java b/src/main/java/com/google/visualization/datasource/render/CsvRenderer.java deleted file mode 100755 index 86f2b79..0000000 --- a/src/main/java/com/google/visualization/datasource/render/CsvRenderer.java +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.render; - -import com.google.visualization.datasource.base.ResponseStatus; -import com.google.visualization.datasource.datatable.ColumnDescription; -import com.google.visualization.datasource.datatable.DataTable; -import com.google.visualization.datasource.datatable.TableCell; -import com.google.visualization.datasource.datatable.TableRow; -import com.google.visualization.datasource.datatable.ValueFormatter; -import com.google.visualization.datasource.datatable.value.ValueType; - -import com.ibm.icu.util.ULocale; - -import org.apache.commons.lang.StringUtils; - -import java.util.List; -import java.util.Map; - -/** - * Takes a data table and returns a csv string. - * - * @author Nimrod T. - */ -public class CsvRenderer { - - /** - * Private constructor. - */ - private CsvRenderer() {} - - /** - * Generates a csv string representation of a data table. - * - * @param dataTable The data table. - * @param locale The locale. If null, uses the default from - * {@code LocaleUtil#getDefaultLocale}. - * @param separator The separator string used to delimit row values. - * If the separator is {@code null}, comma is used as a separator. - * - * @return The char sequence with the csv string. - */ - public static CharSequence renderDataTable(DataTable dataTable, ULocale locale, - String separator) { - if (separator == null) { - separator = ","; - } - - // Deal with empty data table. - if (dataTable.getColumnDescriptions().isEmpty()) { - return ""; - } - - // Deal with non-empty data table. - StringBuilder sb = new StringBuilder(); - List columns = dataTable.getColumnDescriptions(); - // Append column labels - for (ColumnDescription column : columns) { - sb.append(escapeString(column.getLabel())).append(separator); - } - - Map formatters = ValueFormatter.createDefaultFormatters(locale); - - // Remove last comma. - int length = sb.length(); - sb.replace(length - 1, length, "\n"); - - // Append the data cells. - List rows = dataTable.getRows(); - for (TableRow row : rows) { - List cells = row.getCells(); - for (TableCell cell : cells) { - String formattedValue = cell.getFormattedValue(); - if (formattedValue == null) { - formattedValue = formatters.get(cell.getType()).format(cell.getValue()); - } - if (cell.isNull()) { - sb.append("null"); - } else { - ValueType type = cell.getType(); - // Escape the string with quotes if its a text value or if it contains a comma. - if (formattedValue.indexOf(',') > -1 || type.equals(ValueType.TEXT)) { - sb.append(escapeString(formattedValue)); - } else { - sb.append(formattedValue); - } - } - sb.append(separator); - } - - // Remove last comma. - length = sb.length(); - sb.replace(length - 1, length, "\n"); - } - return sb.toString(); - } - - /** - * Escapes a string that is written to a csv file. The escaping is as follows: - * 1) surround with ". - * 2) double each internal ". - * - * @param input The input string. - * - * @return An escaped string. - */ - private static String escapeString(String input) { - StringBuilder sb = new StringBuilder(); - sb.append("\""); - sb.append(StringUtils.replace(input, "\"", "\"\"")); - sb.append("\""); - return sb.toString(); - } - - /** - * Renders an error message. - * - * @param responseStatus The response status. - * - * @return An error message. - */ - public static String renderCsvError(ResponseStatus responseStatus) { - StringBuilder sb = new StringBuilder(); - sb.append("Error: ").append(responseStatus.getReasonType().getMessageForReasonType(null)); - sb.append(". ").append(responseStatus.getDescription()); - return escapeString(sb.toString()); - } -} diff --git a/src/main/java/com/google/visualization/datasource/render/EscapeUtil.java b/src/main/java/com/google/visualization/datasource/render/EscapeUtil.java deleted file mode 100755 index 0823118..0000000 --- a/src/main/java/com/google/visualization/datasource/render/EscapeUtil.java +++ /dev/null @@ -1,157 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.render; - - -import org.apache.commons.lang.StringEscapeUtils; - -/** - * A utility to escape strings. - * - * @author Hillel M. - */ -public class EscapeUtil { - - /** - * This helper lookup array is used for json escaping. It enables fast lookup of unicode - * characters. - * {@link #jsonEscape}. - */ - private static final char[] HEX_DIGITS = { - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' - }; - - /** - * Private constructor. - */ - private EscapeUtil() { - } - - /** - * This method is used to escape strings embedded in the json response. The method is based on - * org.apache.shindig.common.JsonSerializer.appendString(). - * The method escapes the following in order to enable safe parsing of the json string: - * 1) single and double quotes - ' and " - * 2) backslash - / - * 3) html brackets - <> - * 4) control characters - \n \t \r .. - * 5) special characters - out of range unicode characters (formatted to the uxxxx format) - * - * @param str The original string to escape. - * - * @return The escaped string. - */ - public static String jsonEscape(String str) { - if (str == null || str.length() == 0) { - return ""; - } - StringBuffer sb = new StringBuffer(); - char current; - for (int i = 0, j = str.length(); i < j; ++i) { - current = str.charAt(i); - switch (current) { - case '\'': - sb.append("\\u0027"); - break; - case '\"': - sb.append("\\u0022"); - break; - case '\\': - sb.append('\\'); - sb.append(current); - break; - // We escape angle brackets in order to prevent content sniffing in user agents like IE. - // This content sniffing can potentially be used to bypass other security restrictions. - case '<': - sb.append("\\u003c"); - break; - case '>': - sb.append("\\u003e"); - break; - default: - if (current < ' ' || (current >= '\u0080' && current < '\u00a0') || - (current >= '\u2000' && current < '\u2100')) { - sb.append('\\'); - switch (current) { - case '\b': - sb.append('b'); - break; - case '\t': - sb.append('t'); - break; - case '\n': - sb.append('n'); - break; - case '\f': - sb.append('f'); - break; - case '\r': - sb.append('r'); - break; - default: - // The possible alternative approaches for dealing with unicode characters are - // as follows: - // Method 1 (from json.org.JSONObject) - // 1. Append "000" + Integer.toHexString(current) - // 2. Truncate this value to 4 digits by using value.substring(value.length() - 4) - // - // Method 2 (from net.sf.json.JSONObject) - // This method is fairly unique because the entire thing uses an intermediate fixed - // size buffer of 1KB. It's an interesting approach, but overall performs worse than - // org.json - // 1. Append "000" + Integer.toHexString(current) - // 2. Append value.charAt(value.length() - 4) - // 2. Append value.charAt(value.length() - 3) - // 2. Append value.charAt(value.length() - 2) - // 2. Append value.charAt(value.length() - 1) - // - // Method 3 (previous experiment) - // 1. Calculate Integer.hexString(current) - // 2. for (int i = 0; i < 4 - value.length(); ++i) { buf.append('0'); } - // 3. buf.append(value) - // - // Method 4 (Sun conversion from java.util.Properties) - // 1. Append '\' - // 2. Append 'u' - // 3. Append each of 4 octets by indexing into a hex array. - // - // Method 5 - // Index into a single lookup table of all relevant lookup values. - sb.append('u'); - sb.append(HEX_DIGITS[(current >> 12) & 0xF]); - sb.append(HEX_DIGITS[(current >> 8) & 0xF]); - sb.append(HEX_DIGITS[(current >> 4) & 0xF]); - sb.append(HEX_DIGITS[current & 0xF]); - } - } else { - sb.append(current); - } - } - } - return sb.toString(); - } - - /** - * Escapes the string for embedding in html. - * - * @param str The string to escape. - * - * @return The escaped string. - */ - public static String htmlEscape(String str) { - return StringEscapeUtils.escapeHtml(str); - } - -} diff --git a/src/main/java/com/google/visualization/datasource/render/HtmlRenderer.java b/src/main/java/com/google/visualization/datasource/render/HtmlRenderer.java deleted file mode 100755 index ac41811..0000000 --- a/src/main/java/com/google/visualization/datasource/render/HtmlRenderer.java +++ /dev/null @@ -1,327 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.render; - -import com.google.visualization.datasource.base.ReasonType; -import com.google.visualization.datasource.base.ResponseStatus; -import com.google.visualization.datasource.base.StatusType; -import com.google.visualization.datasource.base.Warning; -import com.google.visualization.datasource.datatable.ColumnDescription; -import com.google.visualization.datasource.datatable.DataTable; -import com.google.visualization.datasource.datatable.TableCell; -import com.google.visualization.datasource.datatable.TableRow; -import com.google.visualization.datasource.datatable.ValueFormatter; -import com.google.visualization.datasource.datatable.value.BooleanValue; -import com.google.visualization.datasource.datatable.value.ValueType; - -import com.ibm.icu.util.ULocale; - -import org.apache.commons.lang.StringUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -import java.io.StringWriter; -import java.io.Writer; -import java.util.List; -import java.util.Map; -import java.util.regex.Pattern; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.transform.OutputKeys; -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerConfigurationException; -import javax.xml.transform.TransformerException; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.dom.DOMSource; -import javax.xml.transform.stream.StreamResult; - -/** - * Takes a data table and returns an html string. - * - * @author Nimrod T. - */ -public class HtmlRenderer { - - /** - * Log. - */ - private static final Log log = LogFactory.getLog("HtmlRenderer"); - - /** - * Private constructor. - */ - private HtmlRenderer() {} - - /** - * Pattern for matching against <a> tags with hrefs. - * Used in sanitizeDetailedMessage. - */ - private static final Pattern DETAILED_MESSAGE_A_TAG_REGEXP = Pattern.compile( - "([^<]*[^<]*)+[^<]*"); - - /** - * Pattern for matching against "javascript:". - * Used in sanitizeDetailedMessage. - */ - private static final Pattern BAD_JAVASCRIPT_REGEXP = Pattern.compile("javascript(( )*):"); - - /** - * Generates an HTML string representation of a data table. - * - * @param dataTable The data table to render. - * @param locale The locale. If null, uses the default from - * {@code LocaleUtil#getDefaultLocale}. - * - * @return The char sequence with the html string. - */ - public static CharSequence renderDataTable(DataTable dataTable, ULocale locale) { - // Create an xml document with head and an empty body. - Document document = createDocument(); - Element bodyElement = appendHeadAndBody(document); - - // Populate the xml document. - Element tableElement = document.createElement("table"); - bodyElement.appendChild(tableElement); - tableElement.setAttribute("border", "1"); - tableElement.setAttribute("cellpadding", "2"); - tableElement.setAttribute("cellspacing", "0"); - - // Labels tr element. - List columnDescriptions = dataTable.getColumnDescriptions(); - Element trElement = document.createElement("tr"); - trElement.setAttribute("style", "font-weight: bold; background-color: #aaa;"); - for (ColumnDescription columnDescription : columnDescriptions) { - Element tdElement = document.createElement("td"); - tdElement.setTextContent(columnDescription.getLabel()); - trElement.appendChild(tdElement); - } - tableElement.appendChild(trElement); - - Map formatters = ValueFormatter.createDefaultFormatters(locale); - // Table tr elements. - int rowCount = 0; - for (TableRow row : dataTable.getRows()) { - rowCount++; - trElement = document.createElement("tr"); - String backgroundColor = (rowCount % 2 != 0) ? "#f0f0f0" : "#ffffff"; - trElement.setAttribute("style", "background-color: " + backgroundColor); - - List cells = row.getCells(); - for (int c = 0; c < cells.size(); c++) { - ValueType valueType = columnDescriptions.get(c).getType(); - TableCell cell = cells.get(c); - String cellFormattedText = cell.getFormattedValue(); - if (cellFormattedText == null) { - cellFormattedText = formatters.get(cell.getType()).format(cell.getValue()); - } - - Element tdElement = document.createElement("td"); - if (cell.isNull()) { - tdElement.setTextContent("\u00a0"); - } else { - switch (valueType) { - case NUMBER: - tdElement.setAttribute("align", "right"); - tdElement.setTextContent(cellFormattedText); - break; - case BOOLEAN: - BooleanValue booleanValue = (BooleanValue) cell.getValue(); - tdElement.setAttribute("align", "center"); - if (booleanValue.getValue()) { - tdElement.setTextContent("\u2714"); // Check mark. - } else { - tdElement.setTextContent("\u2717"); // X mark. - } - break; - default: - if (StringUtils.isEmpty(cellFormattedText)) { - tdElement.setTextContent("\u00a0"); // nbsp. - } else { - tdElement.setTextContent(cellFormattedText); - } - } - } - trElement.appendChild(tdElement); - } - tableElement.appendChild(trElement); - } - bodyElement.appendChild(tableElement); - - // Warnings: - for (Warning warning : dataTable.getWarnings()) { - bodyElement.appendChild(document.createElement("br")); - bodyElement.appendChild(document.createElement("br")); - Element messageElement = document.createElement("div"); - messageElement.setTextContent(warning.getReasonType().getMessageForReasonType() + ". " + - warning.getMessage()); - bodyElement.appendChild(messageElement); - } - - return transformDocumentToHtmlString(document); - } - - /** - * Transforms a document to a valid html string. - * - * @param document The document to transform - * - * @return A string representation of a valid html. - */ - private static String transformDocumentToHtmlString(Document document) { - // Generate a CharSequence from the xml document. - Transformer transformer = null; - try { - transformer = TransformerFactory.newInstance().newTransformer(); - } catch (TransformerConfigurationException e) { - log.error("Couldn't create a transformer", e); - throw new RuntimeException("Couldn't create a transformer. This should never happen.", e); - } - transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no"); - transformer.setOutputProperty(OutputKeys.INDENT, "yes"); - transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, "-//W3C//DTD HTML 4.01//EN"); - transformer.setOutputProperty(OutputKeys.METHOD, "html"); - transformer.setOutputProperty(OutputKeys.VERSION, "4.01"); - - DOMSource source = new DOMSource(document); - Writer writer = new StringWriter(); - StreamResult result = new StreamResult(writer); - try { - transformer.transform(source, result); - } catch (TransformerException e) { - log.error("Couldn't transform", e); - throw new RuntimeException("Couldn't transform. This should never happen.", e); - } - - return writer.toString(); - } - - /** - * Sanitizes the html in the detailedMessage, to allow only href inside <a> tags. - * - * @param detailedMessage The detailedMessage. - * - * @return The sanitized detailedMessage. - */ - static String sanitizeDetailedMessage(String detailedMessage) { - if (StringUtils.isEmpty(detailedMessage)) { - return ""; - } - - if (DETAILED_MESSAGE_A_TAG_REGEXP.matcher(detailedMessage).matches() - && (!BAD_JAVASCRIPT_REGEXP.matcher(detailedMessage).find())) { - // No need to escape. - return detailedMessage; - } else { - // Need to html escape. - return EscapeUtil.htmlEscape(detailedMessage); - } - } - - /** - * Renders a simple html for the given responseStatus. - * - * @param responseStatus The response message. - * - * @return A simple html for the given responseStatus. - */ - public static CharSequence renderHtmlError(ResponseStatus responseStatus) { - // Get the responseStatus details. - StatusType status = responseStatus.getStatusType(); - ReasonType reason = responseStatus.getReasonType(); - String detailedMessage = responseStatus.getDescription(); - - // Create an xml document with head and an empty body. - Document document = createDocument(); - Element bodyElement = appendHeadAndBody(document); - - // Populate the xml document. - Element oopsElement = document.createElement("h3"); - oopsElement.setTextContent("Oops, an error occured."); - bodyElement.appendChild(oopsElement); - - if (status != null) { - String text = "Status: " + status.lowerCaseString(); - appendSimpleText(document, bodyElement, text); - } - - if (reason != null) { - String text = "Reason: " + reason.getMessageForReasonType(null); - appendSimpleText(document, bodyElement, text); - } - - if (detailedMessage != null) { - String text = "Description: " + sanitizeDetailedMessage(detailedMessage); - appendSimpleText(document, bodyElement, text); - } - - return transformDocumentToHtmlString(document); - } - - /** - * Creates a document element. - * - * @return A document element. - */ - private static Document createDocument() { - DocumentBuilder documentBuilder = null; - try { - documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); - } catch (ParserConfigurationException e) { - log.error("Couldn't create a document builder", e); - throw new RuntimeException( - "Couldn't create a document builder. This should never happen.", e); - } - Document document = documentBuilder.newDocument(); - return document; - } - - /** - * Appends <html>, <head>, <title>, and <body> elements to the document. - * - * @param document The containing document. - * - * @return The <body> element. - */ - private static Element appendHeadAndBody(Document document) { - Element htmlElement = document.createElement("html"); - document.appendChild(htmlElement); - Element headElement = document.createElement("head"); - htmlElement.appendChild(headElement); - Element titleElement = document.createElement("title"); - titleElement.setTextContent("Google Visualization"); - headElement.appendChild(titleElement); - Element bodyElement = document.createElement("body"); - htmlElement.appendChild(bodyElement); - return bodyElement; - } - - /** - * Appends a simple text line to the body of the document. - * - * @param document The containing document. - * @param bodyElement The body of the document. - * @param text The text to append. - */ - private static void appendSimpleText(Document document, Element bodyElement, String text) { - Element statusElement = document.createElement("div"); - statusElement.setTextContent(text); - bodyElement.appendChild(statusElement); - } -} diff --git a/src/main/java/com/google/visualization/datasource/render/JsonRenderer.java b/src/main/java/com/google/visualization/datasource/render/JsonRenderer.java deleted file mode 100755 index e29e113..0000000 --- a/src/main/java/com/google/visualization/datasource/render/JsonRenderer.java +++ /dev/null @@ -1,503 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.render; - -import com.google.common.collect.Lists; -import com.google.visualization.datasource.base.DataSourceParameters; -import com.google.visualization.datasource.base.OutputType; -import com.google.visualization.datasource.base.ReasonType; -import com.google.visualization.datasource.base.ResponseStatus; -import com.google.visualization.datasource.base.StatusType; -import com.google.visualization.datasource.base.Warning; -import com.google.visualization.datasource.datatable.ColumnDescription; -import com.google.visualization.datasource.datatable.DataTable; -import com.google.visualization.datasource.datatable.TableCell; -import com.google.visualization.datasource.datatable.TableRow; -import com.google.visualization.datasource.datatable.value.BooleanValue; -import com.google.visualization.datasource.datatable.value.DateTimeValue; -import com.google.visualization.datasource.datatable.value.DateValue; -import com.google.visualization.datasource.datatable.value.NumberValue; -import com.google.visualization.datasource.datatable.value.TimeOfDayValue; -import com.google.visualization.datasource.datatable.value.Value; -import com.google.visualization.datasource.datatable.value.ValueType; - -import com.ibm.icu.util.GregorianCalendar; - -import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang.text.StrBuilder; - -import java.util.List; -import java.util.Map; - -/** - * Takes a data table and returns a json string. - * - * The renderer renders a response which primarily contains the serializing of a data table. - * The response type can be either json or jsonp (a json format wrapped inside a callback method). - * The main difference regarding data table serialization between the two types, is the way dates - * are serialized. Dates have no standard representation in json thus they are rendered according - * to the future use of the response. When the response type is jsonp, the data table is likely to - * be evaluated with standard browser 'eval' and therefore date represented by Date constructor - * will be transformed into javaScript dates (as expected), e.g new Date(2011,1,1). - * When the response type is json, Date constructors can not be used (not defined in the json - * standard) and so custom date strings are used instead. In this case, custom parsing of the string - * is required to construct dates objects from their respective strings, e.g "Date(2011,1,1)". - * - * @author Nimrod T. - */ -public class JsonRenderer { - - /** - * Private constructor. - */ - private JsonRenderer() {} - - /** - * Returns a String-form 32-bit hash of this table's json. - * Note: the signature ignores formatting. - * - * @param data The data table. - * - * @return a String-form 64-bit hash of this table. - */ - public static String getSignature(DataTable data) { - String tableAsString = renderDataTable(data, true, false, true).toString(); - // Casting to long to avoid bug with abs(Integer.MIN_VALUE) being negative. - long longHashCode = tableAsString.hashCode(); - return String.valueOf(Math.abs(longHashCode)); - } - - /** - * Returns the part of the json string that describes a single warning or error. - * - * @param reasonType The reason for the warning or error. - * @param description The detailed description for this warning or error. - * - * @return The part of the json string. - */ - private static String getFaultString(ReasonType reasonType, String description) { - List objectParts = Lists.newArrayList(); - if (reasonType != null) { - objectParts.add("\"reason\":\"" + reasonType.lowerCaseString() + "\""); - objectParts.add("\"message\":\"" + EscapeUtil.jsonEscape( - reasonType.getMessageForReasonType(null)) + "\""); - } - - if (description != null) { - objectParts.add("\"detailed_message\":\"" + EscapeUtil.jsonEscape(description) - + "\""); - } - return new StrBuilder("{").appendWithSeparators(objectParts, ",").append("}").toString(); - } - - /** - * @deprecated As of version 1.1.1, isJsonp is removed and instead is inferred from dsParams. - * Please use: - * renderJsonResponse(DataSourceParameters dsParams, ResponseStatus responseStatus, - * DataTable data) - * - * Returns the json response for the given data table. - * - * @param dsParams The datasource parameters. - * @param responseStatus The response status. - * @param data The data table. - * @param True if response should be rendered as jsonp, otherwise False. - * - * @return The json response for the given data table and parameters. - */ - @Deprecated public static CharSequence renderJsonResponse( - DataSourceParameters dsParams, - ResponseStatus responseStatus, - DataTable data, - boolean isJsonp) { - dsParams.setOutputType(OutputType.JSONP); - return renderJsonResponse(dsParams, responseStatus, data); - } - - /** - * Returns the json response for the given data table. - * - * @param dsParams The datasource parameters. If the OutputType parameter is set to - * JSONP the response will be rendered as JSONP. Otherwise a plain JSON string will - * be returned. - * @param responseStatus The response status. - * @param data The data table. - * - * @return The json response for the given data table and parameters. - */ - public static CharSequence renderJsonResponse( - DataSourceParameters dsParams, - ResponseStatus responseStatus, - DataTable data) { - StrBuilder sb = new StrBuilder(); - boolean isJsonp = dsParams.getOutputType() == OutputType.JSONP; - if (isJsonp) { - sb.append(dsParams.getResponseHandler()).append("("); - } - sb.append("{\"version\":\"0.6\""); - - // If no reqId found in the request, do not return reqId in the response. - String requestId = dsParams.getRequestId(); - if (requestId != null) { - sb.append(",\"reqId\":\"").append(EscapeUtil.jsonEscape(requestId)).append("\""); - } - - // Check signature. - String previousSignature = dsParams.getSignature(); - if (responseStatus == null) { - if (!StringUtils.isEmpty(previousSignature) && (data != null) - && (JsonRenderer.getSignature(data).equals(previousSignature))) { - responseStatus = new ResponseStatus(StatusType.ERROR, ReasonType.NOT_MODIFIED, null); - } else { - responseStatus = new ResponseStatus(StatusType.OK, null, null); - } - } - - StatusType statusType = responseStatus.getStatusType(); - sb.append(",\"status\":\"").append(statusType.lowerCaseString()).append("\""); - - // There are reason and messages if the status is WARNING/ERROR. - if (statusType != StatusType.OK) { - // Status is warning or error. - if (statusType == StatusType.WARNING) { - List warnings = data.getWarnings(); - List warningJsonStrings = Lists.newArrayList(); - if (warnings != null) { - for (Warning warning : warnings) { - warningJsonStrings.add(getFaultString(warning.getReasonType(), warning.getMessage())); - } - } - sb.append(",\"warnings\":[").appendWithSeparators(warningJsonStrings, ",").append("]"); - - } else { // Status is error. - sb.append(",\"errors\":["); - sb.append(getFaultString(responseStatus.getReasonType(), responseStatus.getDescription())); - sb.append("]"); - } - } - - if ((statusType != StatusType.ERROR) && (data != null)) { - // MessageType OK or WARNING, - // so need to attach a data table (and a signature). - sb.append(",\"sig\":\"").append(JsonRenderer.getSignature(data)).append("\""); - sb.append(",\"table\":").append(JsonRenderer.renderDataTable(data, true, true, isJsonp)); - } - - sb.append("}"); - if (isJsonp) { - sb.append(");"); - } - - return sb.toString(); - } - - /** - * @deprecated As of version 1.1.1, renderDateAsDateConstructor parameter added. Please use: - * renderDataTable(DataTable dataTable, boolean includeValues, boolean includeFormatting, - * boolean renderDateAsDateConstructor) - * - * Generates a JSON representation of the data table object. - * - * @param includeValues False if the json should contain just meta-data and column descriptions - * but without the data rows. - * @param includeFormatting False if formatting information should be omitted from the - * generated json. - * - * @return The char sequence with the Json string. - */ - @Deprecated public static CharSequence renderDataTable(DataTable dataTable, boolean includeValues, - boolean includeFormatting) { - return renderDataTable(dataTable, includeValues, includeFormatting, true); - } - - /** - * Generates a JSON representation of the data table object. - * - * @param includeValues False if the json should contain just meta-data and column descriptions - * but without the data rows. - * @param includeFormatting False if formatting information should be omitted from the - * generated json. - * @param renderDateAsDateConstructor True -> date constructor, False -> date string. - * True if date values should be rendered into the json string as a call to - * Date object constructor (usually used when rendering jsonp string). - * False if it should should be rendered as string. - * For example, when rendering the date 1/1/2011 as Date object constructor its value - * in the json string will be new Date(2011,1,1), and when rendered as string - * will be "Date(2011,1,1)". For further explanation, see class comment. - * - * @return The char sequence with the Json string. - */ - public static CharSequence renderDataTable(DataTable dataTable, boolean includeValues, - boolean includeFormatting, boolean renderDateAsDateConstructor) { - if (dataTable.getColumnDescriptions().isEmpty()) { - return ""; - } - - List columnDescriptions = dataTable.getColumnDescriptions(); - - StringBuilder sb = new StringBuilder(); - sb.append("{"); - sb.append("\"cols\":["); // column descriptions. - - ColumnDescription col; - for (int colId = 0; colId < columnDescriptions.size(); colId++) { - col = columnDescriptions.get(colId); - appendColumnDescriptionJson(col, sb); - if (colId != (columnDescriptions.size() - 1)) { - sb.append(","); - } - } - sb.append("]"); // columns. - - if (includeValues) { - sb.append(",\"rows\":["); - List cells; - TableCell cell; - ColumnDescription columnDescription; - - List rows = dataTable.getRows(); - for (int rowId = 0; rowId < rows.size(); rowId++) { - TableRow tableRow = rows.get(rowId); - cells = tableRow.getCells(); - sb.append("{\"c\":["); - for (int cellId = 0; cellId < cells.size(); cellId++) { - cell = cells.get(cellId); - if (cellId < (cells.size() - 1)) { - appendCellJson(cell, sb, includeFormatting, false, renderDateAsDateConstructor); - sb.append(","); - } else { - // Last column in the row. - appendCellJson(cell, sb, includeFormatting, true, renderDateAsDateConstructor); - } - } - sb.append("]"); - - // Row properties. - String customPropertiesString = getPropertiesMapString(tableRow.getCustomProperties()); - if (customPropertiesString != null) { - sb.append(",\"p\":").append(customPropertiesString); - } - - sb.append("}"); // cells. - if ((rows.size() - 1) > rowId) { - sb.append(","); - } - } - - sb.append("]"); // rows. - } - - // Table properties. - String customPropertiesString = getPropertiesMapString(dataTable.getCustomProperties()); - if (customPropertiesString != null) { - sb.append(",\"p\":").append(customPropertiesString); - } - - sb.append("}"); // table. - return sb; - } - - /** - * @deprecated As of version 1.1.1, changed visibility to private. - * - * Appends a Json representing a cell to the string buffer. - * - * @param cell The cell to write Json for. - * @param sb The string buffer to append to. - * @param includeFormatting Flase if formatting information should be omitted from the json. - * @param isLastColumn Is this the last column in the row. - * - * @return The input string builder. - */ - @Deprecated public static StringBuilder appendCellJson(TableCell cell, - StringBuilder sb, boolean includeFormatting, boolean isLastColumn) { - return appendCellJson(cell, sb, includeFormatting, isLastColumn, true); - } - - /** - * Appends a Json representing a cell to the string buffer. - * - * @param cell The cell to write Json for. - * @param sb The string buffer to append to. - * @param includeFormatting Flase if formatting information should be omitted from the json. - * @param isLastColumn Is this the last column in the row. - * @param renderDateAsDateConstructor True -> date constructor, False -> date string. - * True if date values should be rendered into the json string as a call to - * Date object constructor (usually used when rendering jsonp string). - * False if it should should be rendered as string. - * For example, when rendering the date 1/1/2011 as Date object constructor its value - * in the json string will be new Date(2011,1,1), and when rendered as string - * will be "Date(2011,1,1)". For further explanation, see class comment. - * - * @return The input string builder. - */ - static StringBuilder appendCellJson(TableCell cell, - StringBuilder sb, boolean includeFormatting, boolean isLastColumn, - boolean renderDateAsDateConstructor) { - Value value = cell.getValue(); - ValueType type = cell.getType(); - StringBuilder valueJson = new StringBuilder(); - GregorianCalendar calendar; - String escapedFormattedString = ""; - boolean isJsonNull = false; - - // Prepare a Json string representing the current value. - DateValue dateValue; - TimeOfDayValue timeOfDayValue; - if ((value == null) || (value.isNull())) { - valueJson.append("null"); - isJsonNull = true; - } else { - switch (type) { - case BOOLEAN: - valueJson.append(((BooleanValue) value).getValue()); - break; - case DATE: - valueJson.append("Date("); - dateValue = (DateValue) value; - valueJson.append(dateValue.getYear()).append(","); - valueJson.append(dateValue.getMonth()).append(","); - valueJson.append(dateValue.getDayOfMonth()); - valueJson.append(")"); - if (renderDateAsDateConstructor) { - // Rendering date as a call to Date constructor, e.g new Date(2011,1,1) - valueJson.insert(0, "new "); - } else { - // Rendering date in string format, e.g "Date(2011,1,1)" - valueJson.insert(0, "\""); - valueJson.append("\""); - } - break; - case NUMBER: - valueJson.append(((NumberValue) value).getValue()); - break; - case TEXT: - valueJson.append("\""); - valueJson.append(EscapeUtil.jsonEscape(value.toString())); - valueJson.append("\""); - break; - case TIMEOFDAY: - valueJson.append("["); - timeOfDayValue = (TimeOfDayValue) value; - valueJson.append(timeOfDayValue.getHours()).append(","); - valueJson.append(timeOfDayValue.getMinutes()).append(","); - valueJson.append(timeOfDayValue.getSeconds()).append(","); - valueJson.append(timeOfDayValue.getMilliseconds()); - valueJson.append("]"); - break; - case DATETIME: - calendar = ((DateTimeValue) value).getCalendar(); - valueJson.append("Date("); - valueJson.append(calendar.get(GregorianCalendar.YEAR)).append(","); - valueJson.append(calendar.get(GregorianCalendar.MONTH)).append(","); - valueJson.append(calendar.get(GregorianCalendar.DAY_OF_MONTH)); - valueJson.append(","); - valueJson.append(calendar.get(GregorianCalendar.HOUR_OF_DAY)); - valueJson.append(","); - valueJson.append(calendar.get(GregorianCalendar.MINUTE)).append(","); - valueJson.append(calendar.get(GregorianCalendar.SECOND)); - valueJson.append(")"); - if (renderDateAsDateConstructor) { - // Rendering date as a call to Date constructor, e.g new Date(2011,1,1,0,0,0) - valueJson.insert(0, "new "); - } else { - // Rendering date in string format, e.g "Date(2011,1,1,0,0,0)" - valueJson.insert(0, "\""); - valueJson.append("\""); - } - break; - default: - throw new IllegalArgumentException("Illegal value Type " + type); - } - } - - // Prepare an escaped string representing the current formatted value. - String formattedValue = cell.getFormattedValue(); - if ((value != null) && !value.isNull() && (formattedValue != null)) { - escapedFormattedString = EscapeUtil.jsonEscape(formattedValue); - // Check for a value of type TEXT if the formatted value equals - // its ordinary toString. - if ((type == ValueType.TEXT) && value.toString().equals(formattedValue)) { - escapedFormattedString = ""; - } - } - - // Add a Json for this cell. And, - // 1) If the formatted value is empty drop it. - // 2) If the value is null, and it is not the last column in the row drop the entire Json. - if ((isLastColumn) || (!isJsonNull)) { - sb.append("{"); - // Value - sb.append("\"v\":").append(valueJson); - // Formatted value - if ((includeFormatting) && (!escapedFormattedString.equals(""))) { - sb.append(",\"f\":\"").append(escapedFormattedString).append("\""); - } - String customPropertiesString = getPropertiesMapString(cell.getCustomProperties()); - if (customPropertiesString != null) { - sb.append(",\"p\":").append(customPropertiesString); - } - sb.append("}"); - } - return sb; - } - - /** - * Appends a Json representing a column description to the string buffer. - * - * @param col The column description to write Json for. - * @param sb The string builder to append to. - * - * @return The input string builder. - */ - public static StringBuilder appendColumnDescriptionJson( - ColumnDescription col, StringBuilder sb) { - sb.append("{"); - sb.append("\"id\":\"").append(EscapeUtil.jsonEscape(col.getId())).append("\","); - sb.append("\"label\":\"").append(EscapeUtil.jsonEscape(col.getLabel())).append("\","); - sb.append("\"type\":\"").append(col.getType().getTypeCodeLowerCase()).append("\","); - sb.append("\"pattern\":\"").append(EscapeUtil.jsonEscape(col.getPattern())).append("\""); - - String customPropertiesString = getPropertiesMapString(col.getCustomProperties()); - if (customPropertiesString != null) { - sb.append(",\"p\":").append(customPropertiesString); - } - - sb.append("}"); - return sb; - } - - /** - * Makes a string from a properties map. - * - * @param propertiesMap The properties map. - * - * @return A json string. - */ - private static String getPropertiesMapString(Map propertiesMap) { - String customPropertiesString = null; - if ((propertiesMap != null) && (!propertiesMap.isEmpty())) { - List customPropertiesStrings = Lists.newArrayList(); - for (Map.Entry entry : propertiesMap.entrySet()) { - customPropertiesStrings.add("\"" - + EscapeUtil.jsonEscape(entry.getKey()) + "\":\"" - + EscapeUtil.jsonEscape(entry.getValue()) + "\""); - } - customPropertiesString = new StrBuilder("{") - .appendWithSeparators(customPropertiesStrings, ",").append("}").toString(); - } - return customPropertiesString; - } -} diff --git a/src/main/java/com/google/visualization/datasource/util/CsvDataSourceException.java b/src/main/java/com/google/visualization/datasource/util/CsvDataSourceException.java deleted file mode 100755 index 10a39bd..0000000 --- a/src/main/java/com/google/visualization/datasource/util/CsvDataSourceException.java +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.util; - -import com.google.visualization.datasource.base.DataSourceException; -import com.google.visualization.datasource.base.ReasonType; - -/** - * An exception concerning the csv data source. - * - * @author Nimrod T. - */ -public class CsvDataSourceException extends DataSourceException { - - /** - * Constructor. - * @param reasonType The reason type. - * @param messageToUser A message that will be displayed to the end user. - */ - public CsvDataSourceException(ReasonType reasonType, String messageToUser) { - super(reasonType, messageToUser); - } -} diff --git a/src/main/java/com/google/visualization/datasource/util/CsvDataSourceHelper.java b/src/main/java/com/google/visualization/datasource/util/CsvDataSourceHelper.java deleted file mode 100755 index 8bd8e6d..0000000 --- a/src/main/java/com/google/visualization/datasource/util/CsvDataSourceHelper.java +++ /dev/null @@ -1,255 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.util; - -import com.google.common.collect.Lists; -import com.google.visualization.datasource.base.DataSourceException; -import com.google.visualization.datasource.base.ReasonType; -import com.google.visualization.datasource.base.TypeMismatchException; -import com.google.visualization.datasource.datatable.ColumnDescription; -import com.google.visualization.datasource.datatable.DataTable; -import com.google.visualization.datasource.datatable.TableRow; -import com.google.visualization.datasource.datatable.ValueFormatter; -import com.google.visualization.datasource.datatable.value.Value; -import com.google.visualization.datasource.datatable.value.ValueType; - -import au.com.bytecode.opencsv.CSVReader; -import com.ibm.icu.util.ULocale; - -import java.io.BufferedReader; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.Reader; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -/** - * Helper class with static utility methods that are specific for building a - * data source based on CSV (Comma Separated Values) files. - * The main functionality is taking a CSV and generating a data table. - * - * @author Nimrod T. - */ -public class CsvDataSourceHelper { - - /** - * Private constructor. All methods are static. - */ - private CsvDataSourceHelper() {} - - /** - * @see #read(java.io.Reader, java.util.List, Boolean, ULocale) - */ - public static DataTable read(Reader reader, List columnDescriptions, - Boolean headerRow) - throws IOException, CsvDataSourceException { - return read(reader, columnDescriptions, headerRow, null); - } - - /** - * Translates a CSV formatted input into a data table representation. - * The reader parameter should point to a CSV file. - * - * @param reader The CSV input Reader from which to read. - * @param columnDescriptions The column descriptions. - * If columnDescriptions is null, then it is assumed that all - * values are strings, and the number of the columns is equal - * to the number of the columns in the first line of the reader. - * If headerRow is set to true, and the columnDescriptions does not - * contain the labels of the columns, then the headerRow values are - * used as the column labels. - * @param headerRow True if there is an header row. - * In that case, the first line of the csv is taken as the header row. - * @param locale An optional locale in which to parse the input csv file. - * If null, uses the default from {@code LocaleUtil#getDefaultLocale}. - * - * @return A data table with the values populated from the CSV file. - * - * @throws IOException In case of error reading from the reader. - * @throws CsvDataSourceException In case of specific csv error. - */ - public static DataTable read(Reader reader, List columnDescriptions, - Boolean headerRow, ULocale locale) - throws IOException, CsvDataSourceException { - DataTable dataTable = new DataTable(); - - if (reader == null) { - return dataTable; - } - - CSVReader csvReader = new CSVReader(reader); - Map defaultFormatters = - ValueFormatter.createDefaultFormatters(locale); - - // Parse the CSV. - String[] line; - boolean firstLine = true; - while ((line = csvReader.readNext()) != null) { - // Being lenient about newlines. - // The reader reads them as lines with - // one element (""). - if ((line.length == 1) && (line[0].equals(""))) { - // This is a new line. - continue; - } - - if ((columnDescriptions != null) && (line.length != columnDescriptions.size())) { - throw new CsvDataSourceException( - ReasonType.INTERNAL_ERROR, - "Wrong number of columns in the data."); - } - if (firstLine) { - // If columnDescriptions is null, create it. - if (columnDescriptions == null) { - columnDescriptions = Lists.newArrayList(); - } - - List tempColumnDescriptions = new ArrayList(); - - // Fill the defaults in the tableDescription. - // This allows easy-to-write table descriptions - // (or even null table descriptions). - for (int i = 0; i < line.length; i++) { - ColumnDescription tempColumnDescription = - (columnDescriptions.isEmpty() || columnDescriptions.get(i) == null) - ? null - : columnDescriptions.get(i); - - String id = - ((tempColumnDescription == null) || (tempColumnDescription.getId() == null)) - ? "Col" + (i) : tempColumnDescription.getId(); - ValueType type = - ((tempColumnDescription == null) || (tempColumnDescription.getType() == null)) - ? ValueType.TEXT : tempColumnDescription.getType(); - String label = - ((tempColumnDescription == null) || (tempColumnDescription.getLabel() == null)) - ? "Column" + i : tempColumnDescription.getLabel(); - String pattern = - ((tempColumnDescription == null) || (tempColumnDescription.getPattern() == null)) - ? "" : tempColumnDescription.getPattern(); - - tempColumnDescription = new ColumnDescription(id, type, label); - tempColumnDescription.setPattern(pattern); - tempColumnDescriptions.add(tempColumnDescription); - } - - // Deal with header rows. - if (headerRow) { - for (int i = 0; i < line.length; i++) { - String string = line[i]; - if (string == null) { - tempColumnDescriptions.get(i).setLabel(""); - } else { - tempColumnDescriptions.get(i).setLabel(line[i].trim()); - } - } - } - - columnDescriptions = tempColumnDescriptions; - dataTable = new DataTable(); - dataTable.addColumns(columnDescriptions); - } - if (!(firstLine && headerRow)) { - // Need to parse the first line as a regular row. - TableRow tableRow = new TableRow(); - for (int i = 0; i < line.length; i++) { - ColumnDescription columnDescription = columnDescriptions.get(i); - ValueType valueType = columnDescription.getType(); - String string = line[i]; - if (string != null) { - string = string.trim(); - } - String pattern = columnDescription.getPattern(); - ValueFormatter valueFormatter; - if (pattern == null || pattern.equals("")) { - valueFormatter = defaultFormatters.get(valueType); - } else { - valueFormatter = ValueFormatter.createFromPattern(valueType, pattern, locale); - } - Value value = valueFormatter.parse(string); - - tableRow.addCell(value); - } - try { - dataTable.addRow(tableRow); - } catch (TypeMismatchException e) { - // Should not happen as we always use the correct types (null if we cannot parse), - // and we check the size of the lines. - } - } - - firstLine = false; - } - - return dataTable; - } - - /** - * Returns a Reader for the url. - * Given a specific url, returns a Reader for that url, - * so that the CSV data source will be able to read the CSV file from that url. - * - * @param url The url to get a Reader for. - * - * @return A Reader for the given url. - * - * @throws DataSourceException In case of a problem reading from the url. - */ - public static Reader getCsvUrlReader(String url) throws DataSourceException { - // Get a Reader. - Reader reader; - try { - reader = new BufferedReader(new InputStreamReader(new URL(url).openStream(), "UTF-8")); - } catch (MalformedURLException e) { - throw new DataSourceException( - ReasonType.INVALID_REQUEST, - "url is malformed: " + url); - } catch (IOException e) { - throw new DataSourceException( - ReasonType.INVALID_REQUEST, - "Couldn't read csv file from url: " + url); - } - return reader; - } - - /** - * Returns a Reader for the file. - * Given a specific file, returns a Reader to that file, - * so that the CSV data source will be able to read the CSV file from that file. - * - * @param file The file to get a Reader for. - * - * @return A Reader for the given file. - * - * @throws DataSourceException In case of a problem reading from the file. - */ - public static Reader getCsvFileReader(String file) throws DataSourceException { - // Get a Reader. - Reader reader = null; - try { - reader = new BufferedReader(new FileReader(file)); - } catch (FileNotFoundException e) { - throw new DataSourceException( - ReasonType.INVALID_REQUEST, - "Couldn't read csv file from: " + file); - } - return reader; - } -} diff --git a/src/main/java/com/google/visualization/datasource/util/SqlDataSourceHelper.java b/src/main/java/com/google/visualization/datasource/util/SqlDataSourceHelper.java deleted file mode 100755 index 723661f..0000000 --- a/src/main/java/com/google/visualization/datasource/util/SqlDataSourceHelper.java +++ /dev/null @@ -1,770 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.util; - -import com.google.common.collect.Lists; -import com.google.visualization.datasource.base.DataSourceException; -import com.google.visualization.datasource.base.ReasonType; -import com.google.visualization.datasource.base.TypeMismatchException; -import com.google.visualization.datasource.datatable.ColumnDescription; -import com.google.visualization.datasource.datatable.DataTable; -import com.google.visualization.datasource.datatable.TableCell; -import com.google.visualization.datasource.datatable.TableRow; -import com.google.visualization.datasource.datatable.value.BooleanValue; -import com.google.visualization.datasource.datatable.value.DateTimeValue; -import com.google.visualization.datasource.datatable.value.DateValue; -import com.google.visualization.datasource.datatable.value.NumberValue; -import com.google.visualization.datasource.datatable.value.TextValue; -import com.google.visualization.datasource.datatable.value.TimeOfDayValue; -import com.google.visualization.datasource.datatable.value.Value; -import com.google.visualization.datasource.datatable.value.ValueType; -import com.google.visualization.datasource.query.AbstractColumn; -import com.google.visualization.datasource.query.AggregationColumn; -import com.google.visualization.datasource.query.AggregationType; -import com.google.visualization.datasource.query.ColumnColumnFilter; -import com.google.visualization.datasource.query.ColumnIsNullFilter; -import com.google.visualization.datasource.query.ColumnSort; -import com.google.visualization.datasource.query.ColumnValueFilter; -import com.google.visualization.datasource.query.ComparisonFilter; -import com.google.visualization.datasource.query.CompoundFilter; -import com.google.visualization.datasource.query.NegationFilter; -import com.google.visualization.datasource.query.Query; -import com.google.visualization.datasource.query.QueryFilter; -import com.google.visualization.datasource.query.QueryGroup; -import com.google.visualization.datasource.query.QuerySelection; -import com.google.visualization.datasource.query.QuerySort; -import com.google.visualization.datasource.query.SimpleColumn; -import com.google.visualization.datasource.query.SortOrder; - -import com.ibm.icu.util.Calendar; -import com.ibm.icu.util.GregorianCalendar; -import com.ibm.icu.util.TimeZone; - -import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang.text.StrBuilder; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.sql.Connection; -import java.sql.Date; -import java.sql.DriverManager; -import java.sql.ResultSet; -import java.sql.ResultSetMetaData; -import java.sql.SQLException; -import java.sql.Statement; -import java.sql.Time; -import java.sql.Timestamp; -import java.sql.Types; -import java.util.List; - - -/** - * A utility class, with static methods that are specific for creating a - * data source based on a SQL database table. - * For now, it can be based on mysql database only. - * - * @author Liron L. - */ -public class SqlDataSourceHelper { - - /** - * Log. - */ - private static final Log log = LogFactory.getLog(SqlDataSourceHelper.class.getName()); - - /** - * A private constructor - all methods are static. - */ - private SqlDataSourceHelper() {} - - /** - * Executes the given query on the given SQL database table, and returns the - * result as a DataTable. - * - * @param query The query. - * @param databaseDescription The information needed to connect to the SQL database and table. - * - * @return DataTable A data table with the data from the specified sql table, - * after applying the specified query on it. - * - * @throws DataSourceException Thrown when the data source fails to perform the action. - */ - public static DataTable executeQuery(Query query, SqlDatabaseDescription databaseDescription) - throws DataSourceException { - Connection con = getDatabaseConnection(databaseDescription); - String tableName = databaseDescription.getTableName(); - - // Build the sql query. - StrBuilder queryStringBuilder = new StrBuilder(); - buildSqlQuery(query, queryStringBuilder, tableName); - List columnIdsList = null; - if (query.hasSelection()) { - columnIdsList = getColumnIdsList(query.getSelection()); - } - Statement stmt = null; - try { - // Execute the sql query. - stmt = con.createStatement(); - ResultSet rs = stmt.executeQuery(queryStringBuilder.toString()); - - DataTable table = buildColumns(rs, columnIdsList); - - // Fill the data in the data table. - buildRows(table, rs); - return table; - } catch (SQLException e) { - String messageToUser = "Failed to execute SQL query. mySQL error message:" - + " " + e.getMessage(); - throw new DataSourceException( - ReasonType.INTERNAL_ERROR, messageToUser); - } finally { - if (stmt != null) { - try { - stmt.close(); - } catch (SQLException e) { /* ignore close errors */ } - } - if (con != null) { - try { - con.close(); - } catch (SQLException e) { /* ignore close errors */ } - } - } - } - - /** - * Returns a connection to the SQL database. - * - * @param databaseDescription The database description. - * - * @return The SQL database connection. - * - * @throws DataSourceException Thrown when the database connection is failed. - */ - private static Connection getDatabaseConnection( - SqlDatabaseDescription databaseDescription) throws DataSourceException{ - Connection con; - // Set the connection's parameters. - String userName = databaseDescription.getUser(); - String password = databaseDescription.getPassword(); - String url = databaseDescription.getUrl(); - try { - // Connect to the database. - // We should add connection pooling to avoid heavy creation of connections. - con = DriverManager.getConnection(url, userName, password); - } catch (SQLException e) { - log.error("Failed to connect to database server.", e); - throw new DataSourceException( - ReasonType.INTERNAL_ERROR, "Failed to connect to database server."); - } - return con; - } - - /** - * Builds the sql query. - * - * @param query The query. - * @param queryStringBuilder A string builder to build the sql query. - * @param tableName The sql table name. - * - * @throws DataSourceException On errors to create the data table. - */ - private static void buildSqlQuery( - Query query, StrBuilder queryStringBuilder, String tableName) - throws DataSourceException { - appendSelectClause(query, queryStringBuilder); - appendFromClause(query, queryStringBuilder, tableName); - appendWhereClause(query, queryStringBuilder); - appendGroupByClause(query, queryStringBuilder); - appendOrderByClause(query, queryStringBuilder); - appendLimitAndOffsetClause(query, queryStringBuilder); - } - - /** - * Appends the LIMIT and OFFSET clause of the sql query to the given string - * builder. If there is no LIMIT on the number of rows, uses the system row - * limit. - * - * @param query The query. - * @param queryStringBuilder The string builder holding the string query. - */ - static void appendLimitAndOffsetClause( - Query query, StrBuilder queryStringBuilder) { - if (query.hasRowLimit()) { - queryStringBuilder.append("LIMIT "); - queryStringBuilder.append(query.getRowLimit()); - } - if (query.hasRowOffset()) { - queryStringBuilder.append(" OFFSET ").append(query.getRowOffset()); - } - } - - /** - * Appends the GROUP BY clause of the sql query to the given string builder. - * - * @param query The query. - * @param queryStringBuilder The string builder holding the string query. - */ - static void appendGroupByClause(Query query, StrBuilder queryStringBuilder) { - if (!query.hasGroup()) { - return; - } - queryStringBuilder.append("GROUP BY "); - QueryGroup queryGroup = query.getGroup(); - List groupColumnIds = queryGroup.getColumnIds(); - List newColumnIds = Lists.newArrayList(); - for (String groupColumnId : groupColumnIds) { - newColumnIds.add('`' + groupColumnId + '`'); - } - queryStringBuilder.appendWithSeparators(newColumnIds, ", "); - queryStringBuilder.append(" "); - } - - /** - * Appends the ORDER BY clause of the sql query to the given string builder. - * - * @param query The query. - * @param queryStringBuilder The string builder holding the string query. - */ - static void appendOrderByClause(Query query, StrBuilder queryStringBuilder) { - if (!query.hasSort()) { - return; - } - queryStringBuilder.append("ORDER BY "); - QuerySort querySort = query.getSort(); - List sortColumns = querySort.getSortColumns(); - int numOfSortColumns = sortColumns.size(); - for (int col = 0; col < numOfSortColumns; col++) { - ColumnSort columnSort = sortColumns.get(col); - queryStringBuilder.append(getColumnId(columnSort.getColumn())); - if (columnSort.getOrder() == SortOrder.DESCENDING) { - queryStringBuilder.append(" DESC"); - } - if (col < numOfSortColumns - 1) { - queryStringBuilder.append(", "); - } - } - queryStringBuilder.append(" "); - } - - /** - * Appends the WHERE clause of the sql query to the given string builder. - * - * @param query The query. - * @param queryStringBuilder The string builder holding the string query. - */ - static void appendWhereClause(Query query, StrBuilder queryStringBuilder) { - if (query.hasFilter()) { - QueryFilter queryFilter = query.getFilter(); - queryStringBuilder.append("WHERE ") - .append(buildWhereClauseRecursively(queryFilter)).append(" "); - } - } - - /** - * Builds the sql WHERE clause recursively from the given query filter. - * The WHERE clause structure is a tree where the leafs are comparison - * filters and the internal nodes are compound filters. The recursion builds - * a string like an in-order walk on the tree. Each filter (i.e. a node in - * the tree) has parenthesis around it. - * - * @param queryFilter The query filter. - * - * @return The sql query WHERE clause as a StrBuilder. - */ - private static StrBuilder buildWhereClauseRecursively(QueryFilter queryFilter) { - StrBuilder whereClause = new StrBuilder(); - - // Base case of the recursion: the filter is not a compound filter. - if (queryFilter instanceof ColumnIsNullFilter) { - buildWhereClauseForIsNullFilter(whereClause, queryFilter); - } else if (queryFilter instanceof ComparisonFilter) { - buildWhereCluaseForComparisonFilter(whereClause, queryFilter); - } else if (queryFilter instanceof NegationFilter) { - whereClause.append("(NOT "); - whereClause.append(buildWhereClauseRecursively( - ((NegationFilter) queryFilter).getSubFilter())); - whereClause.append(")"); - } else { - // queryFilter is a CompoundFilter. - CompoundFilter compoundFilter = (CompoundFilter) queryFilter; - - int numberOfSubFilters = compoundFilter.getSubFilters().size(); - - // If the compound filter is empty, build a where clause according to the - // logical operator: nothing AND nothing -> WHERE "true", nothing OR - // nothing -> WHERE "false" (match the query language rules). - if (numberOfSubFilters == 0) { - if (compoundFilter.getOperator() == CompoundFilter.LogicalOperator.AND) { - whereClause.append("true"); - } else {// OR - whereClause.append("false"); - } - } else { - List filterComponents = Lists.newArrayList(); - for (QueryFilter filter : compoundFilter.getSubFilters()) { - filterComponents.add(buildWhereClauseRecursively(filter).toString()); - } - String logicalOperator = getSqlLogicalOperator(compoundFilter.getOperator()); - whereClause.append("(").appendWithSeparators(filterComponents, " " + logicalOperator + " ") - .append(")"); - } - } - return whereClause; - } - - /** - * Builds a WHERE clause for is-null filter. - * - * @param whereClause A string builder representing the WHERE clause of the SQL query. - * @param queryFilter The query filter. - */ - private static void buildWhereClauseForIsNullFilter(StrBuilder whereClause, - QueryFilter queryFilter) { - ColumnIsNullFilter filter = (ColumnIsNullFilter) queryFilter; - - whereClause.append("(").append(getColumnId(filter.getColumn())).append(" IS NULL)"); - } - - /** - * Builds the WHERE clause for comparison filter. This is the base case of - * the recursive building of the WHERE clause of the sql query. - * - * @param whereClause A string builder representing the WHERE clause of the SQL query. - * @param queryFilter The query filter. - */ - private static void buildWhereCluaseForComparisonFilter( - StrBuilder whereClause, QueryFilter queryFilter) { - StrBuilder first = new StrBuilder(); - StrBuilder second = new StrBuilder(); - - // Build the left part and the right part of the clause according to the filter's type. - if (queryFilter instanceof ColumnColumnFilter) { - ColumnColumnFilter filter = (ColumnColumnFilter) queryFilter; - first.append(getColumnId(filter.getFirstColumn())); - second.append(getColumnId(filter.getSecondColumn())); - } else { // The filter is a ColumnValueFilter - ColumnValueFilter filter = (ColumnValueFilter) queryFilter; - first.append(getColumnId(filter.getColumn())); - second.append(filter.getValue().toString()); - if ((filter.getValue().getType() == ValueType.TEXT) - || (filter.getValue().getType() == ValueType.DATE) - || (filter.getValue().getType() == ValueType.DATETIME) - || (filter.getValue().getType() == ValueType.TIMEOFDAY)) { - second.insert(0, "\""); - second.insert(second.length(), "\""); - } - } - whereClause.append(buildWhereClauseFromRightAndLeftParts( - first, second, ((ComparisonFilter) queryFilter).getOperator())); - } - - /** - * Returns the sql operator of the given CompoundFilter.LogicalOperator as a string. - * - * @param operator The CompoundFilter.LogicalOperator. - * - * @return A string representation of the SQL operator. - */ - private static String getSqlLogicalOperator(CompoundFilter.LogicalOperator operator) { - String stringOperator; - switch (operator) { - case AND: - stringOperator = "AND"; - break; - case OR: - stringOperator = "OR"; - break; - default:// Should never get here. - throw new RuntimeException("Logical operator was not found: " + operator); - } - return stringOperator; - } - - /** - * Builds the where clause of the SQL query sql from the two given values and - * the operator between these two values. - * - * @param value1 The first value in the where clause (either column id or value) - * @param value2 The second value in the where clause (either column id or value) - * @param operator The ComparisonFilter.Operator. - * - * @return A string builder representing the where clause of the SQL query. - */ - private static StrBuilder buildWhereClauseFromRightAndLeftParts( - StrBuilder value1, StrBuilder value2, ComparisonFilter.Operator operator) { - StrBuilder clause; - switch (operator) { - case EQ: - clause = value1.append("=").append(value2); - break; - case NE: - clause = value1.append("<>").append(value2); - break; - case LT: - clause = value1.append("<").append(value2); - break; - case GT: - clause = value1.append(">").append(value2); - break; - case LE: - clause = value1.append("<=").append(value2); - break; - case GE: - clause = value1.append(">=").append(value2); - break; - case CONTAINS: - value2 = new StrBuilder(value2.toString().replace("\"", "")); - clause = value1.append(" LIKE ").append("\"%").append(value2).append("%\""); - break; - case STARTS_WITH: - value2 = new StrBuilder(value2.toString().replace("\"", "")); - clause = value1.append(" LIKE ").append("\"").append(value2).append("%\""); - break; - case ENDS_WITH: - value2 = new StrBuilder(value2.toString().replace("\"", "")); - clause = value1.append(" LIKE ").append("\"%").append(value2).append("\""); - break; - case MATCHES: - throw new RuntimeException("SQL does not support regular expression"); - case LIKE: - value2 = new StrBuilder(value2.toString().replace("\"", "")); - clause = value1.append(" LIKE ").append("\"").append(value2).append("\""); - break; - default:// Should never get here. - throw new RuntimeException("Operator was not found: " + operator); - } - clause.insert(0, "(").append(")"); - return clause; - } - - /** - * Appends the SELECT clause of the sql query to the given string builder. - * - * @param query The query. - * @param queryStringBuilder The string builder holding the string query. - */ - - static void appendSelectClause(Query query, - StrBuilder queryStringBuilder) { - queryStringBuilder.append("SELECT "); - - // If it's a selectAll query, build "select *" clause. - if (!query.hasSelection()) { - queryStringBuilder.append("* "); - return; - } - - List columns = query.getSelection().getColumns(); - int numOfColsInQuery = columns.size(); - - // Add the Ids of the columns to the select clause - for (int col = 0; col < numOfColsInQuery; col++) { - queryStringBuilder.append(getColumnId(columns.get(col))); - if (col < numOfColsInQuery - 1) { - queryStringBuilder.append(", "); - } - } - queryStringBuilder.append(" "); - } - - /** - * Returns the column id in SQL. - * - * @param abstractColumn The column. - * - * @return The column id for the data table. - */ - private static StrBuilder getColumnId(AbstractColumn abstractColumn) { - StrBuilder columnId = new StrBuilder(); - - // For simple column the id is simply the column id. - if (abstractColumn instanceof SimpleColumn) { - columnId.append("`").append(abstractColumn.getId()).append("`"); - } else { - // For aggregation column build the id from the aggregation type and the - // column id (e.g. for aggregation type 'min' and column id 'salary', the - // sql column id will be: min(`salary`); - AggregationColumn aggregationColumn = (AggregationColumn) abstractColumn; - columnId.append(getAggregationFunction( - aggregationColumn.getAggregationType())).append("(`"). - append(aggregationColumn.getAggregatedColumn()).append("`)"); - } - return columnId; - } - - /** - * Returns a list with the selected column ids in the table description. - * - * @param selection The query selection. - * - * @return a list with the selected column ids. - */ - private static List getColumnIdsList(QuerySelection selection) { - List columnIds = - Lists.newArrayListWithCapacity(selection.getColumns().size()); - for (AbstractColumn column : selection.getColumns()) { - columnIds.add(column.getId()); - } - return columnIds; - } - - /** - * Returns a string representation of the given aggregation type. - * - * @param type The aggregation type. - * - * @return The aggragation type's string representation. - */ - private static String getAggregationFunction(AggregationType type) { - return type.getCode(); - } - - /** - * Appends the FROM clause of the sql query to the given string builder. Takes - * the table name from the configuration file. If no table name is given, - * takes the table name from the query. - * - * @param query The query. - * @param queryStringBuilder The string builder holding the string query. - * @param tableName The database table name. - * - * @throws DataSourceException Thrown when no table name provided, or when the - * table name in the data source doesn't match the table name in the - * query. - */ - static void appendFromClause(Query query, - StrBuilder queryStringBuilder, String tableName) - throws DataSourceException { - if (StringUtils.isEmpty(tableName)) { - log.error("No table name provided."); - throw new DataSourceException(ReasonType.OTHER, "No table name provided."); - } - queryStringBuilder.append("FROM "); - queryStringBuilder.append(tableName); - queryStringBuilder.append(" "); - } - - /** - * Returns the table description which includes the ids, labels and types of - * the table columns. - * - * @param rs The result set holding the data from the sql table. - * @param columnIdsList The list of the column ids in the data table. - * - * @return The table description. - * - * @throws SQLException Thrown when the connection to the database failed. - */ - static DataTable buildColumns(ResultSet rs, List columnIdsList) throws SQLException { - DataTable result = new DataTable(); - ResultSetMetaData metaData = rs.getMetaData(); - int numOfCols = metaData.getColumnCount(); - // For each column in the table, create the column description. SQL indexes - // are 1-based. - for (int i = 1; i <= numOfCols; i++) { - String id = (columnIdsList == null) ? metaData.getColumnLabel(i) : - columnIdsList.get(i - 1); - ColumnDescription columnDescription = - new ColumnDescription(id, - sqlTypeToValueType(metaData.getColumnType(i)), - metaData.getColumnLabel(i)); - result.addColumn(columnDescription); - } - return result; - } - - /** - * Converts the given SQL type to a value type. - * - * @param sqlType The sql type to be converted. - * - * @return The value type that fits the given sql type. - */ - private static ValueType sqlTypeToValueType(int sqlType) { - ValueType valueType; - switch (sqlType) { - case Types.BOOLEAN: - case Types.BIT: { - valueType = ValueType.BOOLEAN; - break; - } - case Types.CHAR: - case Types.VARCHAR: - valueType = ValueType.TEXT; - break; - case Types.INTEGER: - case Types.SMALLINT: - case Types.BIGINT: - case Types.TINYINT: - case Types.REAL: - case Types.NUMERIC: - case Types.DOUBLE: - case Types.FLOAT: - case Types.DECIMAL: - valueType = ValueType.NUMBER; - break; - case Types.DATE: - valueType = ValueType.DATE; - break; - case Types.TIME: - valueType = ValueType.TIMEOFDAY; - break; - case Types.TIMESTAMP: - valueType = ValueType.DATETIME; - break; - default: - valueType = ValueType.TEXT; - break; - } - return valueType; - } - - /** - * Populates the data table and returns it. - * - * @param dataTable The data table to populates, that should already contains the - * column descriptions. - * @param rs The result set holding the results of running the query on the - * relevant sql database table. The result set's data required for - * building the rows of the data table. - * - * @throws SQLException Thrown when the connection to the database failed. - */ - static void buildRows(DataTable dataTable, ResultSet rs) throws SQLException { - List columnsDescriptionList = dataTable.getColumnDescriptions(); - int numOfCols = dataTable.getNumberOfColumns(); - - // Get the value types of the columns. - ValueType[] columnsTypeArray = new ValueType[numOfCols]; - for (int c = 0; c < numOfCols; c++) { - columnsTypeArray[c] = columnsDescriptionList.get(c).getType(); - } - - // Build the data table rows, and in each row create the table cells with - // the information in the result set. - while (rs.next()) { - TableRow tableRow = new TableRow(); - for (int c = 0; c < numOfCols; c++) { - tableRow.addCell(buildTableCell(rs, columnsTypeArray[c], c)); - } - try { - dataTable.addRow(tableRow); - } catch (TypeMismatchException e) { - // Should not happen. An SQLException would already have been thrown if there was such a - // problem. - } - } - } - - /** - * Creates a table cell from the value in the current row of the given result - * set and the given column index. The type of the value is determined by the - * given value type. - * - * @param rs The result set holding the data from the sql table. The result - * points to the current row. - * @param valueType The value type of the column that the cell belongs to. - * @param column The column index. Indexes are 0-based. - * - * @return The table cell. - * - * @throws SQLException Thrown when the connection to the database failed. - */ - private static TableCell buildTableCell(ResultSet rs, ValueType valueType, - int column) throws SQLException { - Value value = null; - - // SQL indexes are 1- based. - column = column + 1; - - switch (valueType) { - case BOOLEAN: - value = BooleanValue.getInstance(rs.getBoolean(column)); - break; - case NUMBER: - value = new NumberValue(rs.getDouble(column)); - break; - case DATE: - Date date = rs.getDate(column); - // If date is null it is handled later. - if (date != null) { - GregorianCalendar gc = - new GregorianCalendar(TimeZone.getTimeZone("GMT")); - // Set the year, month and date in the gregorian calendar. - // Use the 'set' method with those parameters, and not the 'setTime' - // method with the date parameter, since the Date object contains the - // current time zone and it's impossible to change it to 'GMT'. - gc.set(date.getYear() + 1900, date.getMonth(), date.getDate()); - value = new DateValue(gc); - } - break; - case DATETIME: - Timestamp timestamp = rs.getTimestamp(column); - // If timestamp is null it is handled later. - if (timestamp != null) { - GregorianCalendar gc = - new GregorianCalendar(TimeZone.getTimeZone("GMT")); - // Set the year, month, date, hours, minutes and seconds in the - // gregorian calendar. Use the 'set' method with those parameters, - // and not the 'setTime' method with the timestamp parameter, since - // the Timestamp object contains the current time zone and it's - // impossible to change it to 'GMT'. - gc.set(timestamp.getYear() + 1900, timestamp.getMonth(), - timestamp.getDate(), timestamp.getHours(), timestamp.getMinutes(), - timestamp.getSeconds()); - // Set the milliseconds explicitly, as they are not saved in the - // underlying date. - gc.set(Calendar.MILLISECOND, timestamp.getNanos() / 1000000); - value = new DateTimeValue(gc); - } - break; - case TIMEOFDAY: - Time time = rs.getTime(column); - // If time is null it is handled later. - if (time != null) { - GregorianCalendar gc = - new GregorianCalendar(TimeZone.getTimeZone("GMT")); - // Set the hours, minutes and seconds of the time in the gregorian - // calendar. Set the year, month and date to be January 1 1970 like - // in the Time object. - // Use the 'set' method with those parameters, - // and not the 'setTime' method with the time parameter, since - // the Time object contains the current time zone and it's - // impossible to change it to 'GMT'. - gc.set(1970, Calendar.JANUARY, 1, time.getHours(), time.getMinutes(), - time.getSeconds()); - // Set the milliseconds explicitly, otherwise the milliseconds from - // the time the gc was initialized are used. - gc.set(GregorianCalendar.MILLISECOND, 0); - value = new TimeOfDayValue(gc); - } - break; - default: - String colValue = rs.getString(column); - if (colValue == null) { - value = TextValue.getNullValue(); - } else { - value = new TextValue(rs.getString(column)); - } - break; - } - // Handle null values. - if (rs.wasNull()) { - return new TableCell(Value.getNullValueFromValueType(valueType)); - } else { - return new TableCell(value); - } - } -} diff --git a/src/main/java/com/google/visualization/datasource/util/SqlDatabaseDescription.java b/src/main/java/com/google/visualization/datasource/util/SqlDatabaseDescription.java deleted file mode 100755 index 4ec18bc..0000000 --- a/src/main/java/com/google/visualization/datasource/util/SqlDatabaseDescription.java +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.util; - -/** - * This class contains all information required to connect to the sql database. - * - * @author Liron L. - */ -public class SqlDatabaseDescription { - - /** - * The url of the sql database. - */ - private String url; - - /** - * The user name used to access the sql database. - */ - private String user; - - /** - * The password used to access the sql database. - */ - private String password; - - /** - * The database table name. Has a {@code null} value in case table name is not provided. - */ - private String tableName; - - /** - * Constructs a sql database description. - * - * @param url The url of the sql databasae. - * @param user The user name to access the sql database. - * @param password The password to access the sql database. - * @param tableName The database table name. - */ - public SqlDatabaseDescription(String url, String user, String password, String tableName) { - this.url = url; - this.user = user; - this.password = password; - this.tableName = tableName; - } - - /** - * Returns the url of the sql databasae. - * - * @return The url of the sql databasae. - */ - public String getUrl() { - return url; - } - - /** - * Returns the user name used to access the sql database. - * - * @return The user name used to access the sql database. - * - */ - public String getUser() { - return user; - } - - /** - * Returns the password used to access the sql database. - * - * @return The password used to access the sql database. - */ - public String getPassword() { - return password; - } - - /** - * Sets the password. - * - * @param password The new password to set. - */ - public void setPassword(String password) { - this.password = password; - } - - /** - * Returns the database table name. - * - * @return The database table name. - */ - public String getTableName() { - return tableName; - } -} diff --git a/src/test/java/com/google/visualization/datasource/DataSourceHelperTest.java b/src/test/java/com/google/visualization/datasource/DataSourceHelperTest.java deleted file mode 100644 index 28bfb5b..0000000 --- a/src/test/java/com/google/visualization/datasource/DataSourceHelperTest.java +++ /dev/null @@ -1,386 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource; - -import com.google.visualization.datasource.base.DataSourceException; -import com.google.visualization.datasource.base.DataSourceParameters; -import com.google.visualization.datasource.base.InvalidQueryException; -import com.google.visualization.datasource.base.TypeMismatchException; -import com.google.visualization.datasource.datatable.ColumnDescription; -import com.google.visualization.datasource.datatable.DataTable; -import com.google.visualization.datasource.datatable.TableRow; -import com.google.visualization.datasource.datatable.value.BooleanValue; -import com.google.visualization.datasource.datatable.value.NumberValue; -import com.google.visualization.datasource.datatable.value.TextValue; -import com.google.visualization.datasource.datatable.value.ValueType; -import com.google.visualization.datasource.query.Query; - -import com.ibm.icu.util.ULocale; - -import junit.framework.TestCase; - -import static org.easymock.EasyMock.*; - -import java.util.ArrayList; -import java.util.Locale; - -import javax.servlet.http.HttpServletRequest; - - -/** - * Unit test for Helper. - * - * @author Yaniv S. - */ -public class DataSourceHelperTest extends TestCase { - - private DataTable createData() throws TypeMismatchException { - DataTable data = new DataTable(); - ArrayList cd = new ArrayList(); - cd.add(new ColumnDescription("name", ValueType.TEXT, "Animal name")); - cd.add(new ColumnDescription("link", ValueType.TEXT, "Link to wikipedia")); - cd.add(new ColumnDescription("population", ValueType.NUMBER, "Population size")); - cd.add(new ColumnDescription("vegeterian", ValueType.BOOLEAN, "Vegeterian?")); - - data.addColumns(cd); - - // Fill the data-table. addRow() needs to be implemented as taking unknown - // number of arguments for this to work. - data.addRowFromValues("Aye-aye", "http://en.wikipedia.org/wiki/Aye-aye", 100, true); - data.addRowFromValues("Sloth", "http://en.wikipedia.org/wiki/Sloth", 300, true); - data.addRowFromValues("Leopard", "http://en.wikipedia.org/wiki/Leopard", 50, false); - data.addRowFromValues("Tiger", "http://en.wikipedia.org/wiki/Tiger", 80, false); - - return data; - } - - /** - * Test applyQuery method. - */ - public void testApplyQuery() throws InvalidQueryException, DataSourceException, - TypeMismatchException { - DataTable data = createData(); - - // Test select. - DataTable result = DataSourceHelper.applyQuery(DataSourceHelper.parseQuery("select population"), - data, ULocale.US); - assertEquals(1, result.getNumberOfColumns()); - assertEquals(4, result.getNumberOfRows()); - assertEquals(new NumberValue(300), result.getRow(1).getCell(0).getValue()); - - data = createData(); - - // Test where. - result = DataSourceHelper.applyQuery(DataSourceHelper.parseQuery( - "select name,vegeterian where population > 100"), data, ULocale.US); - assertEquals(2, result.getNumberOfColumns()); - assertEquals(1, result.getNumberOfRows()); - assertEquals(new TextValue("Sloth"), result.getRow(0).getCell(0).getValue()); - assertEquals(BooleanValue.TRUE, result.getRow(0).getCell(1).getValue()); - - data = createData(); - - // Test group by. - result = DataSourceHelper.applyQuery(DataSourceHelper.parseQuery( - "select vegeterian,sum(population) group by vegeterian"), data, ULocale.US); - assertEquals(2, result.getNumberOfColumns()); - assertEquals(2, result.getNumberOfRows()); - assertEquals(BooleanValue.FALSE, result.getRow(0).getCell(0).getValue()); - assertEquals(new NumberValue(130), result.getRow(0).getCell(1).getValue()); - - data = createData(); - - // Test pivot. - result = DataSourceHelper.applyQuery(DataSourceHelper.parseQuery( - "select sum(population) pivot vegeterian"), data, ULocale.US); - assertEquals(2, result.getNumberOfColumns()); - assertEquals(1, result.getNumberOfRows()); - assertEquals("false", result.getColumnDescription(0).getLabel()); - assertEquals(new NumberValue(130), result.getRow(0).getCell(0).getValue()); - - data = createData(); - - // Test order by. - result = DataSourceHelper.applyQuery(DataSourceHelper.parseQuery( - "select name order by population"), data, ULocale.US); - assertEquals(1, result.getNumberOfColumns()); - assertEquals(4, result.getNumberOfRows()); - assertEquals(new TextValue("Leopard"), result.getRow(0).getCell(0).getValue()); - assertEquals(new TextValue("Tiger"), result.getRow(1).getCell(0).getValue()); - assertEquals(new TextValue("Aye-aye"), result.getRow(2).getCell(0).getValue()); - assertEquals(new TextValue("Sloth"), result.getRow(3).getCell(0).getValue()); - - data = createData(); - - // Test limit and offset. - result = DataSourceHelper.applyQuery(DataSourceHelper.parseQuery("limit 1 offset 1"), data, - ULocale.US); - assertEquals(4, result.getNumberOfColumns()); - assertEquals(1, result.getNumberOfRows()); - assertEquals(new TextValue("Sloth"), result.getRow(0).getCell(0).getValue()); - - data = createData(); - - // Test label and format. - result = DataSourceHelper.applyQuery(DataSourceHelper.parseQuery( - "label population 'Population size (thousands)' format population \"'$'#'k'\""), data, - ULocale.US); - assertEquals(4, result.getNumberOfColumns()); - assertEquals(4, result.getNumberOfRows(), 4); - assertEquals("Population size (thousands)", - result.getColumnDescription("population").getLabel()); - int populationIndex = result.getColumnIndex("population"); - assertEquals("$100k", result.getRow(0).getCell(populationIndex).getFormattedValue()); - - // Test that validation can fail - try { - DataSourceHelper.parseQuery("select min(min(a))"); - fail(); - } catch (InvalidQueryException e) { - // Do nothing. - } - - // Test that validation against the table description can fail. - Query q = DataSourceHelper.parseQuery("select avg(name) group by link"); - try { - DataSourceHelper.applyQuery(q, data, ULocale.US); - fail(); - } catch (InvalidQueryException e) { - // Do nothing. - } - } - - /** - * Test genereateResponse method. - * - * @throws DataSourceException - */ - public void testGenerateResponse() throws DataSourceException { - // Check with simple data table and simple data source parameters. - DataTable dataTable = new DataTable(); - dataTable.addColumn(new ColumnDescription("col1", ValueType.NUMBER, "column1")); - dataTable.addColumn(new ColumnDescription("col2", ValueType.BOOLEAN, "column2")); - dataTable.addColumn(new ColumnDescription("col3", ValueType.TEXT, "column3")); - TableRow tableRow = new TableRow(); - tableRow.addCell(7); - tableRow.addCell(false); - tableRow.addCell("Why?"); - dataTable.addRow(tableRow); - - DataSourceRequest dataSourceRequest = new DataSourceRequest( - new Query(), - new DataSourceParameters(null), - ULocale.UK); - assertEquals( - "{\"version\":\"0.6\",\"status\":\"ok\",\"sig\":\"1548939605\"," - + "\"table\":{\"cols\":[{\"id\":\"col1\",\"label\":\"column1\"," - + "\"type\":\"number\",\"pattern\":\"\"}," - + "{\"id\":\"col2\",\"label\":\"column2\",\"type\":\"boolean\",\"pattern\":\"\"}," - + "{\"id\":\"col3\",\"label\":\"column3\",\"type\":\"string\",\"pattern\":\"\"}]," - + "\"rows\":[{\"c\":[{\"v\":7.0},{\"v\":false},{\"v\":\"Why?\"}]}]}}", - DataSourceHelper.generateResponse(dataTable, dataSourceRequest)); - - // With reqId:666; - dataSourceRequest = new DataSourceRequest( - new Query(), - new DataSourceParameters("reqId:666"), - ULocale.UK); - assertEquals( - "{\"version\":\"0.6\",\"reqId\":\"666\",\"status\":\"ok\",\"sig\":\"1548939605\"," - + "\"table\":{\"cols\":[{\"id\":\"col1\",\"label\":\"column1\"," - + "\"type\":\"number\",\"pattern\":\"\"}," - + "{\"id\":\"col2\",\"label\":\"column2\",\"type\":\"boolean\",\"pattern\":\"\"}," - + "{\"id\":\"col3\",\"label\":\"column3\",\"type\":\"string\",\"pattern\":\"\"}]," - + "\"rows\":[{\"c\":[{\"v\":7.0},{\"v\":false},{\"v\":\"Why?\"}]}]}}", - DataSourceHelper.generateResponse(dataTable, dataSourceRequest)); - - // With out:json; - dataSourceRequest = new DataSourceRequest( - new Query(), - new DataSourceParameters("out:json"), - ULocale.UK); - assertEquals( - "{\"version\":\"0.6\",\"status\":\"ok\",\"sig\":\"1548939605\"," - + "\"table\":{\"cols\":[{\"id\":\"col1\",\"label\":\"column1\"," - + "\"type\":\"number\",\"pattern\":\"\"}," - + "{\"id\":\"col2\",\"label\":\"column2\",\"type\":\"boolean\",\"pattern\":\"\"}," - + "{\"id\":\"col3\",\"label\":\"column3\",\"type\":\"string\",\"pattern\":\"\"}]," - + "\"rows\":[{\"c\":[{\"v\":7.0},{\"v\":false},{\"v\":\"Why?\"}]}]}}", - DataSourceHelper.generateResponse(dataTable, dataSourceRequest)); - - // With out:jsonp; - dataSourceRequest = new DataSourceRequest( - new Query(), - new DataSourceParameters("out:jsonp"), - ULocale.UK); - assertEquals( - "// Data table response\ngoogle.visualization.Query.setResponse(" - + "{\"version\":\"0.6\",\"status\":\"ok\",\"sig\":\"1548939605\"," - + "\"table\":{\"cols\":[{\"id\":\"col1\",\"label\":\"column1\"," - + "\"type\":\"number\",\"pattern\":\"\"}," - + "{\"id\":\"col2\",\"label\":\"column2\",\"type\":\"boolean\",\"pattern\":\"\"}," - + "{\"id\":\"col3\",\"label\":\"column3\",\"type\":\"string\",\"pattern\":\"\"}]," - + "\"rows\":[{\"c\":[{\"v\":7.0},{\"v\":false},{\"v\":\"Why?\"}]}]}});", - DataSourceHelper.generateResponse(dataTable, dataSourceRequest)); - - // Now with out:csv; - dataSourceRequest = new DataSourceRequest( - new Query(), - new DataSourceParameters("out:tsv-excel"), - ULocale.UK); - assertEquals( - "\"column1\"\t\"column2\"\t\"column3\"\n7\tfalse\t\"Why?\"\n", - DataSourceHelper.generateResponse(dataTable, dataSourceRequest)); - - // Now with out:tsv-excel; - dataSourceRequest = new DataSourceRequest( - new Query(), - new DataSourceParameters("out:csv;reqId:7"), - ULocale.UK); - assertEquals( - "\"column1\",\"column2\",\"column3\"\n7,false,\"Why?\"\n", - DataSourceHelper.generateResponse(dataTable, dataSourceRequest)); - } - - - public void testGetLocaleFromReuqest() { - HttpServletRequest req = createMock(HttpServletRequest.class); - expect(req.getParameter(DataSourceHelper.LOCALE_REQUEST_PARAMETER)).andReturn("fr"); - expect(req.getParameter(DataSourceHelper.LOCALE_REQUEST_PARAMETER)).andReturn(null); - expect(req.getLocale()).andReturn(Locale.CANADA_FRENCH); - replay(req); - - assertEquals(Locale.FRENCH, DataSourceHelper.getLocaleFromRequest(req).toLocale()); - assertEquals(ULocale.CANADA_FRENCH, DataSourceHelper.getLocaleFromRequest(req)); - - verify(req); - } - - public void testVerifyAccessApprovedTest() throws DataSourceException { - HttpServletRequest req = createNiceMock(HttpServletRequest.class); - - // Verify that json from same domain is approved. - setupHttpRequestMock(req, true, "out:json"); - DataSourceHelper.verifyAccessApproved(new DataSourceRequest(req)); - verify(req); - - // Verify that json from cross domain is denied. - setupHttpRequestMock(req, false, "out:json"); - try { - DataSourceHelper.verifyAccessApproved(new DataSourceRequest(req)); - fail(); - } catch (DataSourceException e) { - // This is the expected behavior. - } - verify(req); - - // Verify that csv from cross domain is approved. - setupHttpRequestMock(req, false, "out:csv"); - DataSourceHelper.verifyAccessApproved(new DataSourceRequest(req)); - verify(req); - - // Verify that html from cross domain is approved. - setupHttpRequestMock(req, false, "out:html"); - DataSourceHelper.verifyAccessApproved(new DataSourceRequest(req)); - verify(req); - - // Verify that tsv-excel from cross domain is approved. - setupHttpRequestMock(req, false, "out:tsv-excel"); - DataSourceHelper.verifyAccessApproved(new DataSourceRequest(req)); - verify(req); - } - - public void testParseQueryErrors() { - DataTable dataTable = new DataTable(); - dataTable.addColumn(new ColumnDescription("A", ValueType.TEXT, "column1")); - dataTable.addColumn(new ColumnDescription("B", ValueType.BOOLEAN, "column2")); - dataTable.addColumn(new ColumnDescription("C", ValueType.NUMBER, "column3")); - // Wrong column id - checkQueryError("select D", dataTable, "Column [D] does not exist in table."); - checkQueryError("where F > 1", dataTable, "Column [F] does not exist in table."); - // aggregation sum and average only on numeric columns - checkQueryError("select avg(A) group by B", dataTable, - "'Average' and 'sum' aggreagation functions can be applied only on numeric values."); - checkQueryError("select sum(A) group by B", dataTable, - "'Average' and 'sum' aggreagation functions can be applied only on numeric values."); - checkQueryError("select sum(B) group by A", dataTable, - "'Average' and 'sum' aggreagation functions can be applied only on numeric values."); - // parse errors - checkQueryError("select (", dataTable, "Query parse error: ", true); - checkQueryError("group by avg(A)", dataTable, - "Column [AVG(`A`)] cannot be in GROUP BY because it has an aggregation."); - checkQueryError("pivot avg(A)", dataTable, - "Column [AVG(`A`)] cannot be in PIVOT because it has an aggregation."); - checkQueryError("where avg(A) > 1", dataTable, - "Column [AVG(`A`)] cannot appear in WHERE because it has an aggregation."); - checkQueryError("select A, sum(A)", dataTable, - "Column [A] cannot be selected both with and without aggregation in SELECT."); - checkQueryError("select sum(C) group by C", dataTable, - "Column [C] which is aggregated in SELECT, cannot appear in GROUP BY."); - checkQueryError("select A group by C", dataTable, - "Cannot use GROUP BY when no aggregations are defined in SELECT."); - checkQueryError("select A pivot C", dataTable, - "Cannot use PIVOT when no aggregations are defined in SELECT."); - checkQueryError("select min(B) pivot B", dataTable, - "Column [B] which is aggregated in SELECT, cannot appear in PIVOT."); - checkQueryError("select A format B 'yes:no'", dataTable, - "Column [`B`] which is referenced in FORMAT, is not part of SELECT clause."); - checkQueryError("select A label B 'COL'", dataTable, - "Column [`B`] which is referenced in LABEL, is not part of SELECT clause."); - checkQueryError("select A,count(B)", dataTable, - "Column [A] should be added to GROUP BY, removed from SELECT, or aggregated in SELECT."); - checkQueryError("select B order by min(A)", dataTable, - "Aggregation [MIN(`A`)] found in ORDER BY but was not found in SELECT"); - checkQueryError("select min(A) pivot B order by min(A)", dataTable, - "Column [A] cannot be aggregated in ORDER BY when PIVOT is used."); - checkQueryError("select min(A) order by B", dataTable, - "Column [`B`] which appears in ORDER BY, must be in SELECT as well, " + - "because SELECT contains aggregated columns."); - checkQueryError("select min(A) group by B pivot B", dataTable, - "Column [B] cannot appear both in GROUP BY and in PIVOT."); - checkQueryError("offset -1", dataTable, - "Invalid value for row offset: -1"); - checkQueryError("select avg(C),avg(C)", dataTable, - "Column [avg(C)] cannot appear more than once in SELECT."); - } - - private void checkQueryError(String query, DataTable dataTable, String expectedMessage) { - checkQueryError(query, dataTable, expectedMessage, false); - } - - private void checkQueryError(String query, DataTable dataTable, String expectedMessage, - boolean startsWith) { - try { - DataSourceHelper.applyQuery( - DataSourceHelper.parseQuery(query), dataTable, null); - fail("Exception should be thrown for query " + query); - } catch (DataSourceException dse) { - if (startsWith) { - assertNotNull(dse.getMessageToUser()); - assertTrue(dse.getMessageToUser().startsWith(expectedMessage)); - } else { - assertEquals(expectedMessage, dse.getMessageToUser()); - } - } - } - - private void setupHttpRequestMock(HttpServletRequest req, boolean hasHeader, String tqx) { - reset(req); - expect(req.getHeader(DataSourceRequest.SAME_ORIGIN_HEADER)).andReturn(hasHeader ? "a" : null); - expect(req.getParameter(DataSourceRequest.DATASOURCE_REQUEST_PARAMETER)).andReturn(tqx); - replay(req); - } -} - diff --git a/src/test/java/com/google/visualization/datasource/DataSourceRequestTest.java b/src/test/java/com/google/visualization/datasource/DataSourceRequestTest.java deleted file mode 100644 index 616de25..0000000 --- a/src/test/java/com/google/visualization/datasource/DataSourceRequestTest.java +++ /dev/null @@ -1,147 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource; - -import com.google.visualization.datasource.base.DataSourceException; -import com.google.visualization.datasource.base.OutputType; - -import com.ibm.icu.util.ULocale; - -import junit.framework.TestCase; - -import org.easymock.EasyMock; - -import java.util.Locale; - -import javax.servlet.http.HttpServletRequest; - -/** - * Unit test for data source request. - * - * @author Nimrod T. - */ -public class DataSourceRequestTest extends TestCase { - - /** - * Test simple constructor. - */ - public void testConstructor() { - // Test with hl == fr, out:csv, same-domain. - DataSourceRequest dataSourceRequest = null; - boolean caught = false; - try { - HttpServletRequest req = EasyMock.createMock(HttpServletRequest.class); - EasyMock.expect(req.getParameter("hl")).andReturn("fr"); - EasyMock.expect(req.getHeader("X-DataSource-Auth")).andReturn("a"); - EasyMock.expect(req.getParameter("tqx")).andReturn("out:csv;"); - EasyMock.expect(req.getParameter("tq")).andReturn(null); - EasyMock.replay(req); - dataSourceRequest = new DataSourceRequest(req); - EasyMock.verify(req); - } catch (DataSourceException e) { - caught = true; - } - assertFalse(caught); - assertEquals(new ULocale("fr"), dataSourceRequest.getUserLocale()); - assertTrue(dataSourceRequest.isSameOrigin()); - assertEquals(OutputType.CSV, dataSourceRequest.getDataSourceParameters().getOutputType()); - - // Test with hl == it, not same-domain. - dataSourceRequest = null; - caught = false; - try { - HttpServletRequest req = EasyMock.createMock(HttpServletRequest.class); - EasyMock.expect(req.getParameter("hl")).andReturn("it"); - EasyMock.expect(req.getHeader("X-DataSource-Auth")).andReturn(null); - EasyMock.expect(req.getParameter("tqx")).andReturn(null); - EasyMock.expect(req.getParameter("tq")).andReturn(null); - EasyMock.replay(req); - dataSourceRequest = new DataSourceRequest(req); - EasyMock.verify(req); - } catch (DataSourceException e) { - caught = true; - } - assertFalse(caught); - assertEquals(new ULocale("it"), dataSourceRequest.getUserLocale()); - assertFalse(dataSourceRequest.isSameOrigin()); - assertEquals(OutputType.JSONP, dataSourceRequest.getDataSourceParameters().getOutputType()); - } - - /** - * Test simple constructor. - */ - public void testGetDefaultDataSourceRequest() { - // Test with hl == fr, out:csv, same-domain. - DataSourceRequest dataSourceRequest; - HttpServletRequest req = EasyMock.createMock(HttpServletRequest.class); - EasyMock.expect(req.getParameter("hl")).andReturn("fr"); - EasyMock.expect(req.getHeader("X-DataSource-Auth")).andReturn("a"); - EasyMock.expect(req.getParameter("tqx")).andReturn("out:csv;"); - EasyMock.expect(req.getParameter("tq")).andReturn(null); - EasyMock.replay(req); - dataSourceRequest = DataSourceRequest.getDefaultDataSourceRequest(req); - EasyMock.verify(req); - assertEquals(new ULocale("fr"), dataSourceRequest.getUserLocale()); - assertTrue(dataSourceRequest.isSameOrigin()); - assertEquals(OutputType.CSV, dataSourceRequest.getDataSourceParameters().getOutputType()); - - // Test with empty request (only locale). - dataSourceRequest = null; - req = EasyMock.createMock(HttpServletRequest.class); - EasyMock.expect(req.getParameter("hl")).andReturn(null); - EasyMock.expect(req.getLocale()).andReturn(new Locale("qq")); - EasyMock.expect(req.getHeader("X-DataSource-Auth")).andReturn(null); - EasyMock.expect(req.getParameter("tqx")).andReturn(null); - EasyMock.expect(req.getParameter("tq")).andReturn(null); - EasyMock.replay(req); - dataSourceRequest = DataSourceRequest.getDefaultDataSourceRequest(req); - EasyMock.verify(req); - assertEquals(new ULocale("qq"), dataSourceRequest.getUserLocale()); - assertFalse(dataSourceRequest.isSameOrigin()); - assertEquals(OutputType.JSONP, dataSourceRequest.getDataSourceParameters().getOutputType()); - - // Test with hl == it, not same-domain. - dataSourceRequest = null; - req = EasyMock.createMock(HttpServletRequest.class); - EasyMock.expect(req.getParameter("hl")).andReturn("it"); - EasyMock.expect(req.getHeader("X-DataSource-Auth")).andReturn(null); - EasyMock.expect(req.getParameter("tqx")).andReturn(null); - EasyMock.expect(req.getParameter("tq")).andReturn(null); - EasyMock.replay(req); - dataSourceRequest = DataSourceRequest.getDefaultDataSourceRequest(req); - EasyMock.verify(req); - assertEquals(new ULocale("it"), dataSourceRequest.getUserLocale()); - assertFalse(dataSourceRequest.isSameOrigin()); - assertEquals(OutputType.JSONP, dataSourceRequest.getDataSourceParameters().getOutputType()); - } - - public void testDetermineSameOrigin() { - HttpServletRequest req = EasyMock.createMock(HttpServletRequest.class); - EasyMock.expect(req.getHeader( - DataSourceRequest.SAME_ORIGIN_HEADER)).andReturn("not null"); - EasyMock.replay(req); - assertTrue("Request should be same origin", - DataSourceRequest.determineSameOrigin(req)); - EasyMock.verify(req); - - req = EasyMock.createMock(HttpServletRequest.class); - EasyMock.expect(req.getHeader( - DataSourceRequest.SAME_ORIGIN_HEADER)).andReturn(null); - EasyMock.replay(req); - assertFalse("Request should not be same origin", - DataSourceRequest.determineSameOrigin(req)); - EasyMock.verify(req); - } -} diff --git a/src/test/java/com/google/visualization/datasource/QuerySplitterTest.java b/src/test/java/com/google/visualization/datasource/QuerySplitterTest.java deleted file mode 100644 index 26b4491..0000000 --- a/src/test/java/com/google/visualization/datasource/QuerySplitterTest.java +++ /dev/null @@ -1,438 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource; - -import com.google.common.collect.Lists; -import com.google.visualization.datasource.datatable.value.TextValue; -import com.google.visualization.datasource.query.AbstractColumn; -import com.google.visualization.datasource.query.AggregationColumn; -import com.google.visualization.datasource.query.AggregationType; -import com.google.visualization.datasource.query.ColumnIsNullFilter; -import com.google.visualization.datasource.query.ColumnSort; -import com.google.visualization.datasource.query.ColumnValueFilter; -import com.google.visualization.datasource.query.ComparisonFilter; -import com.google.visualization.datasource.query.Query; -import com.google.visualization.datasource.query.QueryFilter; -import com.google.visualization.datasource.query.QueryFormat; -import com.google.visualization.datasource.query.QueryGroup; -import com.google.visualization.datasource.query.QueryLabels; -import com.google.visualization.datasource.query.QueryOptions; -import com.google.visualization.datasource.query.QueryPivot; -import com.google.visualization.datasource.query.QuerySelection; -import com.google.visualization.datasource.query.QuerySort; -import com.google.visualization.datasource.query.ScalarFunctionColumn; -import com.google.visualization.datasource.query.SimpleColumn; -import com.google.visualization.datasource.query.SortOrder; -import com.google.visualization.datasource.query.scalarfunction.TimeComponentExtractor; - -import junit.framework.TestCase; - -import java.util.List; - - -/** - * A test for the QuerySplitter class. - * - * @author Yonatan B.Y. - */ -public class QuerySplitterTest extends TestCase { - - /** - * Holds some default query for the tests. - */ - private Query q = null; - - /** - * Sets up the default query. - */ - @Override - public void setUp() throws Exception { - q = new Query(); - QuerySelection selection = new QuerySelection(); - selection.addColumn(new SimpleColumn("A")); - selection.addColumn(new AggregationColumn(new SimpleColumn("B"), AggregationType.MAX)); - q.setSelection(selection); - QuerySort sort = new QuerySort(); - sort.addSort(new ColumnSort(new SimpleColumn("A"), SortOrder.DESCENDING)); - q.setSort(sort); - QueryFilter filter = new ColumnValueFilter(new SimpleColumn("A"), new TextValue("foo"), - ComparisonFilter.Operator.GT); - q.setFilter(filter); - q.setRowLimit(7); - q.setRowOffset(17); - QueryLabels labels = new QueryLabels(); - labels.addLabel(new SimpleColumn("A"), "bar"); - q.setLabels(labels); - QueryFormat format = new QueryFormat(); - format.addPattern(new SimpleColumn("A"), "foo"); - q.setUserFormatOptions(format); - QueryOptions options = new QueryOptions(); - options.setNoFormat(true); - q.setOptions(options); - QueryGroup group = new QueryGroup(); - group.addColumn(new SimpleColumn("A")); - q.setGroup(group); - QueryPivot pivot = new QueryPivot(); - pivot.addColumn(new SimpleColumn("C")); - q.setPivot(pivot); - } - - /** - * Tests the query splitter with a datasource with SQL CapabilitySet, when the - * query contains a pivot statement. - */ - public void testSplitSQLWithPivot() throws Exception { - QueryPair split = QuerySplitter.splitQuery(q, Capabilities.SQL); - Query dataSourceQuery = split.getDataSourceQuery(); - Query completionQuery = split.getCompletionQuery(); - - QuerySelection selection = dataSourceQuery.getSelection(); - List columns = selection.getColumns(); - assertEquals(3, columns.size()); - assertEquals("A", ((SimpleColumn) columns.get(0)).getId()); - assertEquals("B", ((AggregationColumn) columns.get(1)).getAggregatedColumn().getId()); - assertEquals(AggregationType.MAX, ((AggregationColumn) columns.get(1)).getAggregationType()); - assertEquals("C", ((SimpleColumn) columns.get(2)).getId()); - assertFalse(dataSourceQuery.hasSort()); - ColumnValueFilter filter = (ColumnValueFilter) dataSourceQuery.getFilter(); - assertEquals("A", ((SimpleColumn) filter.getColumn()).getId()); - assertFalse(dataSourceQuery.hasRowSkipping()); - assertFalse(dataSourceQuery.hasRowLimit()); - assertFalse(dataSourceQuery.hasRowOffset()); - assertFalse(dataSourceQuery.hasOptions()); - assertFalse(dataSourceQuery.hasLabels()); - assertFalse(dataSourceQuery.hasUserFormatOptions()); - assertFalse(dataSourceQuery.hasPivot()); - columns = dataSourceQuery.getGroup().getColumns(); - assertEquals(2, columns.size()); - assertEquals("A", ((SimpleColumn) columns.get(0)).getId()); - assertEquals("C", ((SimpleColumn) columns.get(1)).getId()); - - selection = completionQuery.getSelection(); - columns = selection.getColumns(); - assertEquals(2, columns.size()); - assertEquals("A", ((SimpleColumn) columns.get(0)).getId()); - assertEquals("max-B", ((AggregationColumn) columns.get(1)).getAggregatedColumn().getId()); - assertEquals(AggregationType.MIN, ((AggregationColumn) columns.get(1)).getAggregationType()); - assertFalse(completionQuery.hasFilter()); - columns = completionQuery.getSort().getColumns(); - assertEquals(1, columns.size()); - assertEquals("A", ((SimpleColumn) columns.get(0)).getId()); - assertEquals(7, completionQuery.getRowLimit()); - assertEquals(17, completionQuery.getRowOffset()); - assertTrue(completionQuery.getOptions().isNoFormat()); - assertTrue(completionQuery.hasLabels()); - assertTrue(completionQuery.hasUserFormatOptions()); - columns = completionQuery.getGroup().getColumns(); - assertEquals(1, columns.size()); - assertEquals("A", ((SimpleColumn) columns.get(0)).getId()); - columns = completionQuery.getPivot().getColumns(); - assertEquals(1, columns.size()); - assertEquals("C", ((SimpleColumn) columns.get(0)).getId()); - } - - /** - * Tests the query splitter with a datasource with SQL CapabilitySet, when the - * query does not contain a pivot statement. - */ - public void testSplitSQLWithoutPivot() throws Exception { - q.setPivot(null); - AggregationColumn maxB = new AggregationColumn(new SimpleColumn("B"), AggregationType.MAX); - q.getLabels().addLabel(maxB, "maxBLabel"); - q.getUserFormatOptions().addPattern(maxB, "maxB#"); - QueryPair split = QuerySplitter.splitQuery(q, Capabilities.SQL); - Query dataSourceQuery = split.getDataSourceQuery(); - Query completionQuery = split.getCompletionQuery(); - - QuerySelection selection = dataSourceQuery.getSelection(); - List columns = selection.getColumns(); - assertEquals(2, columns.size()); - assertEquals("A", ((SimpleColumn) columns.get(0)).getId()); - assertEquals("B", ((AggregationColumn) columns.get(1)).getAggregatedColumn().getId()); - assertEquals(AggregationType.MAX, ((AggregationColumn) columns.get(1)).getAggregationType()); - columns = dataSourceQuery.getSort().getColumns(); - assertEquals(1, columns.size()); - assertEquals("A", ((SimpleColumn) columns.get(0)).getId()); - ColumnValueFilter filter = (ColumnValueFilter) dataSourceQuery.getFilter(); - assertEquals("A", ((SimpleColumn) filter.getColumn()).getId()); - assertEquals(7, dataSourceQuery.getRowLimit()); - assertEquals(17, dataSourceQuery.getRowOffset()); - assertFalse(dataSourceQuery.hasOptions()); - assertFalse(dataSourceQuery.hasLabels()); - assertFalse(dataSourceQuery.hasUserFormatOptions()); - assertFalse(dataSourceQuery.hasPivot()); - columns = dataSourceQuery.getGroup().getColumns(); - assertEquals(1, columns.size()); - assertEquals("A", ((SimpleColumn) columns.get(0)).getId()); - - assertFalse(completionQuery.hasSelection()); - assertFalse(completionQuery.hasFilter()); - assertFalse(completionQuery.hasSort()); - assertFalse(completionQuery.hasRowLimit()); - assertFalse(completionQuery.hasRowOffset()); - assertTrue(completionQuery.getOptions().isNoFormat()); - assertTrue(completionQuery.hasLabels()); - // Test that labels and formats changed appropriately - AbstractColumn[] labelColumns = - completionQuery.getLabels().getColumns().toArray(new AbstractColumn[]{}); - if (labelColumns[1].getId().equals("A")) { - AbstractColumn tmp = labelColumns[0]; - labelColumns[0] = labelColumns[1]; - labelColumns[1] = tmp; - } - assertEquals(2, labelColumns.length); - assertEquals("A", labelColumns[0].getId()); - AbstractColumn col = labelColumns[1]; - assertTrue(col instanceof SimpleColumn); - assertEquals("max-B", ((SimpleColumn) col).getId()); - assertEquals("maxBLabel", completionQuery.getLabels().getLabel(col)); - AbstractColumn[] formatColumns = - completionQuery.getUserFormatOptions().getColumns().toArray(new AbstractColumn[]{}); - if (formatColumns[1].getId().equals("A")) { - AbstractColumn tmp = formatColumns[0]; - formatColumns[0] = formatColumns[1]; - formatColumns[1] = tmp; - } - assertEquals(2, formatColumns.length); - assertEquals("A", formatColumns[0].getId()); - col = formatColumns[1]; - assertTrue(col instanceof SimpleColumn); - assertEquals("max-B", ((SimpleColumn) col).getId()); - assertEquals("maxB#", completionQuery.getUserFormatOptions().getPattern(col)); - - assertFalse(completionQuery.hasGroup()); - assertFalse(completionQuery.hasPivot()); - } - - /** - * Tests the query splitter with a datasource with SORT_AND_PAGINATION CapabilitySet, when the - * query contains one of group/filter/pivot. - */ - public void testSortAndPagination() throws Exception { - QueryPair split = QuerySplitter.splitQuery(q, Capabilities.SORT_AND_PAGINATION); - Query dataSourceQuery = split.getDataSourceQuery(); - Query completionQuery = split.getCompletionQuery(); - - assertFalse(dataSourceQuery.hasSelection()); - assertFalse(dataSourceQuery.hasFilter()); - assertFalse(dataSourceQuery.hasSort()); - assertFalse(dataSourceQuery.hasRowSkipping()); - assertFalse(dataSourceQuery.hasRowLimit()); - assertFalse(dataSourceQuery.hasRowOffset()); - assertFalse(dataSourceQuery.hasOptions()); - assertFalse(dataSourceQuery.hasLabels()); - assertFalse(dataSourceQuery.hasUserFormatOptions()); - assertFalse(dataSourceQuery.hasGroup()); - assertFalse(dataSourceQuery.hasPivot()); - - assertEquals(q, completionQuery); - } - - /** - * Tests the query splitter with a datasource with SORT_AND_PAGINATION CapabilitySet, when the - * query does not contain any of group/filter/pivot. - */ - public void testSortAndPaginationOnSimpleQuery() throws Exception { - q.setGroup(null); - q.setFilter(null); - q.setPivot(null); - // Remove aggregation column: - QuerySelection newSel = new QuerySelection(); - newSel.addColumn(new SimpleColumn("A")); - q.setSelection(newSel); - - QueryPair split = QuerySplitter.splitQuery(q, Capabilities.SORT_AND_PAGINATION); - Query dataSourceQuery = split.getDataSourceQuery(); - Query completionQuery = split.getCompletionQuery(); - - assertFalse(dataSourceQuery.hasSelection()); - assertFalse(dataSourceQuery.hasFilter()); - List columns = dataSourceQuery.getSort().getColumns(); - assertEquals(1, columns.size()); - assertEquals("A", ((SimpleColumn) columns.get(0)).getId()); - assertEquals(7, dataSourceQuery.getRowLimit()); - assertEquals(17, dataSourceQuery.getRowOffset()); - assertFalse(dataSourceQuery.hasOptions()); - assertFalse(dataSourceQuery.hasLabels()); - assertFalse(dataSourceQuery.hasUserFormatOptions()); - assertFalse(dataSourceQuery.hasGroup()); - assertFalse(dataSourceQuery.hasPivot()); - - columns = completionQuery.getSelection().getColumns(); - assertEquals(1, columns.size()); - assertEquals("A", ((SimpleColumn) columns.get(0)).getId()); - assertFalse(completionQuery.hasFilter()); - assertFalse(completionQuery.hasSort()); - assertFalse(completionQuery.hasRowLimit()); - assertFalse(completionQuery.hasRowOffset()); - assertTrue(completionQuery.hasOptions()); - assertTrue(completionQuery.hasLabels()); - assertTrue(completionQuery.hasUserFormatOptions()); - assertFalse(completionQuery.hasGroup()); - assertFalse(completionQuery.hasPivot()); - } - - /** - * Tests the query splitter with a datasource with SELECT CapabilitySet. - */ - public void testSplitSelection() throws Exception { - QueryPair split = QuerySplitter.splitQuery(q, Capabilities.SELECT); - Query dataSourceQuery = split.getDataSourceQuery(); - Query completionQuery = split.getCompletionQuery(); - - List columns = dataSourceQuery.getSelection().getColumns(); - assertEquals(3, columns.size()); - assertEquals("A", ((SimpleColumn) columns.get(0)).getId()); - assertEquals("B", ((SimpleColumn) columns.get(1)).getId()); - assertEquals("C", ((SimpleColumn) columns.get(2)).getId()); - assertFalse(dataSourceQuery.hasFilter()); - assertFalse(dataSourceQuery.hasSort()); - assertFalse(dataSourceQuery.hasRowSkipping()); - assertFalse(dataSourceQuery.hasRowLimit()); - assertFalse(dataSourceQuery.hasRowOffset()); - assertFalse(dataSourceQuery.hasOptions()); - assertFalse(dataSourceQuery.hasLabels()); - assertFalse(dataSourceQuery.hasUserFormatOptions()); - assertFalse(dataSourceQuery.hasGroup()); - assertFalse(dataSourceQuery.hasPivot()); - - assertEquals(q, completionQuery); - } - - /** - * Tests the query splitter with a datasource with ALL CapabilitySet. - */ - public void testSplitAll() throws Exception { - QueryPair split = QuerySplitter.splitQuery(q, Capabilities.ALL); - Query dataSourceQuery = split.getDataSourceQuery(); - Query completionQuery = split.getCompletionQuery(); - - assertEquals(q, dataSourceQuery); - - assertFalse(completionQuery.hasSelection()); - assertFalse(completionQuery.hasFilter()); - assertFalse(completionQuery.hasSort()); - assertFalse(completionQuery.hasRowLimit()); - assertFalse(completionQuery.hasRowOffset()); - assertFalse(completionQuery.hasOptions()); - assertFalse(completionQuery.hasLabels()); - assertFalse(completionQuery.hasUserFormatOptions()); - assertFalse(completionQuery.hasGroup()); - assertFalse(completionQuery.hasPivot()); - } - - /** - * Tests the query splitter with a datasource with NONE CapabilitySet. - */ - public void testSplitNone() throws Exception { - QueryPair split = QuerySplitter.splitQuery(q, Capabilities.NONE); - Query dataSourceQuery = split.getDataSourceQuery(); - Query completionQuery = split.getCompletionQuery(); - - assertNull(dataSourceQuery); - assertEquals(q, completionQuery); - } - - /** - * Tests the query splitter with a datasource with SQL/SORT_AND_PAGINATION - * CapabilitySets, when the query contains a scalar function column. - */ - public void testSplittingWithScalarFunctions() throws Exception { - List columnList = Lists.newArrayList(new SimpleColumn("A")); - q.setFilter(new ColumnIsNullFilter(new ScalarFunctionColumn(columnList, - TimeComponentExtractor.getInstance(TimeComponentExtractor.TimeComponent.YEAR)))); - - QueryPair split = QuerySplitter.splitQuery(q, Capabilities.SQL); - Query dataSourceQuery = split.getDataSourceQuery(); - - assertFalse(dataSourceQuery.hasSelection()); - assertFalse(dataSourceQuery.hasFilter()); - assertFalse(dataSourceQuery.hasSort()); - assertFalse(dataSourceQuery.hasRowSkipping()); - assertFalse(dataSourceQuery.hasRowLimit()); - assertFalse(dataSourceQuery.hasRowOffset()); - assertFalse(dataSourceQuery.hasOptions()); - assertFalse(dataSourceQuery.hasLabels()); - assertFalse(dataSourceQuery.hasUserFormatOptions()); - assertFalse(dataSourceQuery.hasGroup()); - assertFalse(dataSourceQuery.hasPivot()); - - split = QuerySplitter.splitQuery(q, Capabilities.SORT_AND_PAGINATION); - dataSourceQuery = split.getDataSourceQuery(); - - assertFalse(dataSourceQuery.hasSelection()); - assertFalse(dataSourceQuery.hasFilter()); - assertFalse(dataSourceQuery.hasSort()); - assertFalse(dataSourceQuery.hasRowSkipping()); - assertFalse(dataSourceQuery.hasRowLimit()); - assertFalse(dataSourceQuery.hasRowOffset()); - assertFalse(dataSourceQuery.hasOptions()); - assertFalse(dataSourceQuery.hasLabels()); - assertFalse(dataSourceQuery.hasUserFormatOptions()); - assertFalse(dataSourceQuery.hasGroup()); - assertFalse(dataSourceQuery.hasPivot()); - } - - public void testSplittingSQLWithPivotWithLabel() throws Exception { - QueryLabels labels = q.getLabels(); - labels.addLabel(new AggregationColumn(new SimpleColumn("B"), AggregationType.MAX), "bar"); - q.setLabels(labels); - QueryPair split = QuerySplitter.splitQuery(q, Capabilities.SQL); - Query dataSourceQuery = split.getDataSourceQuery(); - - assertFalse(dataSourceQuery.hasSelection()); - assertFalse(dataSourceQuery.hasFilter()); - assertFalse(dataSourceQuery.hasSort()); - assertFalse(dataSourceQuery.hasRowSkipping()); - assertFalse(dataSourceQuery.hasRowLimit()); - assertFalse(dataSourceQuery.hasRowOffset()); - assertFalse(dataSourceQuery.hasOptions()); - assertFalse(dataSourceQuery.hasLabels()); - assertFalse(dataSourceQuery.hasUserFormatOptions()); - assertFalse(dataSourceQuery.hasGroup()); - assertFalse(dataSourceQuery.hasPivot()); - } - - public void testSortAndPaginationWithSkipping() throws Exception { - Query testQuery = new Query(); - testQuery.copyFrom(q); - testQuery.setGroup(null); - testQuery.setFilter(null); - testQuery.setPivot(null); - testQuery.setRowSkipping(5); - - QueryPair split = QuerySplitter.splitQuery(testQuery, Capabilities.SORT_AND_PAGINATION); - Query dataSourceQuery = split.getDataSourceQuery(); - Query completionQuery = split.getCompletionQuery(); - - // The original query contains sort, skipping, limit, offset. We split it - // for sort and pagination capabilities. Data source query should have sort, - // and the completion query should have both skipping and pagination. - assertFalse(dataSourceQuery.hasSelection()); - assertFalse(dataSourceQuery.hasFilter()); - assertTrue(dataSourceQuery.hasSort()); - assertFalse(dataSourceQuery.hasRowSkipping()); - assertFalse(dataSourceQuery.hasRowLimit()); - assertFalse(dataSourceQuery.hasRowOffset()); - assertFalse(dataSourceQuery.hasOptions()); - assertFalse(dataSourceQuery.hasLabels()); - assertFalse(dataSourceQuery.hasUserFormatOptions()); - assertFalse(dataSourceQuery.hasGroup()); - assertFalse(dataSourceQuery.hasPivot()); - - testQuery.setSort(null); - assertEquals(testQuery, completionQuery); - } -} diff --git a/src/test/java/com/google/visualization/datasource/ResponseWriterTest.java b/src/test/java/com/google/visualization/datasource/ResponseWriterTest.java deleted file mode 100644 index 578c649..0000000 --- a/src/test/java/com/google/visualization/datasource/ResponseWriterTest.java +++ /dev/null @@ -1,232 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource; - -import com.google.common.collect.Lists; -import com.google.visualization.datasource.base.DataSourceException; -import com.google.visualization.datasource.base.DataSourceParameters; -import com.google.visualization.datasource.base.ReasonType; -import com.google.visualization.datasource.base.ResponseStatus; -import com.google.visualization.datasource.base.StatusType; -import com.google.visualization.datasource.datatable.ColumnDescription; -import com.google.visualization.datasource.datatable.DataTable; -import com.google.visualization.datasource.datatable.TableCell; -import com.google.visualization.datasource.datatable.TableRow; -import com.google.visualization.datasource.datatable.value.NumberValue; -import com.google.visualization.datasource.datatable.value.TextValue; -import com.google.visualization.datasource.datatable.value.ValueType; -import com.google.visualization.datasource.render.JsonRenderer; - -import java.util.List; - -import javax.servlet.http.HttpServletResponse; - -import junit.framework.TestCase; - -import static org.easymock.EasyMock.createMock; -import static org.easymock.EasyMock.expect; -import static org.easymock.EasyMock.eq; -import static org.easymock.EasyMock.expectLastCall; -import static org.easymock.EasyMock.replay; -import static org.easymock.EasyMock.verify; - - -/** - * Unit test for ResponseWriter. - * - * @author Nimrod T. - */ -public class ResponseWriterTest extends TestCase { - - private DataTable getTestDataTable() throws DataSourceException { - DataTable dataTable = new DataTable(); - ColumnDescription c0 = new ColumnDescription("A", ValueType.TEXT, "col0"); - ColumnDescription c1 = new ColumnDescription("B", ValueType.NUMBER, "col1"); - ColumnDescription c2 = new ColumnDescription("C", ValueType.BOOLEAN, "col2"); - - dataTable.addColumn(c0); - dataTable.addColumn(c1); - dataTable.addColumn(c2); - - List rows = Lists.newArrayList(); - - TableRow row = new TableRow(); - row.addCell(new TableCell("aaa")); - row.addCell(new TableCell(new NumberValue(222), "222")); - row.addCell(new TableCell(false)); - rows.add(row); - - row = new TableRow(); - row.addCell(new TableCell("")); - row.addCell(new TableCell(111)); - row.addCell(new TableCell(true)); - rows.add(row); - - row = new TableRow(); - row.addCell(new TableCell((new TextValue("bbb")), "bbb")); - row.addCell(new TableCell(333)); - row.addCell(new TableCell(true)); - rows.add(row); - - row = new TableRow(); - row.addCell(new TableCell("ddd")); - row.addCell(new TableCell(222)); - row.addCell(new TableCell(false)); - rows.add(row); - dataTable.addRows(rows); - - return dataTable; - } - - public void testSetServletResponseJson() throws DataSourceException { - // Basic test 1. - DataTable data = getTestDataTable(); - DataSourceParameters dsParamsJson = - new DataSourceParameters("responseHandler:babylon;out:json"); - ResponseStatus responseStatus = new ResponseStatus(StatusType.OK, null, null); - - String expected = "{\"version\":\"0.6\",\"status\":\"ok\"," - + "\"sig\":\"2087475733\",\"table\":" - + "{\"cols\":[{\"id\":\"A\",\"label\":\"col0\",\"type\":\"string\",\"pattern\":\"\"}," - + "{\"id\":\"B\",\"label\":\"col1\",\"type\":\"number\",\"pattern\":\"\"}," - + "{\"id\":\"C\",\"label\":\"col2\",\"type\":\"boolean\",\"pattern\":\"\"}]," - + "\"rows\":[{\"c\":[{\"v\":\"aaa\"},{\"v\":222.0,\"f\":\"222\"},{\"v\":false}]}," - + "{\"c\":[{\"v\":\"\"},{\"v\":111.0},{\"v\":true}]}," - + "{\"c\":[{\"v\":\"bbb\"},{\"v\":333.0},{\"v\":true}]}," - + "{\"c\":[{\"v\":\"ddd\"},{\"v\":222.0},{\"v\":false}]}]}}"; - - assertEquals(expected, JsonRenderer.renderJsonResponse( - dsParamsJson, responseStatus, data).toString()); - - DataSourceParameters dsParamsJsonP = - new DataSourceParameters("responseHandler:babylon;out:jsonp"); - assertEquals("babylon(" + expected + ");", JsonRenderer.renderJsonResponse( - dsParamsJsonP, responseStatus, data).toString()); - - // Basic test 2. - data = getTestDataTable(); - dsParamsJson = new DataSourceParameters("reqId:90210;responseHandler:babylon;"); - responseStatus = new ResponseStatus(StatusType.OK, null, null); - - expected = "{\"version\":\"0.6\",\"reqId\":\"90210\",\"status\":\"ok\"," - + "\"sig\":\"2087475733\",\"table\":" - + "{\"cols\":[{\"id\":\"A\",\"label\":\"col0\",\"type\":\"string\",\"pattern\":\"\"}," - + "{\"id\":\"B\",\"label\":\"col1\",\"type\":\"number\",\"pattern\":\"\"}," - + "{\"id\":\"C\",\"label\":\"col2\",\"type\":\"boolean\",\"pattern\":\"\"}]," - + "\"rows\":[{\"c\":[{\"v\":\"aaa\"},{\"v\":222.0,\"f\":\"222\"},{\"v\":false}]}," - + "{\"c\":[{\"v\":\"\"},{\"v\":111.0},{\"v\":true}]}," - + "{\"c\":[{\"v\":\"bbb\"},{\"v\":333.0},{\"v\":true}]}," - + "{\"c\":[{\"v\":\"ddd\"},{\"v\":222.0},{\"v\":false}]}]}}"; - - assertEquals(expected, JsonRenderer.renderJsonResponse( - dsParamsJson, responseStatus, data).toString()); - - dsParamsJsonP = new DataSourceParameters("reqId:90210;responseHandler:babylon;out:jsonp"); - assertEquals("babylon(" + expected + ");", JsonRenderer.renderJsonResponse( - dsParamsJsonP, responseStatus, data).toString()); - } - - public void testGenerateJsonResponseError() throws DataSourceException { - DataTable data = getTestDataTable(); - DataSourceParameters dsParamsJson = - new DataSourceParameters("reqId:90210;responseHandler:babylon;"); - ResponseStatus responseStatus = new ResponseStatus( - StatusType.ERROR, - ReasonType.INTERNAL_ERROR, - "this is me not you why it is that not knowing me cave man"); - - String expected = "{\"version\":\"0.6\",\"reqId\":\"90210\",\"status\":\"error\",\"errors\":" - + "[{\"reason\":\"internal_error\",\"message\":\"Internal error\",\"detailed_message\":" - + "\"this is me not you why it is that not knowing me cave man\"}]}"; - assertEquals( - expected, - JsonRenderer.renderJsonResponse(dsParamsJson, responseStatus, data).toString()); - - DataSourceParameters dsParamsJsonP = - new DataSourceParameters("reqId:90210;responseHandler:babylon;out:jsonp"); - assertEquals( - "babylon(" + expected + ");", - JsonRenderer.renderJsonResponse(dsParamsJsonP, responseStatus, data).toString()); - } - - public void testCSVResponse() throws DataSourceException { - final String csvContentType = "text/csv; charset=UTF-8"; - final String csvheaderName = "Content-Disposition"; - final String csvheaderValue = "attachment; filename=testFile.csv"; - - DataSourceParameters dsParamsCSV = - new DataSourceParameters("outFileName:testFile;out:csv"); - - HttpServletResponse mockHttpServletResponse = createMock(HttpServletResponse.class); - mockHttpServletResponse.setContentType(eq(csvContentType)); - mockHttpServletResponse.setHeader(eq(csvheaderName), eq(csvheaderValue)); - expectLastCall(); - - replay(mockHttpServletResponse); - ResponseWriter.setServletResponseCSV(dsParamsCSV, mockHttpServletResponse); - verify(mockHttpServletResponse); - } - - public void testTSVExcelResponse() throws DataSourceException { - final String tsvExcelContentType = "text/csv; charset=UTF-16LE"; - final String headerName = "Content-Disposition"; - final String headerValue = "attachment; filename=testFile.xls"; - - DataSourceParameters dsParamsTsvExcel = - new DataSourceParameters("outFileName:testFile.xls;out:tsv_excel"); - - HttpServletResponse mockHttpServletResponse = createMock(HttpServletResponse.class); - mockHttpServletResponse.setContentType(eq(tsvExcelContentType)); - mockHttpServletResponse.setHeader(eq(headerName), eq(headerValue)); - expectLastCall(); - - replay(mockHttpServletResponse); - ResponseWriter.setServletResponseTSVExcel(dsParamsTsvExcel, mockHttpServletResponse); - verify(mockHttpServletResponse); - } - - public void testHTMLResponseContentType() { - final String HtmlContentType = "text/html; charset=UTF-8"; - HttpServletResponse mockHttpServletResponse = createMock(HttpServletResponse.class); - mockHttpServletResponse.setContentType(eq(HtmlContentType)); - expectLastCall(); - - replay(mockHttpServletResponse); - ResponseWriter.setServletResponseHTML(mockHttpServletResponse); - verify(mockHttpServletResponse); - } - - public void testJsonResponseContentType() { - final String jsonContentType = "application/json; charset=UTF-8"; - HttpServletResponse mockHttpServletResponse = createMock(HttpServletResponse.class); - mockHttpServletResponse.setContentType(eq(jsonContentType)); - expectLastCall(); - - replay(mockHttpServletResponse); - ResponseWriter.setServletResponseJSON(mockHttpServletResponse); - verify(mockHttpServletResponse); - } - - public void testJsonpResponseContentType() { - final String jsonpContentType = "text/javascript; charset=UTF-8"; - HttpServletResponse mockHttpServletResponse = createMock(HttpServletResponse.class); - mockHttpServletResponse.setContentType(eq(jsonpContentType)); - expectLastCall(); - - replay(mockHttpServletResponse); - ResponseWriter.setServletResponseJSONP(mockHttpServletResponse); - verify(mockHttpServletResponse); - } -} diff --git a/src/test/java/com/google/visualization/datasource/base/BooleanFormatTest.java b/src/test/java/com/google/visualization/datasource/base/BooleanFormatTest.java deleted file mode 100644 index 80c6fb7..0000000 --- a/src/test/java/com/google/visualization/datasource/base/BooleanFormatTest.java +++ /dev/null @@ -1,185 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.base; - -import junit.framework.TestCase; - -import java.text.FieldPosition; -import java.text.ParseException; -import java.text.ParsePosition; - -/** - * BooleanFormat Tester. - * - * @author Hillel M. - */ -public class BooleanFormatTest extends TestCase { - - private Boolean trueValue = Boolean.TRUE; - - private Boolean falseValue = Boolean.FALSE; - - private BooleanFormat boolFormat; - - private BooleanFormat boolFormat1; - - private BooleanFormat boolFormat2; - - private BooleanFormat boolFormat3; - - @Override - public void setUp() throws Exception { - super.setUp(); - boolFormat = new BooleanFormat(); - boolFormat1 = new BooleanFormat("yes", "no"); - boolFormat2 = new BooleanFormat("T:F"); - boolFormat3 = new BooleanFormat("X", "O"); - } - - public void testConstructor() { - BooleanFormat booleanFormat = new BooleanFormat("1", "0"); - assertNotNull(booleanFormat); - } - - // The method UFormat.format() calls - // BooleanFormat.format(Object, StringBuffer, FieldPosition) - public void testFormat() { - assertEquals("true", boolFormat.format(trueValue)); - assertEquals("yes", boolFormat1.format(trueValue)); - assertEquals("T", boolFormat2.format(trueValue)); - assertEquals("X", boolFormat3.format(trueValue)); - - assertEquals("false", boolFormat.format(falseValue)); - assertEquals("no", boolFormat1.format(falseValue)); - assertEquals("F", boolFormat2.format(falseValue)); - assertEquals("O", boolFormat3.format(falseValue)); - } - - - public void testFormatThrowsException() { - FieldPosition pos = new FieldPosition(0); - StringBuffer sb = new StringBuffer(); - - try { - boolFormat.format(Integer.valueOf(7)); - fail(); - } catch (IllegalArgumentException e) { - // Expected. - } - - boolFormat.format(null); - assertTrue(0 == pos.getBeginIndex()); - assertTrue(0 == pos.getEndIndex()); - - try { - // StringBuffer is null. - boolFormat.format(trueValue, null, pos); - fail(); - } catch (NullPointerException e) { - assertTrue(0 == pos.getBeginIndex()); - assertTrue(0 == pos.getEndIndex()); - } - try { - // FieldPosition is null. - boolFormat.format(trueValue, sb, null); - fail(); - } catch (NullPointerException e) { - // OK. - } - pos = new FieldPosition(0); - sb = new StringBuffer(); - // Object is null. - boolFormat.format(null, sb, pos); - assertTrue(0 == pos.getBeginIndex()); - assertTrue(0 == pos.getEndIndex()); - assertTrue(0 == sb.length()); - - pos = new FieldPosition(0); - try { - // Object is not instance of Boolean. - boolFormat.format(new Object(), new StringBuffer(), pos); - fail(); - } catch (IllegalArgumentException e) { - assertTrue(0 == pos.getBeginIndex()); - assertTrue(0 == pos.getEndIndex()); - assertTrue(0 == sb.length()); - } - } - - public void testFieldPosition() { - - // Boolean trueValue. - FieldPosition pos = new FieldPosition(0); - StringBuffer sb = new StringBuffer(); - boolFormat.format(trueValue, sb, pos); - assertTrue(0 == pos.getBeginIndex()); - assertTrue(("true".length() - 1) == pos.getEndIndex()); - - // Boolean falseValue. - pos = new FieldPosition(0); - sb = new StringBuffer(); - boolFormat.format(falseValue, sb, pos); - assertTrue(0 == pos.getBeginIndex()); - assertTrue(("false".length() - 1) == pos.getEndIndex()); - } - - public void testParse() throws ParseException { - - // == Boolean trueValue. - assertEquals(trueValue, boolFormat.parseObject("true")); - // non-case sensitive. - assertEquals(trueValue, boolFormat.parseObject("tRuE")); - assertEquals(trueValue, boolFormat1.parseObject("yes")); - assertEquals(trueValue, boolFormat2.parseObject("T")); - assertEquals(trueValue, boolFormat3.parseObject("X")); - - // == Boolean falseValue. - assertEquals(falseValue, boolFormat.parseObject("false")); - assertEquals(falseValue, boolFormat1.parseObject("no")); - // non-case sensitive. - assertEquals(falseValue, boolFormat1.parseObject("nO")); - assertEquals(falseValue, boolFormat2.parseObject("F")); - assertEquals(falseValue, boolFormat3.parseObject("O")); - } - - public void testParseNullCases() { - ParsePosition pos = new ParsePosition(0); - try { - boolFormat.parseObject("true", null); - fail(); - } catch (NullPointerException e) { - // OK. - } - try { - boolFormat.parseObject(null, pos); - fail(); - } catch (NullPointerException e) { - // OK. - } - Object value = boolFormat.parseObject("not a good string", pos); - assertNull(value); - assertTrue(0 == pos.getErrorIndex()); - } - - public void testParseParsePosition() { - ParsePosition pos = new ParsePosition(0); - boolFormat.parseObject("true", pos); - assertTrue("true".length() == pos.getIndex()); - - pos = new ParsePosition(0); - boolFormat.parseObject("false", pos); - assertTrue("false".length() == pos.getIndex()); - } -} diff --git a/src/test/java/com/google/visualization/datasource/base/DataSourceParametersTest.java b/src/test/java/com/google/visualization/datasource/base/DataSourceParametersTest.java deleted file mode 100644 index 9700522..0000000 --- a/src/test/java/com/google/visualization/datasource/base/DataSourceParametersTest.java +++ /dev/null @@ -1,124 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -package com.google.visualization.datasource.base; - -import junit.framework.TestCase; - -/** - * Unit test for DataSourceParameters. - * - * @author Nimrod T. - */ -public class DataSourceParametersTest extends TestCase { - - /** - * Test request parsing. - */ - public void testRequestParsing() throws DataSourceException { - // Test null and default values. - String tqxValue = null; - DataSourceParameters dsParams = new DataSourceParameters(tqxValue); - assertEquals(null, dsParams.getTqxValue()); - assertEquals(null, dsParams.getRequestId()); - assertEquals("JSON", dsParams.getOutputType().toString()); - assertEquals("data.csv", dsParams.getOutFileName()); - assertEquals("google.visualization.Query.setResponse", dsParams.getResponseHandler()); - - // Test empty string and default values. - tqxValue = ""; - dsParams = new DataSourceParameters(tqxValue); - assertEquals(null, dsParams.getTqxValue()); - assertEquals(null, dsParams.getRequestId()); - assertEquals("JSON", dsParams.getOutputType().toString()); - assertEquals("data.csv", dsParams.getOutFileName()); - assertEquals("google.visualization.Query.setResponse", dsParams.getResponseHandler()); - - // Test double ::. - boolean caught = false; - try { - tqxValue = "reqId::7;sig:666"; - dsParams = new DataSourceParameters(tqxValue); - } catch (DataSourceException e) { - caught = true; - assertEquals("Internal error(malformed)", e.getMessageToUser()); - assertEquals(ReasonType.INVALID_REQUEST, e.getReasonType()); - } - assertTrue(caught); - - - // Test double ;;. - caught = false; - try { - tqxValue = "reqId:7;;sig:666"; - dsParams = new DataSourceParameters(tqxValue); - } catch (DataSourceException e) { - caught = true; - assertEquals("Internal error(malformed)", e.getMessageToUser()); - assertEquals(ReasonType.INVALID_REQUEST, e.getReasonType()); - } - assertTrue(caught); - - // Test no value for a key. - caught = false; - try { - tqxValue = "reqId:7;sig"; - dsParams = new DataSourceParameters(tqxValue); - } catch (DataSourceException e) { - caught = true; - assertEquals("Internal error(malformed)", e.getMessageToUser()); - assertEquals(ReasonType.INVALID_REQUEST, e.getReasonType()); - } - assertTrue(caught); - - // Test empty value for a key. - caught = false; - try { - tqxValue = "reqId:7;sig:"; - dsParams = new DataSourceParameters(tqxValue); - } catch (DataSourceException e) { - caught = true; - assertEquals("Internal error(malformed)", e.getMessageToUser()); - assertEquals(ReasonType.INVALID_REQUEST, e.getReasonType()); - } - assertTrue(caught); - - // Test leniently. - tqxValue = "blahblah:bluhbluh;reqId:251ddd;ganja:sensi;"; - dsParams = new DataSourceParameters(tqxValue); - assertEquals("251ddd", dsParams.getRequestId()); - - // Test signature. - tqxValue = "sig:1234567"; - dsParams = new DataSourceParameters(tqxValue); - assertEquals("1234567", dsParams.getSignature()); - - // Test out and outFilename when out is html. - tqxValue = "out:html;outFileName:babylon.burn"; - dsParams = new DataSourceParameters(tqxValue); - assertEquals("HTML", dsParams.getOutputType().toString()); - assertEquals("babylon.burn", dsParams.getOutFileName()); - - // Test out and outFilename when out is csv. - tqxValue = "out:csv;outFileName:babylon.burn"; - dsParams = new DataSourceParameters(tqxValue); - assertEquals("CSV", dsParams.getOutputType().toString()); - assertEquals("babylon.burn", dsParams.getOutFileName()); - - // Test out and outFilename when outFilename is without .csv. - tqxValue = "out:csv;outFileName:babylon"; - dsParams = new DataSourceParameters(tqxValue); - assertEquals("CSV", dsParams.getOutputType().toString()); - assertEquals("babylon.csv", dsParams.getOutFileName()); - } -} diff --git a/src/test/java/com/google/visualization/datasource/base/LocaleUtilTest.java b/src/test/java/com/google/visualization/datasource/base/LocaleUtilTest.java deleted file mode 100644 index becb6ed..0000000 --- a/src/test/java/com/google/visualization/datasource/base/LocaleUtilTest.java +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.base; - -import junit.framework.TestCase; - -import java.util.Locale; - -/** - * Unit test for LocaleUtil. - * - * @author Hillel M. - */ -public class LocaleUtilTest extends TestCase { - - - public void testGetLocalizedMessageFromBundle() { - assertEquals("Sign in", LocaleUtil.getLocalizedMessageFromBundle( - "com.google.visualization.datasource.base.ErrorMessages", "SIGN_IN", null)); - - assertEquals("Sign in", LocaleUtil.getLocalizedMessageFromBundle( - "com.google.visualization.datasource.base.ErrorMessages", "SIGN_IN", Locale.CANADA_FRENCH)); - - assertEquals("Access denied", LocaleUtil.getLocalizedMessageFromBundle( - "com.google.visualization.datasource.base.ErrorMessages", "ACCESS_DENIED", Locale.GERMAN)); - } - -} \ No newline at end of file diff --git a/src/test/java/com/google/visualization/datasource/base/ReasonTypeTest.java b/src/test/java/com/google/visualization/datasource/base/ReasonTypeTest.java deleted file mode 100644 index 7b213b7..0000000 --- a/src/test/java/com/google/visualization/datasource/base/ReasonTypeTest.java +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.base; - -import junit.framework.TestCase; - - -/** - * Unit test for Helper. - * - * @author Yaniv S. - */ -public class ReasonTypeTest extends TestCase { - - public void testBasic() { - // Test getMessageForReasonType with default locale. - assertEquals(ReasonType.INVALID_QUERY.getMessageForReasonType(), "Invalid query"); - } - - public void testLowerString() { - ReasonType reasonType = ReasonType.ACCESS_DENIED; - assertEquals("access_denied", reasonType.lowerCaseString()); - } -} diff --git a/src/test/java/com/google/visualization/datasource/base/ResponseStatusTest.java b/src/test/java/com/google/visualization/datasource/base/ResponseStatusTest.java deleted file mode 100644 index 6de2d7e..0000000 --- a/src/test/java/com/google/visualization/datasource/base/ResponseStatusTest.java +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.base; - -import junit.framework.TestCase; - -import java.util.Locale; - -/** - * Unit test for ResponseStatus. - * - * @author Nimrod T. - */ -public class ResponseStatusTest extends TestCase { - public void testBasic() { - // Test getMessageForReasonType with default locale. - assertEquals("Invalid query", ReasonType.INVALID_QUERY.getMessageForReasonType()); - - // Test getMessageForReasonType with specified locale. - assertEquals("Retrieved data was truncated", - ReasonType.DATA_TRUNCATED.getMessageForReasonType(new Locale("en", "US"))); - } - - public void testGetModifiedResponseStatus() { - String urlMessage = "http://www.google.com"; - ResponseStatus responseStatusAccessDenied = new ResponseStatus(StatusType.ERROR, - ReasonType.ACCESS_DENIED, urlMessage); - ResponseStatus responseStatusUserNotAuthenticated = new ResponseStatus(StatusType.ERROR, - ReasonType.USER_NOT_AUTHENTICATED, urlMessage); - ResponseStatus responseStatusUserNotAuthenticatedNoUrl = new ResponseStatus(StatusType.ERROR, - ReasonType.USER_NOT_AUTHENTICATED, "123"); - - // no modification - assertEquals(responseStatusAccessDenied, - ResponseStatus.getModifiedResponseStatus(responseStatusAccessDenied)); - - assertEquals(responseStatusUserNotAuthenticatedNoUrl, - ResponseStatus.getModifiedResponseStatus(responseStatusUserNotAuthenticatedNoUrl)); - - // modified - ResponseStatus modifiedResponse = - ResponseStatus.getModifiedResponseStatus(responseStatusUserNotAuthenticated); - assertEquals(StatusType.ERROR, modifiedResponse.getStatusType()); - assertEquals(ReasonType.USER_NOT_AUTHENTICATED, modifiedResponse.getReasonType()); - String htmlSignInString = "Sign in"; - assertEquals(htmlSignInString, modifiedResponse.getDescription()); - } - - public void testCreateResponseStatus() { - DataSourceException dse = new DataSourceException(ReasonType.INTERNAL_ERROR, "123"); - ResponseStatus responseStatus = ResponseStatus.createResponseStatus(dse); - - assertEquals(StatusType.ERROR, responseStatus.getStatusType()); - assertEquals(ReasonType.INTERNAL_ERROR, responseStatus.getReasonType()); - assertEquals("123", responseStatus.getDescription()); - } -} diff --git a/src/test/java/com/google/visualization/datasource/base/StatusTypeTest.java b/src/test/java/com/google/visualization/datasource/base/StatusTypeTest.java deleted file mode 100644 index d885c56..0000000 --- a/src/test/java/com/google/visualization/datasource/base/StatusTypeTest.java +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.base; - -import junit.framework.TestCase; - -/** - * Unit test for StatusType. - * - * @author Nimrod T. - */ -public class StatusTypeTest extends TestCase { - public void testBasic() { - StatusType statusType = StatusType.OK; - assertEquals("ok", statusType.lowerCaseString()); - } -} diff --git a/src/test/java/com/google/visualization/datasource/base/TextFormatTest.java b/src/test/java/com/google/visualization/datasource/base/TextFormatTest.java deleted file mode 100644 index d5b66d6..0000000 --- a/src/test/java/com/google/visualization/datasource/base/TextFormatTest.java +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.base; - -import junit.framework.TestCase; - -import java.text.FieldPosition; -import java.text.ParsePosition; - -/** - * TextFormat Tester. - * - * @author Hillel M. - */ -public class TextFormatTest extends TestCase { - - private TextFormat textFormat; - - private StringBuffer sb; - - private FieldPosition fieldPos; - - private ParsePosition parsePos; - - public void testConstructor() { - textFormat = new TextFormat(); - assertNotNull(textFormat); - } - - /** - * UFormat.format() calls - * BooleanFormat.format(Object, StringBuffer, FieldPosition) - */ - public void testFormat() { - textFormat = new TextFormat(); - assertEquals("String", textFormat.format("String")); - assertEquals("abcdefghijklmnop!@#$%^&*()", - textFormat.format("abcdefghijklmnop!@#$%^&*()")); - } - - public void testFormatThrowsException() { - textFormat = new TextFormat(); - fieldPos = new FieldPosition(0); - sb = new StringBuffer(); - try { - // StringBuffer null. - textFormat.format("String", null, fieldPos); - fail(); - } catch (NullPointerException e) { - assertTrue(0 == fieldPos.getBeginIndex()); - assertTrue(0 == fieldPos.getEndIndex()); - } - fieldPos = new FieldPosition(0); - try { - // FieldPosition is null. - textFormat.format("String", sb, null); - fail(); - } catch (NullPointerException e) { - // OK. - } - fieldPos = new FieldPosition(0); - sb = new StringBuffer(); - try { - // Object is null. - textFormat.format(null, sb, fieldPos); - fail(); - } catch (IllegalArgumentException e) { - assertTrue(0 == sb.length()); - assertTrue(0 == fieldPos.getBeginIndex()); - assertTrue(0 == fieldPos.getEndIndex()); - } - fieldPos = new FieldPosition(0); - sb = new StringBuffer(); - try { - // Object is not instance of String - textFormat.format(new Object(), sb, fieldPos); - fail(); - } catch (IllegalArgumentException e) { - assertTrue(0 == sb.length()); - assertTrue(0 == fieldPos.getBeginIndex()); - assertTrue(0 == fieldPos.getEndIndex()); - } - } - - public void testFormatFieldPosition() { - // Regular TextValue. - textFormat = new TextFormat(); - fieldPos = new FieldPosition(0); - sb = new StringBuffer(); - textFormat.format("Another String", sb, fieldPos); - assertTrue(0 == fieldPos.getBeginIndex()); - assertTrue(("Another String".length() - 1) == fieldPos.getEndIndex()); - // Empty TextValue. - fieldPos = new FieldPosition(0); - sb = new StringBuffer(); - textFormat.format("", sb, fieldPos); - assertTrue(0 == fieldPos.getBeginIndex()); - assertTrue(0 == fieldPos.getEndIndex()); - } - - public void testParse() { - textFormat = new TextFormat(); - parsePos = new ParsePosition(0); - assertEquals("abcdefghijklmnop!@#$%^&*()", textFormat. - parseObject("abcdefghijklmnop!@#$%^&*()", parsePos)); - } - - public void testParseNullCases() { - textFormat = new TextFormat(); - parsePos = new ParsePosition(0); - try { - // ParsePostion is null. - textFormat.parseObject("true", null); - fail(); - } catch (NullPointerException e) { - // OK. - } - try { - // source is null - textFormat.parseObject(null, parsePos); - fail(); - } catch (NullPointerException e) { - // OK. - } - } - - public void testParseParsePosition() { - textFormat = new TextFormat(); - ParsePosition pos = new ParsePosition(0); - textFormat.parseObject("abcdefghijklmnop!@#$%^&*()", pos); - assertTrue("abcdefghijklmnop!@#$%^&*()".length() == pos.getIndex()); - } -} diff --git a/src/test/java/com/google/visualization/datasource/datatable/ColumnDescriptionTest.java b/src/test/java/com/google/visualization/datasource/datatable/ColumnDescriptionTest.java deleted file mode 100644 index 711f66c..0000000 --- a/src/test/java/com/google/visualization/datasource/datatable/ColumnDescriptionTest.java +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.datatable; - -import com.google.visualization.datasource.datatable.value.ValueType; - -import junit.framework.TestCase; - -/** - * ColumnDescription Tester. - * - * @author Hillel M. - */ -public class ColumnDescriptionTest extends TestCase { - - private ColumnDescription columnDescription; - - public void testConstructor() { - columnDescription = new ColumnDescription("col123", ValueType.TIMEOFDAY, "123"); - assertNotNull(columnDescription); - } - - public void testGetId() { - columnDescription = new ColumnDescription("col123", ValueType.TIMEOFDAY, "123"); - assertEquals("col123", columnDescription.getId()); - } - - public void testGetType() { - columnDescription = new ColumnDescription("col123", ValueType.TIMEOFDAY, "123"); - assertEquals(ValueType.TIMEOFDAY, columnDescription.getType()); - } - - - public void testGetLabel() { - columnDescription = new ColumnDescription("col123", ValueType.TIMEOFDAY, "123"); - assertEquals("123", columnDescription.getLabel()); - } - - public void testColumnProperties() { - columnDescription = new ColumnDescription("col123", ValueType.BOOLEAN, "123"); - assertNull(columnDescription.getCustomProperty("brandy")); - - columnDescription.setCustomProperty("brandy", "cognac"); - assertEquals("cognac", columnDescription.getCustomProperty("brandy")); - } -} diff --git a/src/test/java/com/google/visualization/datasource/datatable/DataTableTest.java b/src/test/java/com/google/visualization/datasource/datatable/DataTableTest.java deleted file mode 100644 index 4d87ec1..0000000 --- a/src/test/java/com/google/visualization/datasource/datatable/DataTableTest.java +++ /dev/null @@ -1,380 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.datatable; - -import com.google.common.collect.Lists; -import com.google.visualization.datasource.base.ReasonType; -import com.google.visualization.datasource.base.TypeMismatchException; -import com.google.visualization.datasource.base.Warning; -import com.google.visualization.datasource.datatable.value.BooleanValue; -import com.google.visualization.datasource.datatable.value.DateTimeValue; -import com.google.visualization.datasource.datatable.value.DateValue; -import com.google.visualization.datasource.datatable.value.NumberValue; -import com.google.visualization.datasource.datatable.value.TextValue; -import com.google.visualization.datasource.datatable.value.TimeOfDayValue; -import com.google.visualization.datasource.datatable.value.Value; -import com.google.visualization.datasource.datatable.value.ValueType; - -import com.ibm.icu.util.GregorianCalendar; -import com.ibm.icu.util.TimeZone; -import com.ibm.icu.util.ULocale; - -import junit.framework.TestCase; - -import java.util.Comparator; -import java.util.List; - -/** - * Tests for DataTable. - * - * @author Yoah B.D. - */ -public class DataTableTest extends TestCase { - - DataTable testData; - - List rows; - - List colIds; - - private static final Comparator CELL_COMPARATOR = - TableCell.getLocalizedComparator(ULocale.ENGLISH); - - @Override - public void setUp() throws Exception { - super.setUp(); - - colIds = Lists.newArrayList(); - - testData = new DataTable(); - ColumnDescription c0 = new ColumnDescription("col0", ValueType.TEXT, "label0"); - ColumnDescription c1 = new ColumnDescription("col1", ValueType.NUMBER, "label1"); - ColumnDescription c2 = new ColumnDescription("col2", ValueType.BOOLEAN, "label2"); - ColumnDescription c3 = new ColumnDescription("col3", ValueType.DATE, "label3"); - ColumnDescription c4 = new ColumnDescription("col4", ValueType.TIMEOFDAY, "label4"); - ColumnDescription c5 = new ColumnDescription("col5", ValueType.DATETIME, "label5"); - - testData.addColumn(c0); - testData.addColumn(c1); - testData.addColumn(c2); - testData.addColumn(c3); - testData.addColumn(c4); - testData.addColumn(c5); - - colIds.add("col0"); - colIds.add("col1"); - colIds.add("col2"); - colIds.add("col3"); - colIds.add("col4"); - colIds.add("col5"); - - rows = Lists.newArrayList(); - - TableRow row = new TableRow(); - row.addCell(new TableCell("aaa")); - row.addCell(new TableCell(222)); - row.addCell(new TableCell(false)); - row.addCell(new TableCell(new DateValue(2001, 10, 14))); - row.addCell(new TableCell(new TimeOfDayValue(12, 11, 13, 14))); - row.addCell(new TableCell(new DateTimeValue(2000, 10 , 1, 1, 10, 23, 432))); - rows.add(row); - - row = new TableRow(); - row.addCell(new TableCell(new TextValue("ccc"), "$ccc")); - row.addCell(new TableCell(111)); - row.addCell(new TableCell(true)); - row.addCell(new TableCell(new DateValue(2001, 1, 14))); - row.addCell(new TableCell(new TimeOfDayValue(12, 30, 13, 14))); - row.addCell(new TableCell(new DateTimeValue(1000, 11, 1, 1, 10, 23, 432))); - rows.add(row); - - row = new TableRow(); - row.addCell(new TableCell("bbb")); - row.addCell(new TableCell(3)); - row.addCell(new TableCell(true)); - row.addCell(new TableCell(new DateValue(2012, 2, 14))); - row.addCell(new TableCell(new TimeOfDayValue(12, 11, 3, 14))); - row.addCell(new TableCell(new DateTimeValue(2000, 1 , 1, 1, 10, 31, 4))); - rows.add(row); - - row = new TableRow(); - row.addCell("ddd"); - row.addCell(222); - row.addCell(false); - row.addCell(new DateValue(1997, 5, 5)); - row.addCell(new TimeOfDayValue(12, 15, 15, 14)); - row.addCell(new DateTimeValue(3100, 1, 2, 15, 15, 1, 0)); - rows.add(row); - - testData.addRows(rows); - } - - @Override - public void tearDown() throws Exception { - super.tearDown(); - testData = null; - rows = null; - } - - /** - * Tests getting cells for a single column. - */ - public void testCellList() { - List cells = testData.getColumnCells(2); - assertEquals(4, cells.size()); - assertEquals(ValueType.BOOLEAN, cells.get(0).getType()); - - cells = testData.getColumnCells("col0"); - assertEquals(4, cells.size()); - assertEquals(ValueType.TEXT, cells.get(0).getType()); - } - - /** - * Tests adding a row. - */ - public void testAddRow() throws Exception { - assertEquals(4, testData.getNumberOfRows()); - TableRow row = new TableRow(); - TableCell cell = new TableCell("1234"); - row.addCell(cell); - testData.addRow(row); - assertEquals(5, testData.getNumberOfRows()); - - TableRow row1 = testData.getRow(4); - assertEquals(cell, row1.getCell(0)); - } - - /** - * Tests addRowFromValues. - */ - public void testAddRowFromValues() { - assertEquals(4, testData.getNumberOfRows()); - GregorianCalendar c1 = new GregorianCalendar(2009, 2, 15); - c1.setTimeZone(TimeZone.getTimeZone("GMT")); - GregorianCalendar c2 = new GregorianCalendar(2009, 2, 15, 12, 30, 45); - c2.setTimeZone(TimeZone.getTimeZone("GMT")); - try { - testData.addRowFromValues("blah", 5, true, c1, c2, c2); - } catch (TypeMismatchException e) { - fail(); - } - assertEquals(5, testData.getNumberOfRows()); - assertEquals(testData.getRow(4).getCell(0).getValue().compareTo(new TextValue("blah")), 0); - assertEquals(testData.getRow(4).getCell(1).getValue().compareTo(new NumberValue(5)), 0); - assertEquals(testData.getRow(4).getCell(2).getValue().compareTo(BooleanValue.TRUE), 0); - assertEquals(testData.getRow(4).getCell(3).getValue().compareTo(new DateValue(c1)), 0); - assertEquals(testData.getRow(4).getCell(4).getValue().compareTo(new TimeOfDayValue(c2)), 0); - assertEquals(testData.getRow(4).getCell(5).getValue().compareTo(new DateTimeValue(c2)), 0); - } - - /** - * Tests get and set rows. - */ - public void testGetSetRows() throws Exception { - testData.setRows(rows); - List retrievedRows = testData.getRows(); - assertNotNull(retrievedRows); - assertEquals(rows.size(), retrievedRows.size()); - assertEquals(rows.get(0).getCell(0).getValue(), retrievedRows.get(0).getCell(0).getValue()); - } - - /** - * Tests distinct column values. - */ - public void testColumnDistinctValues() { - List values = testData.getColumnDistinctValues(0); - assertEquals(4, values.size()); - values = testData.getColumnDistinctValues("col1"); - assertEquals(3, values.size()); - assertEquals("3.0", values.get(0).toString()); - assertEquals("111.0", values.get(1).toString()); - assertEquals("222.0", values.get(2).toString()); - values = testData.getColumnDistinctValues("col2"); - assertEquals(2, values.size()); - } - - /** - * Tests distinct column values. - */ - public void testColumnDistinctCellsSorted() { - // Test col1. - List cells = testData. - getColumnDistinctCellsSorted(1, CELL_COMPARATOR); - assertEquals(3, cells.size()); - assertEquals("3.0", cells.get(0).toString()); - assertEquals("111.0", cells.get(1).toString()); - assertEquals("222.0", cells.get(2).toString()); - - // Test col2. - cells = testData.getColumnDistinctCellsSorted(2, CELL_COMPARATOR); - assertEquals(2, cells.size()); - assertEquals("false", cells.get(0).toString()); - assertEquals("true", cells.get(1).toString()); - - // Test col6, verify that when formatted value is present - // the sorting is based on it. - cells = testData.getColumnDistinctCellsSorted(0, CELL_COMPARATOR); - assertEquals(4, cells.size()); - assertEquals("aaa", cells.get(0).toString()); - assertEquals("bbb", cells.get(1).toString()); - assertEquals("ccc", cells.get(2).toString()); - assertEquals("ddd", cells.get(3).toString()); - } - - - /** - * Tests the check that a list of column ids are all in the data. - */ - public void testContainsAll() { - assertTrue(testData.containsAllColumnIds(colIds)); - // Check that it works for a partial set of ids as well. - if (!colIds.isEmpty()) { - colIds.remove(0); - assertTrue(testData.containsAllColumnIds(colIds)); - } - colIds.add("@@@@@#@#@#@#"); - assertFalse(testData.containsAllColumnIds(colIds)); - } - - public void testClone() throws Exception { - testData = new DataTable(); - ColumnDescription c0 = new ColumnDescription("A", ValueType.TEXT, "col0"); - ColumnDescription c1 = new ColumnDescription("B", ValueType.NUMBER, "col1"); - ColumnDescription c2 = new ColumnDescription("C", ValueType.BOOLEAN, "col2"); - testData.setLocaleForUserMessages(ULocale.JAPAN); - testData.addColumn(c0); - testData.addColumn(c1); - testData.addColumn(c2); - - rows = Lists.newArrayList(); - - TableRow row = new TableRow(); - row.addCell(new TableCell("aaa")); - row.addCell(new TableCell(new NumberValue(222), "222")); - row.addCell(new TableCell(false)); - rows.add(row); - - row = new TableRow(); - row.addCell(new TableCell("")); - row.addCell(new TableCell(111)); - row.addCell(new TableCell(true)); - rows.add(row); - - row = new TableRow(); - row.addCell(new TableCell(new TextValue("bbb"), "bbb")); - row.addCell(new TableCell(333)); - row.addCell(new TableCell(true)); - rows.add(row); - - row = new TableRow(); - row.addCell(new TableCell("ddd")); - row.addCell(new TableCell(222)); - row.addCell(new TableCell(false)); - rows.add(row); - - testData.addRows(rows); - - DataTable cloned = testData.clone(); - - // Test that the data is the same: - assertEquals("col0", cloned.getColumnDescription("A").getLabel()); - assertEquals("aaa", cloned.getRow(0).getCell(0).getValue().toString()); - assertEquals("222", cloned.getRow(0).getCell(1).getFormattedValue()); - assertEquals(testData.getLocaleForUserMessages(), cloned.getLocaleForUserMessages()); - - // Test that some pointers are not the same: - assertTrue(cloned != testData); - assertTrue(cloned.getRows() != testData.getRows()); - assertTrue(cloned.getRow(1) != testData.getRow(1)); - assertTrue(cloned.getRow(2).getCell(0) != testData.getRow(2).getCell(0)); - - // Change cloned's metadata and see that the original data remains the same. - cloned.addWarning(new Warning(ReasonType.OTHER, "baz")); - cloned.addColumn(new ColumnDescription("foo", ValueType.BOOLEAN, "a")); - cloned.getColumnDescription("A").setLabel("chacha"); - - assertTrue(testData.getWarnings().isEmpty()); - assertEquals(4, testData.getRows().size()); - assertFalse(testData.containsColumn("foo")); - assertEquals("col0", testData.getColumnDescription("A").getLabel()); - } - - public void testTableProperties() { - DataTable dataEmpty = new DataTable(); - assertNull(dataEmpty.getCustomProperty("brandy")); - - dataEmpty.setCustomProperty("brandy", "cognac"); - assertEquals("cognac", dataEmpty.getCustomProperty("brandy")); - } - - public void testToString() { - DataTable dataTable = testData; - assertEquals( - "aaa,222.0,false,2001-11-14,12:11:13. 14,2000-11-01 01:10:23.432\nccc,111.0,true," - + "2001-02-14,12:30:13. 14,1000-12-01 01:10:23.432\nbbb,3.0,true,2012-03-14,12:11:03. " - + "14,2000-02-01 01:10:31.004\nddd,222.0,false,1997-06-05,12:15:15. 14,3100-02-02 15:15:01", - testData.toString()); - } - - public void testGetCellAndGetValue() { - assertEquals(new TextValue("ccc"), testData.getValue(1, 0)); - TableCell cell = testData.getCell(1, 0); - assertEquals("$ccc", cell.getFormattedValue()); - } - - public void testReplaceCell() throws Exception { - DataTable dataTable = testData.clone(); - - TableCell newNumberValueCell = new TableCell(new NumberValue(5699), "5699$"); - newNumberValueCell.setCustomProperty("testProperty", "A test property"); - TableCell newBooleanValueCell = new TableCell(false); - TableCell newDateValueCell = new TableCell(new DateValue(2011, 3, 6), "03/06/2011"); - - dataTable.setCell(1, 1, newNumberValueCell); - dataTable.setCell(2, 2, newBooleanValueCell); - dataTable.setCell(2, 3, newDateValueCell); - - assertEquals(newNumberValueCell.getValue(), dataTable.getValue(1, 1)); - assertEquals(newNumberValueCell.getFormattedValue(), - dataTable.getCell(1,1).getFormattedValue()); - assertEquals(newNumberValueCell.getCustomProperty("testProperty"), - dataTable.getCell(1,1).getCustomProperty("testProperty")); - assertEquals(newBooleanValueCell.getValue(), dataTable.getValue(2, 2)); - assertEquals(newDateValueCell.getValue(), dataTable.getValue(2, 3)); - assertEquals(newDateValueCell.getFormattedValue(), - dataTable.getCell(2,3).getFormattedValue()); - - try { - dataTable.setCell(3, 3, new TableCell(100)); - fail(); - } catch (TypeMismatchException e) { - // Expected behavior. - } - - try { - dataTable.setCell(1, 1, new TableCell(false)); - fail(); - } catch (TypeMismatchException e) { - // Expected behavior. - } - - try { - dataTable.setCell(20, 20, new TableCell(100)); - fail(); - } catch (IndexOutOfBoundsException e) { - // Expected behavior. - } - } -} diff --git a/src/test/java/com/google/visualization/datasource/datatable/TableCellTest.java b/src/test/java/com/google/visualization/datasource/datatable/TableCellTest.java deleted file mode 100644 index 836efd2..0000000 --- a/src/test/java/com/google/visualization/datasource/datatable/TableCellTest.java +++ /dev/null @@ -1,156 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.datatable; - -import com.google.visualization.datasource.datatable.value.BooleanValue; -import com.google.visualization.datasource.datatable.value.DateValue; -import com.google.visualization.datasource.datatable.value.NumberValue; -import com.google.visualization.datasource.datatable.value.TextValue; -import com.google.visualization.datasource.datatable.value.ValueType; - -import com.ibm.icu.util.ULocale; - -import junit.framework.TestCase; - -import java.util.Comparator; - -/** - * TableCell Tester. - * - * @author Hillel M. - */ -public class TableCellTest extends TestCase { - - private String storedFormattedValue; - private DateValue dateValue; - - @Override - public void setUp() throws Exception { - super.setUp(); - storedFormattedValue = "21-Feb-2007"; - dateValue = new DateValue(2007, 1, 21); - } - - @Override - public void tearDown() throws Exception { - super.tearDown(); - } - - public void testGetFormattedValue() { - TableCell cell = new TableCell(true); - String formattedValue; - - // Test use of the default column formatter. - formattedValue = cell.getFormattedValue(); - assertNull(formattedValue); - - cell.setFormattedValue("YES"); - formattedValue = cell.getFormattedValue(); - assertEquals("YES", formattedValue); - } - - public void testConstructorString() { - TableCell cell = new TableCell("string"); - assertNotNull(cell); - assertEquals(new TextValue("string"), cell.getValue()); - } - - public void testConstructorBoolean() { - TableCell cell = new TableCell(true); - assertNotNull(cell); - assertEquals(BooleanValue.TRUE, cell.getValue()); - } - - public void testConstructorDouble() { - TableCell cell = new TableCell(34.43); - assertNotNull(cell); - assertEquals(new NumberValue(34.43), cell.getValue()); - } - - - public void testConstructor() { - TableCell cell = new TableCell(dateValue); - assertNotNull(cell); - assertEquals(dateValue, cell.getValue()); - - cell = new TableCell(dateValue, storedFormattedValue); - assertNotNull(cell); - assertEquals(dateValue, cell.getValue()); - } - - public void testGetType() { - TableCell cell = new TableCell(dateValue, storedFormattedValue); - assertEquals(ValueType.DATE, cell.getType()); - } - - public void testGetNull() { - TableCell cell = new TableCell(dateValue, storedFormattedValue); - assertFalse(cell.isNull()); - cell = new TableCell(DateValue.getNullValue()); - assertTrue(cell.isNull()); - } - - public void testToString() { - TableCell cell = new TableCell(BooleanValue.TRUE); - assertEquals("true", cell.toString()); - } - - /** - * Tests the localized comparator. - */ - public void testLocalizedComparator() { - // Test that strings are compared according to the given locale. - Comparator rootComparator = TableCell.getLocalizedComparator( - ULocale.ROOT); - Comparator frComparator = TableCell.getLocalizedComparator( - ULocale.FRENCH); - TableCell cell1 = new TableCell(new TextValue("cot\u00E9")); - TableCell cell2 = new TableCell(new TextValue("c\u00F4te")); - assertEquals(-1, rootComparator.compare(cell1, cell2)); - assertEquals(1, frComparator.compare(cell1, cell2)); - - // Test that number values are sorted correctly. - TableCell numberCell2 = new TableCell((new NumberValue(2))); - TableCell numberCell1 = new TableCell((new NumberValue(1))); - assertEquals(-1, rootComparator.compare(numberCell1, numberCell2)); - - // Test that value type must be the same. - try { - assertEquals(-1, rootComparator.compare(cell1, numberCell2)); - fail(); - } catch (RuntimeException e) { - // Expected behavior. - } - } - - public void testClone() throws Exception { - TableCell cell = new TableCell(new NumberValue(-2.3), "foobar23"); - TableCell cloned = cell.clone(); - - assertEquals(-2.3, ((NumberValue) cloned.getValue()).getValue()); - assertEquals("foobar23", cloned.getFormattedValue()); - assertTrue(cloned.getCustomProperties().isEmpty()); - - cloned.setCustomProperty("foo", "bar"); - cell.setCustomProperty("foo2", "bar2"); - cell.setFormattedValue("chuku23"); - - assertEquals(1, cell.getCustomProperties().size()); - assertEquals(1, cloned.getCustomProperties().size()); - assertEquals("bar", cloned.getCustomProperty("foo")); - assertEquals("bar2", cell.getCustomProperty("foo2")); - assertEquals("foobar23", cloned.getFormattedValue()); - } -} diff --git a/src/test/java/com/google/visualization/datasource/datatable/TableRowTest.java b/src/test/java/com/google/visualization/datasource/datatable/TableRowTest.java deleted file mode 100644 index 400c287..0000000 --- a/src/test/java/com/google/visualization/datasource/datatable/TableRowTest.java +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.datatable; - -import com.google.visualization.datasource.datatable.value.BooleanValue; -import com.google.visualization.datasource.datatable.value.DateValue; -import com.google.visualization.datasource.datatable.value.NumberValue; -import com.google.visualization.datasource.datatable.value.TextValue; - -import junit.framework.TestCase; - -/** - * Tests for TableRow - * - * @author Yonatan B.Y. - */ -public class TableRowTest extends TestCase { - - @Override - public void setUp() throws Exception { - super.setUp(); - } - - @Override - public void tearDown() throws Exception { - super.tearDown(); - } - - public void testClone() throws Exception { - TableRow row = new TableRow(); - row.addCell(true); - row.addCell(BooleanValue.getNullValue()); - row.addCell(-2.3); - row.addCell("foo"); - row.addCell(new DateValue(2008, 2, 3)); - row.getCell(2).setFormattedValue("bar-2.3"); - row.getCell(4).setCustomProperty("foo", "bar"); - - TableRow clonedRow = row.clone(); - - assertEquals(true, ((BooleanValue) clonedRow.getCell(0).getValue()).getValue()); - assertTrue(clonedRow.getCell(1).isNull()); - assertEquals(-2.3, ((NumberValue) clonedRow.getCell(2).getValue()).getValue()); - assertEquals("foo", ((TextValue) clonedRow.getCell(3).getValue()).getValue()); - assertEquals(3, ((DateValue) clonedRow.getCell(4).getValue()).getDayOfMonth()); - assertEquals("bar-2.3", clonedRow.getCell(2).getFormattedValue()); - assertEquals("bar", clonedRow.getCell(4).getCustomProperty("foo")); - assertEquals(1, clonedRow.getCell(4).getCustomProperties().size()); - - assertTrue(clonedRow != row); - assertTrue(clonedRow.getCell(0) != row.getCell(0)); - assertTrue(clonedRow.getCell(1) != row.getCell(1)); - assertTrue(clonedRow.getCell(4).getCustomProperties() != row.getCell(4).getCustomProperties()); - - row.getCell(0).setCustomProperty("foo2", "bar2"); - assertTrue(clonedRow.getCell(0).getCustomProperties().isEmpty()); - - clonedRow.getCell(3).setCustomProperty("foo3", "bar3"); - assertTrue(row.getCell(3).getCustomProperties().isEmpty()); - } -} diff --git a/src/test/java/com/google/visualization/datasource/datatable/ValueFormatterTest.java b/src/test/java/com/google/visualization/datasource/datatable/ValueFormatterTest.java deleted file mode 100644 index d07dfb7..0000000 --- a/src/test/java/com/google/visualization/datasource/datatable/ValueFormatterTest.java +++ /dev/null @@ -1,356 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.datatable; - -import com.google.visualization.datasource.base.LocaleUtil; -import com.google.visualization.datasource.datatable.value.BooleanValue; -import com.google.visualization.datasource.datatable.value.DateTimeValue; -import com.google.visualization.datasource.datatable.value.DateValue; -import com.google.visualization.datasource.datatable.value.NumberValue; -import com.google.visualization.datasource.datatable.value.TextValue; -import com.google.visualization.datasource.datatable.value.TimeOfDayValue; -import com.google.visualization.datasource.datatable.value.ValueType; - -import com.ibm.icu.util.Calendar; -import com.ibm.icu.util.ULocale; - -import junit.framework.TestCase; - -import org.apache.commons.lang.StringUtils; - -import java.util.Map; - -/** - * ValueFormatter tests. - * - * There is a test per each value type. Each test has three parts as follows: A test of the default - * pattern, a test of a provided pattern, and a test that fails because the provided differs from - * the pattern of the actual text to parse. - * - * @author Hillel M. - */ -public class ValueFormatterTest extends TestCase { - - private ULocale[] ulocales; - - @Override - public void setUp() throws Exception { - super.setUp(); - ulocales = ULocale.getAvailableLocales(); - } - - /** - * This test checks the creation of ValueFormatters for each - * ValueType and for each ULocale. The output strings are very different - * since they are locale dependent thus the checks are quite primitive. - * Nevertheless it is (almost) impossible to create better tests since - * the output strings are so diverse (usually not all fonts are available - * on a single machine to even display all of them correctly). - * - * ULocale is a class analogous to java.util.Locale that provides additional - * support for ICU protocol. - */ - public void testValueFormatterFromPatternAndLocale() { - for (ULocale ulocale : ulocales) { - // Create a ValueFormatter for each ValueType. - ValueFormatter booleanFormatter = ValueFormatter.createFromPattern( - ValueType.BOOLEAN, "true:false", ulocale); - ValueFormatter numberFormatter = ValueFormatter.createFromPattern( - ValueType.NUMBER, "#.##", ulocale); - ValueFormatter textFormatter = ValueFormatter.createFromPattern( - ValueType.TEXT, "TEXT-PATTERN", ulocale); - ValueFormatter dateFormatter = ValueFormatter.createFromPattern( - ValueType.DATE, "dd/mm/YYYY", ulocale); - ValueFormatter timeOfDayFormatter = ValueFormatter.createFromPattern( - ValueType.TIMEOFDAY, "HH:mm:ss", ulocale); - ValueFormatter dateTimeFormatter = ValueFormatter.createFromPattern( - ValueType.DATETIME, "YYYY/mm/dd HH:mm:ss", ulocale); - - // Boolean - String formattedValue = booleanFormatter.format(BooleanValue.TRUE); - assertEquals("true", formattedValue); - - // Number - formattedValue = numberFormatter.format(new NumberValue(-12.23)); - assertFalse(StringUtils.isEmpty(formattedValue)); - String language = ulocale.getDisplayLanguage(); - if (isReadableLetters(language)) { - assertTrue(formattedValue.contains("12")); - } - - // Text - formattedValue = textFormatter.format(new TextValue("this is a test")); - assertEquals("this is a test", formattedValue); - - // Date - formattedValue = dateFormatter.format(new DateValue(1988, 11, 24)); - assertFalse(StringUtils.isEmpty(formattedValue)); - language = ulocale.getDisplayLanguage(); - if (isReadableLetters(language)) { - assertTrue(formattedValue.contains("88")); - } - - // Time - formattedValue = timeOfDayFormatter.format(new TimeOfDayValue(2, 24, 6)); - assertFalse(StringUtils.isEmpty(formattedValue)); - language = ulocale.getDisplayLanguage(); - if (isReadableLetters(language)) { - assertTrue(formattedValue.contains("24")); - } - - // Timestamp - formattedValue = dateTimeFormatter.format(new DateTimeValue(1597, 9, 29, 1, 2, 33, 142)); - assertFalse(StringUtils.isEmpty(formattedValue)); - language = ulocale.getDisplayLanguage(); - if (isReadableLetters(language)) { - assertTrue(formattedValue.contains("29")); - } - - // test nulls: - assertEquals("", booleanFormatter.format(BooleanValue.getNullValue())); - assertEquals("", numberFormatter.format(NumberValue.getNullValue())); - assertEquals("", dateFormatter.format(DateValue.getNullValue())); - assertEquals("", dateTimeFormatter.format(DateTimeValue.getNullValue())); - assertEquals("", timeOfDayFormatter.format(TimeOfDayValue.getNullValue())); - } - } - - public void testDefaultAndNullCases() { - ValueFormatter booleanFormatter = ValueFormatter.createFromPattern( - ValueType.BOOLEAN, null, null); - ValueFormatter numberFormatter = ValueFormatter.createFromPattern( - ValueType.NUMBER, null, null); - ValueFormatter textFormatter = ValueFormatter.createFromPattern( - ValueType.TEXT, null, null); - ValueFormatter dateFormatter = ValueFormatter.createFromPattern( - ValueType.DATE, null, null); - ValueFormatter timeOfDayFormatter = ValueFormatter.createFromPattern( - ValueType.TIMEOFDAY, null, null); - ValueFormatter dateTimeFormatter = ValueFormatter.createFromPattern( - ValueType.DATETIME, null, null); - - assertNotNull(booleanFormatter); - assertNotNull(numberFormatter); - assertNotNull(dateFormatter); - assertNotNull(dateTimeFormatter); - assertNotNull(timeOfDayFormatter); - assertNotNull(textFormatter); - - assertNotNull(booleanFormatter.getUFormat()); - assertNotNull(numberFormatter.getUFormat()); - assertNotNull(dateFormatter.getUFormat()); - assertNotNull(dateTimeFormatter.getUFormat()); - assertNotNull(timeOfDayFormatter.getUFormat()); - assertNotNull(textFormatter.getUFormat()); - - assertEquals(LocaleUtil.getDefaultLocale(), booleanFormatter.getLocale()); - assertEquals(LocaleUtil.getDefaultLocale(), numberFormatter.getLocale()); - assertEquals(LocaleUtil.getDefaultLocale(), dateFormatter.getLocale()); - assertEquals(LocaleUtil.getDefaultLocale(), dateTimeFormatter.getLocale()); - assertEquals(LocaleUtil.getDefaultLocale(), timeOfDayFormatter.getLocale()); - assertEquals(LocaleUtil.getDefaultLocale(), textFormatter.getLocale()); - - assertEquals(ValueType.BOOLEAN, booleanFormatter.getType()); - assertEquals(ValueType.NUMBER, numberFormatter.getType()); - assertEquals(ValueType.DATE, dateFormatter.getType()); - assertEquals(ValueType.DATETIME, dateTimeFormatter.getType()); - assertEquals(ValueType.TIMEOFDAY, timeOfDayFormatter.getType()); - assertEquals(ValueType.TEXT, textFormatter.getType()); - - assertNotNull(ValueFormatter.createDefault(ValueType.BOOLEAN, null)); - assertNotNull(ValueFormatter.createDefault(ValueType.NUMBER, null)); - assertNotNull(ValueFormatter.createDefault(ValueType.DATE, null)); - assertNotNull(ValueFormatter.createDefault(ValueType.DATETIME, null)); - assertNotNull(ValueFormatter.createDefault(ValueType.TIMEOFDAY, null)); - assertNotNull(ValueFormatter.createDefault(ValueType.TEXT, null)); - - ULocale ulocale = ULocale.ENGLISH; - ULocale ulocale1 = ULocale.CANADA_FRENCH; - - assertEquals(ulocale, - ValueFormatter.createFromPattern(ValueType.NUMBER, "", ulocale).getLocale()); - assertEquals(ulocale1, - ValueFormatter.createDefault(ValueType.NUMBER, ulocale1).getLocale()); - } - - public void testAFewMoreCases() { - ULocale ulocale = ULocale.ENGLISH; - - // Create a ValueFormatter for each type - ValueFormatter booleanFormatter = ValueFormatter.createFromPattern( - ValueType.BOOLEAN, null, ulocale); - assertNotNull(booleanFormatter); - - ValueFormatter numberFormatter = ValueFormatter.createFromPattern( - ValueType.NUMBER, null, ulocale); - assertNotNull(numberFormatter); - - ValueFormatter dateFormatter = ValueFormatter.createFromPattern( - ValueType.DATE, "YYYY/mm", null); - assertNotNull(dateFormatter); - - ValueFormatter textFormatter = ValueFormatter.createFromPattern(ValueType.TEXT, "", ulocale); - assertNotNull(textFormatter); - } - - /** - * Since not all locales use greek letters, this is a simple way to filter - * SOME of the greek letter using languages. - */ - private boolean isReadableLetters(String language) { - return ((language.equals("English")) || (language.equals("Spanish")) - || (language.equals("German")) || (language.equals("Greek"))); - } - - /** - * This test checks formatting by aq specific pattern in the US locale. - */ - public void testSpecificPatternFormattingInUSLocale() { - // Create a ColumnFormatter for each pattern - ValueFormatter booleanFormatter = ValueFormatter.createFromPattern( - ValueType.BOOLEAN, "yep:na", ULocale.US); - ValueFormatter numberFormatter = ValueFormatter.createFromPattern( - ValueType.NUMBER, "#,##0.000", ULocale.US); - ValueFormatter textFormatter = ValueFormatter.createFromPattern( - ValueType.TEXT, "", ULocale.US); - ValueFormatter dateFormatter = ValueFormatter.createFromPattern( - ValueType.DATE, "MM | dd | yy", ULocale.US); - ValueFormatter timeFormatter = ValueFormatter.createFromPattern( - ValueType.TIMEOFDAY, "HH-mm", ULocale.US); - ValueFormatter timestampFormatter = ValueFormatter.createFromPattern( - ValueType.DATETIME, "dd_MM_yy HH:mm", ULocale.US); - - // Boolean - String formattedValue = booleanFormatter.format(BooleanValue.TRUE); - assertEquals("yep", formattedValue); - - // Number - formattedValue = numberFormatter.format(new NumberValue(-12000.23)); - assertEquals("-12,000.230", formattedValue); - - // Text - formattedValue = textFormatter.format(new TextValue("this is another test")); - assertEquals("this is another test", formattedValue); - - // Date - formattedValue = dateFormatter.format(new DateValue(1988, 11, 24)); - assertEquals("12 | 24 | 88", formattedValue); - - // Time - formattedValue = - timeFormatter.format(new TimeOfDayValue(2, 24, 6)); - assertEquals("02-24", formattedValue); - - // Timestamp - formattedValue = timestampFormatter.format(new DateTimeValue(1597, 9, 29, 1, 2, 33, 142)); - assertEquals("29_10_97 01:02", formattedValue); - } - - // Some locales use localized digits and so even a simple pattern will be formatted - // differently than in English. - // The following is a simple example for Hindi. - public void testHindiLocale() { - ValueFormatter dateFormatter = ValueFormatter.createFromPattern( - ValueType.DATE, "MM | dd | yyyy", new ULocale("hi_IN")); - DateValue dateValue = new DateValue(2009, 1, 2); - String dateString = - "\u0966\u0968\u0020\u007c\u0020\u0966\u0968\u0020\u007c\u0020\u0968\u0966\u0966\u096f"; - assertEquals(dateString, dateFormatter.format(dateValue)); - assertEquals(dateValue, dateFormatter.parse(dateString)); - } - - public void testGetDefaultValueForamtters() { - Map formatters = ValueFormatter.createDefaultFormatters(null); - assertNotNull(formatters); - assertEquals(6, formatters.size()); - for (ValueType type : ValueType.values()) { - ValueFormatter valueFormatter = ValueFormatter.createDefault(type, null); - assertEquals(valueFormatter.getPattern(), formatters.get(type).getPattern()); - assertEquals(valueFormatter.getLocale(), formatters.get(type).getLocale()); - } - } - - public void testParseAll() { - assertEquals(new NumberValue(22), - ValueFormatter.createDefault(ValueType.NUMBER, null).parse("22")); - - assertEquals(new TextValue("1a"), - ValueFormatter.createDefault(ValueType.TEXT, null).parse("1a")); - - assertEquals(BooleanValue.TRUE, - ValueFormatter.createDefault(ValueType.BOOLEAN, null).parse("true")); - - assertEquals(new DateValue(2009, Calendar.JANUARY, 1), - ValueFormatter.createDefault(ValueType.DATE, null).parse("2009-1-1")); - - assertEquals(new DateTimeValue(2009, Calendar.JANUARY, 1, 12, 13, 14, 0), - ValueFormatter.createDefault(ValueType.DATETIME, null).parse("2009-1-1 12:13:14")); - - assertEquals(new TimeOfDayValue(12, 13, 14, 0), - ValueFormatter.createDefault(ValueType.TIMEOFDAY, null).parse("12:13:14")); - - } - public void testParseNumber() { - ValueFormatter numberFormatter = ValueFormatter.createDefault(ValueType.NUMBER, null); - assertEquals("22.0", numberFormatter.parse("22%").toString()); - assertEquals("22.0", numberFormatter.parse("22.0").toString()); - assertEquals("null", numberFormatter.parse("#0.0%").toString()); - } - - public void testParseBoolean() { - ValueFormatter booleanFormatter = ValueFormatter.createFromPattern( - ValueType.BOOLEAN, "1:0", null); - - assertEquals(BooleanValue.getNullValue(), booleanFormatter.parse("false")); - assertEquals(BooleanValue.TRUE, booleanFormatter.parse("1")); - } - - public void testParseText() { - ValueFormatter textFormatter = ValueFormatter.createDefault(ValueType.TEXT, null); - assertEquals(new TextValue("text"), textFormatter.parse("text")); - } - - public void testParseDate() { - ValueFormatter dateFormatter = ValueFormatter.createDefault(ValueType.DATE, null); - - assertEquals(new DateValue(2004, Calendar.FEBRUARY, 15), - dateFormatter.parse("2004-02-15")); - dateFormatter = ValueFormatter.createFromPattern(ValueType.DATE, "MM/dd/yyyy", null); - assertEquals(new DateValue(2004, Calendar.JANUARY, 15), dateFormatter.parse("01/15/2004")); - assertEquals(DateValue.getNullValue(), dateFormatter.parse("01.15.2004")); - } - - public void testParseTimeOfDay() { - ValueFormatter timeOfDayFormatter = ValueFormatter.createDefault(ValueType.TIMEOFDAY, null); - assertEquals(new TimeOfDayValue(7, 22, 44), timeOfDayFormatter.parse("7:22:44")); - - timeOfDayFormatter = ValueFormatter.createFromPattern(ValueType.TIMEOFDAY, "ss:mm:HH", null); - - assertEquals(new TimeOfDayValue(7, 22, 44), timeOfDayFormatter.parse("44:22:7")); - - assertEquals(TimeOfDayValue.getNullValue(), timeOfDayFormatter.parse("01.15.2004")); - } - - public void testParseDateTime() { - ValueFormatter dateTimeFormatter = ValueFormatter.createDefault(ValueType.DATETIME, null); - assertEquals(new DateTimeValue(2004, Calendar.FEBRUARY, 15, 7, 22, 44, 0), - dateTimeFormatter.parse("2004-02-15 7:22:44")); - dateTimeFormatter = - ValueFormatter.createFromPattern(ValueType.DATETIME, "MM/dd/yyyy ss:mm:HH", null); - assertEquals(new DateTimeValue(2004, Calendar.JANUARY, 15, 7, 22, 44, 0), - dateTimeFormatter.parse("01/15/2004 44:22:7")); - assertEquals(DateTimeValue.getNullValue(), dateTimeFormatter.parse("01.15.2004")); - } -} diff --git a/src/test/java/com/google/visualization/datasource/datatable/value/BooleanValueTest.java b/src/test/java/com/google/visualization/datasource/datatable/value/BooleanValueTest.java deleted file mode 100644 index 2e04575..0000000 --- a/src/test/java/com/google/visualization/datasource/datatable/value/BooleanValueTest.java +++ /dev/null @@ -1,165 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.datatable.value; - -import junit.framework.TestCase; - -/** - * Test for BooleanValue - * - * @author Yoah B.D. - */ -public class BooleanValueTest extends TestCase { - BooleanValue t; - BooleanValue f; - BooleanValue n; - - @Override - public void setUp() { - t = BooleanValue.TRUE; - f = BooleanValue.FALSE; - n = BooleanValue.getNullValue(); - } - - public void testValue() { - assertTrue(t.getValue()); - assertFalse(f.getValue()); - } - - public void testFormatting() { - assertEquals("true", t.toString()); - assertEquals("false", f.toString()); - } - - public void testNull() throws Exception { - assertEquals("null", n.toString()); - assertTrue(n.isNull()); - - assertFalse(f.isNull()); - } - - public void testNullValueException() throws Exception { - try { - n.getValue(); - fail("Shouldn't get here - should have thrown a null value exception"); - } catch (NullValueException nve) { - // This is the expected behavior. - } - } - - public void testCompare() { - BooleanValue t2 = BooleanValue.TRUE; - BooleanValue f2 = BooleanValue.FALSE; - - assertTrue(t.compareTo(f) > 0); - assertTrue(f.compareTo(t) < 0); - assertTrue(t.compareTo(t) == 0); - assertTrue(f.compareTo(f) == 0); - assertTrue(t.compareTo(t2) == 0); - assertTrue(f.compareTo(f2) == 0); - - assertTrue(t.compareTo(BooleanValue.getNullValue()) > 0); - assertTrue(f.compareTo(BooleanValue.getNullValue()) > 0); - } - - public void testComapreNullCases() { - // Test null cases and classCast issues. - BooleanValue val = BooleanValue.TRUE; - try { - val.compareTo(null); - fail(); - } catch (NullPointerException e) { - // Expected behavior. - } - try { - val.compareTo(new NumberValue(123)); - fail(); - } catch (ClassCastException e) { - // Expected behavior. - } - - // Test NULL_VALUE cases. - BooleanValue val1 = BooleanValue.FALSE; - BooleanValue valNull = BooleanValue.getNullValue(); - - assertTrue(0 < val1.compareTo(valNull)); - assertTrue(0 > valNull.compareTo(val)); - - // Test same object. - assertTrue(0 == valNull.compareTo(BooleanValue.getNullValue())); - assertTrue(0 == val.compareTo(val)); - - // Test that compareTo can cast. - Value val2 = BooleanValue.TRUE; - assertTrue(0 == val.compareTo(val2)); - Value val3 = BooleanValue.getNullValue(); - assertTrue(0 < val.compareTo(val3)); - } - - public void testEquals() { - BooleanValue t2 = BooleanValue.TRUE; - BooleanValue f2 = BooleanValue.FALSE; - BooleanValue null1 = BooleanValue.getNullValue(); - BooleanValue null2 = BooleanValue.getNullValue(); - - assertTrue(t.equals(t)); - assertTrue(t.equals(t2)); - assertTrue(f.equals(f)); - assertTrue(f.equals(f2)); - assertTrue(null1.equals(null1)); - assertTrue(null1.equals(null2)); - - assertFalse(t.equals(f)); - assertFalse(f.equals(t)); - assertFalse(t.equals(null1)); - assertFalse(f.equals(null1)); - assertFalse(null1.equals(t)); - assertFalse(null2.equals(t2)); - - // Check interaction with other classes: - assertFalse(t.equals(Integer.valueOf(7))); - assertFalse(null1.equals(NumberValue.getNullValue())); - } - - public void testHashCode() { - assertTrue(1 == t.hashCode()); - assertTrue(0 == f.hashCode()); - assertTrue(-1 == n.hashCode()); - - } - - public void testGetValueToFormat () { - assertEquals(Boolean.TRUE, t.getObjectToFormat()); - assertEquals(Boolean.FALSE, f.getObjectToFormat()); - assertNull(n.getObjectToFormat()); - } - - public void testGetType() { - assertEquals(ValueType.BOOLEAN, t.getType()); - assertEquals(ValueType.BOOLEAN, f.getType()); - assertEquals(ValueType.BOOLEAN, n.getType()); - } - - public void testToQueryString() { - assertEquals("true", t.toQueryString()); - assertEquals("false", f.toQueryString()); - try { - n.toQueryString(); - fail("Should have thrown an exception."); - } catch (RuntimeException e) { - // Expected behavior. - } - } -} \ No newline at end of file diff --git a/src/test/java/com/google/visualization/datasource/datatable/value/DateTimeValueTest.java b/src/test/java/com/google/visualization/datasource/datatable/value/DateTimeValueTest.java deleted file mode 100644 index 83e7cbf..0000000 --- a/src/test/java/com/google/visualization/datasource/datatable/value/DateTimeValueTest.java +++ /dev/null @@ -1,345 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.datatable.value; - -import com.ibm.icu.util.GregorianCalendar; -import com.ibm.icu.util.TimeZone; - -import junit.framework.TestCase; - -/** - * Test for DateTimeValue. - * - * @author Hillel M. - */ -public class DateTimeValueTest extends TestCase { - - public void testNullValue() { - DateTimeValue value = DateTimeValue.getNullValue(); - assertTrue(value.isNull()); - value = new DateTimeValue(2007, 10, 11, 23, 34, 56, 609); - assertFalse(value.isNull()); - } - - - public void testConstructorOutOFRangeValuesMonth() { - // Check that the Exception is thrown. - try { - new DateTimeValue(2007, 13, 11, 23, 34, 56, 609); - fail(); - } catch (IllegalArgumentException e) { - // Expected behavior. - } - try { - new DateTimeValue(2007, -1, 11, 23, 34, 56, 609); - fail(); - } catch (IllegalArgumentException e) { - // Expected behavior. - } - } - - public void testConstructorOutOfRangeValuesDayOfMonth() { - // Check that the Exception is thrown. - try { - new DateTimeValue(2007, 10, 32, 23, 34, 56, 609); - fail(); - } catch (IllegalArgumentException e) { - // Expected behavior. - } - try { - new DateTimeValue(2007, 10, 0, 23, 34, 56, 609); - fail(); - } catch (IllegalArgumentException e) { - // Expected behavior. - } - } - - public void testConstructorOutOfRangeValuesHours() { - // Check that the Exception is thrown. - try { - new DateTimeValue(2007, 8, 20, 24, 34, 56, 609); - fail(); - } catch (IllegalArgumentException e) { - // Expected behavior. - } - try { - new DateTimeValue(2007, 8, 20, -1, 34, 56, 609); - fail(); - } catch (IllegalArgumentException e) { - // Expected behavior. - } - } - - public void testConstructorOutOfRangeValuesMinutes() { - // Check that the Exception is thrown. - try { - new DateTimeValue(2007, 7, 11, 14, 62, 56, 609); - fail(); - } catch (IllegalArgumentException e) { - // Expected behavior. - } - try { - new DateTimeValue(2007, 7, 11, 14, -1, 56, 609); - fail(); - } catch (IllegalArgumentException e) { - // Expected behavior. - } - } - - public void testConstructorOutOfRangeValuesSeconds() { - // Check that the Exception is thrown. - try { - new DateTimeValue(2007, 8, 11, 23, 34, 63, 609); - fail(); - } catch (IllegalArgumentException e) { - // Expected behavior. - } - try { - new DateTimeValue(2007, 8, 11, 23, 34, -10, 609); - fail(); - } catch (IllegalArgumentException e) { - // Expected behavior. - } - } - - public void testConstructorOutOfRangeValuesMilliseconds() { - // Check that the Exception is thrown. - try { - new DateTimeValue(2007, 7, 11, 23, 34, 56, 1000); - fail(); - } catch (IllegalArgumentException e) { - // Expected behavior. - } - try { - new DateTimeValue(2007, 7, 11, 23, 34, 56, -1); - fail(); - } catch (IllegalArgumentException e) { - // Expected behavior. - } - } - - - public void testConstructorSpecialValuesOfDate() { - try { - // February doesn't have 30 days. - new DateTimeValue(1990, 1, 30, 23, 11, 11, 100); - fail(); - } catch (IllegalArgumentException e) { - // Expected behavior. - } - try { - // February doesn't have 29 days in 2007. - new DateTimeValue(2007, 1, 29, 23, 10, 10, 200); - fail(); - } catch (IllegalArgumentException e) { - // Expected behavior. - } - try { - // September doesn't have 31 days. - new DateTimeValue(2007, 8, 31, 11, 5, 5, 5); - fail(); - } catch (IllegalArgumentException e) { - // Expected behavior. - } - } - - /** - * Months in DateValue are represented by the numbers {0, .., 11} as in Java. - */ - public void testJavaMonthConvention() { - // Check the Exception is thrown. - try { - new DateTimeValue(1990, 12, 10, 1, 1, 1, 1); - fail(); - } catch (IllegalArgumentException e) { - // Expected behavior. - } - } - - public void testTimestampConstructor() { - // Test if the construction does not fail. - try { - // 1st of February 2300. - DateTimeValue value = new DateTimeValue(2300, 1, 1, 15, 15, 15, 150); - assertNotNull(value); - assertFalse(value.isNull()); - } catch (IllegalArgumentException e) { - // Should not be here - assertFalse("An exception was not supposed to be thorwn", true); - } - try { - // 1st of January 130. - DateTimeValue value = new DateTimeValue(130, 0, 1, 0, 0, 0, 0); - assertNotNull(value); - assertFalse(value.isNull()); - } catch (IllegalArgumentException e) { - // Should not be here - assertFalse("An exception was not supposed to be thorwn. " - + e.getMessage(), true); - } - // This is the 29th of February of 2009 which is a real date. - try { - DateTimeValue value = new DateTimeValue(2008, 1, 29, 15, 12, 10, 600); - assertNotNull(value); - assertFalse(value.isNull()); - } catch (IllegalArgumentException e) { - // should not be here - assertFalse("An exception was not supposed to be thorwn", true); - } - } - - public void testCalendarConstructor() { - GregorianCalendar calendar = new GregorianCalendar(2006, 1, 1, 21, 24, 25); - calendar.set(GregorianCalendar.MILLISECONDS_IN_DAY, 222); - DateTimeValue value = null; - calendar.setTimeZone(TimeZone.getTimeZone("IST")); - // Check exception thrown for non GMT time zone. - try { - value = new DateTimeValue(calendar); - fail(); - } catch (IllegalArgumentException iae) { - // do nothing - } - calendar.setTimeZone(TimeZone.getTimeZone("GMT")); - // Check exception not thrown for GMT time zone. - try { - value = new DateTimeValue(calendar); - } catch (IllegalArgumentException iae) { - fail(); - } - // Verify values - default milliseconds. - assertEquals(calendar, value.getCalendar()); - } - - public void testGetType() { - DateTimeValue value = new DateTimeValue(2007, 7, 11, 23, 34, 56, 100); - assertEquals(value.getType(), ValueType.DATETIME); - value = DateTimeValue.getNullValue(); - assertEquals(value.getType(), ValueType.DATETIME); - - } - - public void testToString() { - DateTimeValue value = DateTimeValue.getNullValue(); - assertEquals(value.toString(), "null"); - value = new DateTimeValue(2007, 7, 11, 23, 34, 56, 100); - assertEquals("2007-08-11 23:34:56.100", value.toString()); - - value = new DateTimeValue(1500, 3, 3, 12, 12, 12, 12); - assertEquals("1500-04-03 12:12:12.012", value.toString()); - } - - public void testCompare(){ - DateTimeValue val1 = DateTimeValue.getNullValue(); - DateTimeValue val2 = new DateTimeValue(1500, 3, 3, 12, 12, 12, 12); - DateTimeValue val3 = new DateTimeValue(1500, 3, 3, 12, 12, 12, 12); - DateTimeValue val4 = new DateTimeValue(1499, 3, 3, 10, 12, 12, 12); - - // Equals. - assertTrue(val2.compareTo(val3) == 0); - assertTrue(val2.compareTo(val2) == 0); - - // One null one not. - assertTrue(val2.compareTo(val1) > 0); - assertTrue(val1.compareTo(val2) < 0); - - // Sanity test for GregorianCalendar.compareTo() - assertTrue(val3.compareTo(val4) > 0); - } - - public void testCompareNullCases() { - // Test null cases and classCast issues. - DateTimeValue val = new DateTimeValue(10, 10, 10, 10, 10, 10 , 10); - try { - val.compareTo(null); - fail(); - } catch (NullPointerException e) { - // Expected behavior. - } - try { - val.compareTo(new NumberValue(123)); - fail(); - } catch (ClassCastException e) { - // Expected behavior. - } - - // Test NULL_VALUE cases. - DateTimeValue val1 = new DateTimeValue(1, 1, 1, 1, 1, 1, 1); - DateTimeValue valNull = DateTimeValue.getNullValue(); - - assertTrue(0 < val1.compareTo(valNull)); - assertTrue(0 > valNull.compareTo(val)); - - // Test same object. - assertTrue(0 == valNull.compareTo(DateTimeValue.getNullValue())); - assertTrue(0 == val.compareTo(val)); - - // Test that compareTo can cast. - Value val2 = new DateTimeValue(10, 10, 10, 15, 10, 10 , 10); - assertTrue(0 > val.compareTo(val2)); - Value val3 = DateTimeValue.getNullValue(); - assertTrue(0 < val.compareTo(val3)); - } - - public void testGetCalendar() { - DateTimeValue val1 = new DateTimeValue(1499, 3, 3, 10, 12, 12, 12); - DateTimeValue val2 = DateTimeValue.getNullValue(); - assertNotNull(val1.getCalendar()); - try { - val2.getCalendar(); - assertFalse(true); - } catch (NullValueException e) { - // Expected behavior. - } - } - - /** - * Checks that the hashCode behaves in a reasonable way and does not map 3 different values to the - * same key. - * However, since this might be the case for some different hashCode function - * then in that case these 3 values should be replaced. - */ - public void testHashCode() { - DateTimeValue val1 = new DateTimeValue(1500, 3, 3, 12, 12, 12, 12); - DateTimeValue val2 = new DateTimeValue(2400, 7, 3, 12, 18, 12, 129); - DateTimeValue val3 = new DateTimeValue(1900, 3, 3, 12, 2, 2, 250); - - assertFalse((val1.hashCode() == val2.hashCode()) - || (val1.hashCode() == val3.hashCode())); - - DateTimeValue val = DateTimeValue.getNullValue(); - assertTrue(val.hashCode() == 0); - } - - public void testGetValueToFormat() { - DateTimeValue val = new DateTimeValue(2020, 3, 12, 2, 31, 12, 111); - DateTimeValue valNull = DateTimeValue.getNullValue(); - - GregorianCalendar g = new GregorianCalendar(2020, 3, 12, 2, 31, 12); - g.set(GregorianCalendar.MILLISECOND, 111); - g.setTimeZone(TimeZone.getTimeZone("GMT")); - - assertNull(valNull.getObjectToFormat()); - assertEquals(g, val.getObjectToFormat()); - } - - public void testToQueryString() { - DateTimeValue val1 = new DateTimeValue(2020, 3, 12, 2, 31, 12, 123); - DateTimeValue val2 = new DateTimeValue(2007, 5, 6, 7, 8, 9, 0); - - assertEquals("DATETIME '2020-4-12 2:31:12.123'", val1.toQueryString()); - assertEquals("DATETIME '2007-6-6 7:8:9'", val2.toQueryString()); - } -} \ No newline at end of file diff --git a/src/test/java/com/google/visualization/datasource/datatable/value/DateValueTest.java b/src/test/java/com/google/visualization/datasource/datatable/value/DateValueTest.java deleted file mode 100644 index 8be99a5..0000000 --- a/src/test/java/com/google/visualization/datasource/datatable/value/DateValueTest.java +++ /dev/null @@ -1,336 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.datatable.value; - -import com.ibm.icu.util.GregorianCalendar; -import com.ibm.icu.util.TimeZone; - -import junit.framework.TestCase; - -/** - * Test for DateValue. - * - * @author Hillel M. - */ -public class DateValueTest extends TestCase { - - public void testNullValue() { - DateValue value = DateValue.getNullValue(); - assertTrue(value.isNull()); - value = new DateValue(1990, 2, 1); - assertFalse(value.isNull()); - } - - /** - * Check that out of range dayOfMonth values are not accepted - * and an exception is thrown. - */ - public void testConstructorOutOFRangeValuesDayOfMonth() { - try { - new DateValue(1990, 11, -1); - fail(); - } catch (IllegalArgumentException e) { - // Expected behavior. - } - try { - DateValue value = new DateValue(1990, 11, 0); - // Shouldn't be here. - assertFalse(true); - } catch (IllegalArgumentException e) { - // Expected behavior. - } - try { - new DateValue(1990, 11, 32); - fail(); - } catch (IllegalArgumentException e) { - // Expected behavior. - } - } - - /** - * Check that out of range month values are not accepted - * and an exception is thrown. - */ - public void testConstructorOutOFRangeValuesMonth() { - try { - new DateValue(1990, 13, 1); - fail(); - } catch (IllegalArgumentException e) { - // Expected behavior. - } - try { - new DateValue(1990, -2, 1); - fail(); - } catch (IllegalArgumentException e) { - // Expected behavior. - } - } - - public void testConstructorSpecialDatesValues() { - try { - // February doesn't have 30 days. - new DateValue(1990, 1, 30); - fail(); - } catch (IllegalArgumentException e) { - // Expected behavior. - } - try { - // February doesn't have 29 days in 2007. - new DateValue(2007, 1, 29); - fail(); - } catch (IllegalArgumentException e) { - // Expected behavior. - } - try { - // September doesn't have 31 days. - new DateValue(2007, 8, 31); - fail(); - } catch (IllegalArgumentException e) { - // Expected behavior. - } - } - - /** - * Months in DateValue are represented by the numbers {0, .., 11} as in Java. - */ - public void testJavaMonthConvention() { - // Check the Exception is thrown. - try { - new DateValue(1990, 12, 10); - fail(); - } catch (IllegalArgumentException e) { - // Expected behavior. - } - } - - public void testDateConstructor() { - // Test if the construction does not fail. - try { - // 1st of February 2300. - DateValue value = new DateValue(2300, 1, 1); - assertNotNull(value); - assertFalse(value.isNull()); - } catch (IllegalArgumentException e) { - // Should not be here - assertFalse("An exception was not supposed to be thorwn", true); - } - try { - // 1st of January 130. - DateValue value = new DateValue(130, 0, 1); - assertNotNull(value); - assertFalse(value.isNull()); - } catch (IllegalArgumentException e) { - // Should not be here - assertFalse("An exception was not supposed to be thorwn", true); - } - // This is the 29th of February of 2009 which is a real date. - try { - DateValue value = new DateValue(2008, 1, 29); - assertNotNull(value); - assertFalse(value.isNull()); - } catch (IllegalArgumentException e) { - // Should not be here - assertFalse("An exception was not supposed to be thorwn", true); - } - } - - public void testCalendarConstructor() { - GregorianCalendar calendar = new GregorianCalendar(2006, 1, 3); - DateValue value = null; - calendar.setTimeZone(TimeZone.getTimeZone("IST")); - // Check exception thrown for non GMT time zone. - try { - value = new DateValue(calendar); - fail(); - } catch (IllegalArgumentException iae) { - // Expected behavior. - } - calendar.setTimeZone(TimeZone.getTimeZone("GMT")); - // Check that an exception is not thrown for GMT time zone. - try { - value = new DateValue(calendar); - } catch (IllegalArgumentException iae) { - fail(); - } - // Verify values - default milliseconds. - assertEquals(2006, value.getYear()); - assertEquals(1, value.getMonth()); - assertEquals(3, value.getDayOfMonth()); - } - - public void testGetType() { - DateValue value = new DateValue(1700, 2, 4); - assertEquals(value.getType(), ValueType.DATE); - value = DateValue.getNullValue(); - assertEquals(value.getType(), ValueType.DATE); - } - - public void testToString() { - DateValue value = new DateValue(500, 4, 20); - assertEquals(value.toString(), "500-05-20"); - value = new DateValue(2200, 3, 11); - assertEquals(value.toString(), "2200-04-11"); - value = DateValue.getNullValue(); - assertEquals(value.toString(), "null"); - } - - public void testlGetYear() { - DateValue value = new DateValue(4000, 1, 4); - assertTrue(value.getYear() == 4000); - } - - public void testGetMonth() { - // Note that the month is August and not July in this case. - DateValue value = new DateValue(2020, 7, 11); - assertTrue(value.getMonth() == 7); - } - - public void testlGetDayOfMonth() { - DateValue value = new DateValue(1414, 9, 17); - assertTrue(value.getDayOfMonth() == 17); - } - - public void testGetYearNull(){ - DateValue val = DateValue.getNullValue(); - try { - val.getYear(); - assertFalse(true); - } catch (NullValueException e) { - // Expected behavior. - } - } - - public void testGetMonthNull(){ - DateValue val = DateValue.getNullValue(); - try { - val.getMonth(); - assertFalse(true); - } catch (NullValueException e) { - // Expected behavior. - } - } - - public void testGetDayOfMonthNull(){ - DateValue val = DateValue.getNullValue(); - try { - val.getDayOfMonth(); - assertFalse(true); - } catch (NullValueException e) { - // Expected behavior. - } - } - - public void testCompare(){ - // Test hours. - DateValue val01 = new DateValue(1599, 11, 10); - DateValue val02 = new DateValue(1500, 11, 10); - DateValue val03 = new DateValue(1690, 11, 10); - - assertTrue(val01.compareTo(val02) > 0); - assertTrue(val01.compareTo(val03) < 0); - - // Test minutes. - DateValue val11 = new DateValue(1599, 8, 10); - DateValue val12 = new DateValue(1599, 6, 10); - DateValue val13 = new DateValue(1599, 10, 10); - - assertTrue(val11.compareTo(val12) > 0); - assertTrue(val11.compareTo(val13) < 0); - - // Test seconds. - DateValue val31 = new DateValue(1599, 11, 13); - DateValue val32 = new DateValue(1599, 11, 11); - DateValue val33 = new DateValue(1599, 11, 17); - - assertTrue(val31.compareTo(val32) > 0); - assertTrue(val31.compareTo(val33) < 0); - - // Test equals - DateValue val51 = new DateValue(3111, 6, 10); - DateValue val52 = new DateValue(3111, 6, 10); - - assertTrue(val51.compareTo(val52) == 0); - } - - public void testCompareNullCases() { - // Test null cases and classCast issues. - DateValue val = new DateValue(1000, 10, 10); - try { - val.compareTo(null); - fail(); - } catch (NullPointerException e) { - // Expected behavior. - } - try { - val.compareTo(new NumberValue(123)); - fail(); - } catch (ClassCastException e) { - // Expected behavior. - } - - // Test NULL_VALUE cases. - DateValue val1 = new DateValue(1111, 1, 1); - DateValue valNull = DateValue.getNullValue(); - - assertTrue(0 < val1.compareTo(valNull)); - assertTrue(0 > valNull.compareTo(val)); - - // Test same object. - assertTrue(0 == valNull.compareTo(DateValue.getNullValue())); - assertTrue(0 == val.compareTo(val)); - - // Test that compareTo can cast. - Value val2 = new DateValue(1000, 10, 12); - assertTrue(0 > val.compareTo(val2)); - Value val3 = DateValue.getNullValue(); - assertTrue(0 < val.compareTo(val3)); - } - - public void testGetValueToFormat() { - DateValue val = new DateValue(500, 2, 30); - DateValue valNull = DateValue.getNullValue(); - - assertNull(valNull.getObjectToFormat()); - GregorianCalendar g = new GregorianCalendar(500, 2, 30); - g.setTimeZone(TimeZone.getTimeZone("GMT")); - assertEquals(g, val.getObjectToFormat()); - - } - /** - * Check that the hashCode behaves in a reasonable way and does not map 3 different values to the - * same key. - * However, since this might be the case for some different hashCode function - * then in that case these 3 values should be replaced. - */ - public void testHashCode() { - DateValue val1 = new DateValue(1900, 0, 1); - DateValue val2 = new DateValue(1800, 0, 20); - DateValue val3 = new DateValue(2019, 1, 10); - - assertFalse((val1.hashCode() == val2.hashCode()) - || (val1.hashCode() == val3.hashCode())); - - DateValue val = DateValue.getNullValue(); - assertTrue(val.hashCode() == 0); - } - - public void testToQueryString() { - DateValue val1 = new DateValue(2007, 6, 20); - DateValue val2 = new DateValue(2010, 11, 11); - - assertEquals("DATE '2007-7-20'", val1.toQueryString()); - assertEquals("DATE '2010-12-11'", val2.toQueryString()); - } -} \ No newline at end of file diff --git a/src/test/java/com/google/visualization/datasource/datatable/value/NumberValueTest.java b/src/test/java/com/google/visualization/datasource/datatable/value/NumberValueTest.java deleted file mode 100644 index cfb8d83..0000000 --- a/src/test/java/com/google/visualization/datasource/datatable/value/NumberValueTest.java +++ /dev/null @@ -1,190 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.datatable.value; - -import junit.framework.TestCase; - -/** - * Test for NumberValue. - * - * @author Yoah B.D. - */ -public class NumberValueTest extends TestCase { - - public void testValue() { - double[] values = {0, -1, 100, 3.2, -12.3}; - for (double v : values) { - NumberValue cell = new NumberValue(v); - assertEquals(v, cell.getValue()); - } - } - - public void testFormatting() { - double[] values = {0, -1, 100, 3.2, -12.3, .01}; - for (double v : values) { - NumberValue cell = new NumberValue(v); - assertEquals(Double.toString(v), cell.toString()); - } - } - - public void testNull() throws Exception { - NumberValue n = NumberValue.getNullValue(); - assertEquals("null", n.toString()); - assertTrue(n.isNull()); - - NumberValue a = new NumberValue(1); - assertFalse(a.isNull()); - } - - public void testCompare() { - NumberValue c0 = new NumberValue(0); - NumberValue c1 = new NumberValue(1); - NumberValue c2 = new NumberValue(2); - NumberValue c1Copy = new NumberValue(1); - NumberValue m1 = new NumberValue(-0.1); - NumberValue m2 = new NumberValue(-0.2); - - assertTrue(c0.compareTo(c1) < 0); - assertTrue(c2.compareTo(c1) > 0); - assertTrue(c2.compareTo(c2) == 0); - assertTrue(c1.compareTo(c1Copy) == 0); - assertTrue(m1.compareTo(m2) > 0); - assertTrue(m2.compareTo(m1) < 0); - - assertTrue(m2.compareTo(NumberValue.getNullValue()) > 0); - assertTrue(NumberValue.getNullValue().compareTo(c1) < 0); - } - - public void testComapreNullCases() { - // Test null cases and classCast issues. - NumberValue val = new NumberValue(1234); - try { - val.compareTo(null); - fail(); - } catch (NullPointerException e) { - // Expected behavior. - } - try { - val.compareTo(new DateValue(123, 1, 21)); - fail(); - } catch (ClassCastException e) { - // Expected behavior. - } - - // Test NULL_VALUE cases. - NumberValue val1 = new NumberValue(-222); - NumberValue valNull = NumberValue.getNullValue(); - - assertTrue(0 < val1.compareTo(valNull)); - assertTrue(0 > valNull.compareTo(val)); - - // Test same object. - assertTrue(0 == valNull.compareTo(NumberValue.getNullValue())); - assertTrue(0 == val.compareTo(val)); - - // Test that compareTo can cast. - Value val2 = new NumberValue(4321); - assertTrue(0 > val.compareTo(val2)); - Value val3 = NumberValue.getNullValue(); - assertTrue(0 < val.compareTo(val3)); - } - - /** - * Test the equals() method of NumberValue. - */ - public void testEquals() { - NumberValue n1 = new NumberValue(-17.3); - NumberValue n2 = new NumberValue(-17.3); - NumberValue zero = new NumberValue(0); - NumberValue nullV = NumberValue.getNullValue(); - - assertTrue(n1.equals(n1)); - assertTrue(n1.equals(n2)); - assertTrue(nullV.equals(nullV)); - - assertFalse(n1.equals(zero)); - assertFalse(n1.equals(nullV)); - assertFalse(nullV.equals(zero)); - - // Check interaction with other classes. - assertFalse(n1.equals(new Double(-17.3))); - assertFalse(nullV.equals(BooleanValue.getNullValue())); - } - - public void testGetColumnType() { - NumberValue n1 = new NumberValue(-17.3); - NumberValue nullV = NumberValue.getNullValue(); - - assertEquals(ValueType.NUMBER, n1.getType()); - assertEquals(ValueType.NUMBER, nullV.getType()); - } - - public void testGetValue() { - NumberValue n1 = new NumberValue(-2131217.3121121); - NumberValue nullV = NumberValue.getNullValue(); - - assertEquals(-2131217.3121121, n1.getValue()); - try { - nullV.getValue(); - fail(); - } catch (NullValueException e) { - // Expected behavior. - } - } - - public void testToString() { - NumberValue n1 = new NumberValue(-2131217.3121121); - NumberValue nullV = NumberValue.getNullValue(); - - assertEquals(Double.toString(-2131217.3121121), n1.toString()); - assertEquals("null", nullV.toString()); - } - - public void testIsNull() { - NumberValue n1 = new NumberValue(-2131217.3121121); - NumberValue nullV = NumberValue.getNullValue(); - - assertFalse(n1.isNull()); - assertTrue(nullV.isNull()); - } - - public void testHashCode() { - NumberValue n1 = new NumberValue(-2131217.3121121); - NumberValue nullV = NumberValue.getNullValue(); - - assertTrue(0 == nullV.hashCode()); - assertTrue(new Double(-2131217.3121121).hashCode() == n1.hashCode()); - } - - public void testGetValueToFormat() { - NumberValue n1 = new NumberValue(-2131217.3121121); - NumberValue nullV1 = NumberValue.getNullValue(); - NumberValue nullV2 = new NumberValue(0); - - assertEquals(-2131217.3121121, n1.getObjectToFormat()); - assertNull(nullV1.getObjectToFormat()); - assertEquals((double) 0, nullV2.getObjectToFormat()); - } - - public void testToQueryString() { - NumberValue n1 = new NumberValue(-123); - NumberValue n2 = new NumberValue(0); - NumberValue n3 = new NumberValue(-12.45); - - assertEquals("-123.0", n1.toQueryString()); - assertEquals("0.0", n2.toQueryString()); - assertEquals("-12.45", n3.toQueryString()); - } -} \ No newline at end of file diff --git a/src/test/java/com/google/visualization/datasource/datatable/value/TextValueTest.java b/src/test/java/com/google/visualization/datasource/datatable/value/TextValueTest.java deleted file mode 100644 index d123c72..0000000 --- a/src/test/java/com/google/visualization/datasource/datatable/value/TextValueTest.java +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.datatable.value; - -import com.ibm.icu.util.ULocale; -import junit.framework.TestCase; - -import java.util.Comparator; - -/** - * Test for TextValue - * - * @author Yoah B.D. - */ -public class TextValueTest extends TestCase { - - public void testValue() { - String v = "abc"; - TextValue cell = new TextValue(v); - assertEquals(v, cell.toString()); - } - - public void testCompare() { - TextValue abc = new TextValue("abc"); - TextValue def = new TextValue("def"); - TextValue empty = new TextValue(""); - TextValue abcCopy = new TextValue("abc"); - - assertTrue(abc.compareTo(def) < 0); - assertTrue(def.compareTo(abc) > 0); - assertTrue(abc.compareTo(abc) == 0); - assertTrue(abc.compareTo(abcCopy) == 0); - assertTrue(abc.compareTo(empty) > 0); - } - - /** - * Tests the equals() method in TextValue. - */ - public void testEquals() { - TextValue abc1 = new TextValue("abc"); - TextValue abc2 = new TextValue("abc"); - TextValue empty1 = new TextValue(""); - TextValue empty2 = new TextValue(""); - - assertTrue(abc1.equals(abc1)); - assertTrue(abc1.equals(abc2)); - assertTrue(empty1.equals(empty1)); - assertTrue(empty1.equals(empty2)); - - assertFalse(abc1.equals(empty1)); - assertFalse(empty1.equals(abc1)); - - // Check interaction with other classes (e.g., String). - assertFalse(abc1.equals("abc")); - } - - public void testGetType() { - TextValue val = new TextValue("asdf"); - assertEquals(ValueType.TEXT, val.getType()); - } - - public void testToString() { - TextValue val1 = new TextValue("val1"); - TextValue emptyValue = new TextValue(""); - - assertEquals("val1", val1.toString()); - assertEquals("", emptyValue.toString()); - } - - public void testHashCode() { - TextValue asdfghjkl = new TextValue("asdfghjkl"); - TextValue emptyValue = new TextValue(""); - - assertTrue("asdfghjkl".hashCode() == asdfghjkl.hashCode()); - assertTrue("".hashCode() == emptyValue.hashCode()); - } - - public void testGetValueToFormat() { - TextValue testVal = new TextValue("goboazmauda"); - TextValue emptyValue = new TextValue(""); - - assertEquals("goboazmauda", testVal.getObjectToFormat()); - assertEquals("", emptyValue.getObjectToFormat()); - } - - public void testComapreNullCases() { - // Test null cases and classCast issues. - TextValue val = new TextValue("go/"); - try { - val.compareTo(null); - fail(); - } catch (NullPointerException e) { - // Expected behavior. - } - try { - val.compareTo(new NumberValue(123)); - fail(); - } catch (ClassCastException e) { - // Expected behavior. - } - // Test same object. - assertTrue(0 == val.compareTo(val)); - - // Test that compareTo can cast. - Value val2 = new TextValue("go/"); - assertTrue(0 == val.compareTo(val2)); - } - - public void testIsNull() { - TextValue val = TextValue.getNullValue(); - TextValue val1 = new TextValue("cheers"); - assertTrue(val.isNull()); - assertFalse(val1.isNull()); - } - - /** - * Tests the localized comparator. - */ - public void testLocalizedComparator() { - // Test that strings are compared according to the given locale. - Comparator rootComparator = TextValue.getTextLocalizedComparator( - ULocale.ROOT); - Comparator frComparator = TextValue.getTextLocalizedComparator( - ULocale.FRENCH); - TextValue text1 = new TextValue("cot\u00E9"); - TextValue text2 = new TextValue("c\u00F4te"); - assertEquals(-1, rootComparator.compare(text1, text2)); - assertEquals(1, frComparator.compare(text1, text2)); - } - - public void testToQueryString() { - TextValue t1 = new TextValue("foo bar"); - TextValue t2 = new TextValue("foo\"bar"); - TextValue t3 = new TextValue("foo'bar"); - TextValue t4 = new TextValue("both \" and '"); - - assertEquals("\"foo bar\"", t1.toQueryString()); - assertEquals("'foo\"bar'", t2.toQueryString()); - assertEquals("\"foo'bar\"", t3.toQueryString()); - - try { - t4.toQueryString(); - fail("Should have thrown an exception."); - } catch (RuntimeException e) { - // Everything's OK. - } - } -} \ No newline at end of file diff --git a/src/test/java/com/google/visualization/datasource/datatable/value/TimeOfDayValueTest.java b/src/test/java/com/google/visualization/datasource/datatable/value/TimeOfDayValueTest.java deleted file mode 100644 index 0b2bdb0..0000000 --- a/src/test/java/com/google/visualization/datasource/datatable/value/TimeOfDayValueTest.java +++ /dev/null @@ -1,383 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.datatable.value; - -import com.ibm.icu.util.Calendar; -import com.ibm.icu.util.GregorianCalendar; -import com.ibm.icu.util.TimeZone; - -import junit.framework.TestCase; - -/** - * Test for TimeOfDayValue. - * - * @author Hillel M. - */ -public class TimeOfDayValueTest extends TestCase { - - public void testNullValue() { - TimeOfDayValue value = TimeOfDayValue.getNullValue(); - assertTrue(value.isNull()); - value = new TimeOfDayValue(1, 2, 31); - assertFalse(value.isNull()); - } - - public void testConstructorIllegalValues() { - // Check the Exception is thrown. - try { - TimeOfDayValue value = new TimeOfDayValue(24, 0, 0); - // Shouldn't be here. - assertFalse(true); - } catch (IllegalArgumentException e) { - // Expected behavior. - } - try { - TimeOfDayValue value = new TimeOfDayValue(-1, 0, 0); - // Shouldn't be here. - assertFalse(true); - } catch (IllegalArgumentException e) { - // Expected behavior. - } - try { - TimeOfDayValue value = new TimeOfDayValue(0, 70, 0); - // Shouldn't be here. - assertFalse(true); - } catch (IllegalArgumentException e) { - // Expected behavior. - } - try { - TimeOfDayValue value = new TimeOfDayValue(0, -1, 0); - // Shouldn't be here. - assertFalse(true); - } catch (IllegalArgumentException e) { - // Expected behavior. - } - try { - TimeOfDayValue value = new TimeOfDayValue(0, 0, 65); - // Shouldn't be here. - assertFalse(true); - } catch (IllegalArgumentException e) { - // Expected behavior. - } - try { - TimeOfDayValue value = new TimeOfDayValue(0, 0, -10); - // Shouldn't be here. - assertFalse(true); - } catch (IllegalArgumentException e) { - // Expected behavior. - } - try { - TimeOfDayValue value = new TimeOfDayValue(24, 0, 2, 0); - // Shouldn't be here. - assertFalse(true); - } catch (IllegalArgumentException e) { - // Expected behavior. - } - try { - TimeOfDayValue value = new TimeOfDayValue(-1, 12, 0, 0); - // Shouldn't be here. - assertFalse(true); - } catch (IllegalArgumentException e) { - // Expected behavior. - } - try { - TimeOfDayValue value = new TimeOfDayValue(0, 70, 0, 0); - // Shouldn't be here. - assertFalse(true); - } catch (IllegalArgumentException e) { - // Expected behavior. - } - try { - TimeOfDayValue value = new TimeOfDayValue(0, -1, 0, 500); - // Shouldn't be here. - assertFalse(true); - } catch (IllegalArgumentException e) { - // Expected behavior. - } - try { - TimeOfDayValue value = new TimeOfDayValue(0, 0, 1500, 0); - // Shouldn't be here. - assertFalse(true); - } catch (IllegalArgumentException e) { - // Expected behavior. - } - try { - TimeOfDayValue value = new TimeOfDayValue(0, 0, -10, 0); - // Shouldn't be here. - assertFalse(true); - } catch (IllegalArgumentException e) { - // Expected behavior. - } - try { - TimeOfDayValue value = new TimeOfDayValue(0, 0, 0, 1500); - // Shouldn't be here. - assertFalse(true); - } catch (IllegalArgumentException e) { - // Expected behavior. - } - try { - TimeOfDayValue value = new TimeOfDayValue(0, 0, 0, -10); - // Shouldn't be here. - assertFalse(true); - } catch (IllegalArgumentException e) { - // Expected behavior. - } - } - - public void testConstructor() { - // Test if the construction does not fail. - try { - TimeOfDayValue value = new TimeOfDayValue(12, 12, 31); - assertNotNull(value); - assertFalse(value.isNull()); - } catch (IllegalArgumentException e) { - // should not be here - assertFalse("An exception was not supposed to be thorwn", true); - } - try { - TimeOfDayValue value = new TimeOfDayValue(12, 12, 31, 666); - assertNotNull(value); - assertFalse(value.isNull()); - } catch (IllegalArgumentException e) { - // should not be here - assertFalse("An exception was not supposed to be thorwn", true); - } - } - - public void testCalendarConstructor() { - // All fields are set in the calendar although only hour, minute and seconds - // are requried. - GregorianCalendar calendar = new GregorianCalendar(2006, 1, 1, 21, 24, 25); - TimeOfDayValue value = null; - calendar.setTimeZone(TimeZone.getTimeZone("IST")); - // Check exception thrown for non GMT time zone. - try { - value = new TimeOfDayValue(calendar); - fail(); - } catch (IllegalArgumentException iae) { - // do nothing - } - calendar.setTimeZone(TimeZone.getTimeZone("GMT")); - // Check exception not thrown for GMT time zone. - try { - value = new TimeOfDayValue(calendar); - } catch (IllegalArgumentException iae) { - fail(); - } - // Verify values - default milliseconds. - assertEquals(21, value.getHours()); - assertEquals(24, value.getMinutes()); - assertEquals(25, value.getSeconds()); - assertEquals(0, value.getMilliseconds()); - - // Non default milliseconds. - calendar.set(GregorianCalendar.MILLISECOND, 123); - value = new TimeOfDayValue(calendar); - assertEquals(123, value.getMilliseconds()); - } - - public void testGetType() { - TimeOfDayValue value = new TimeOfDayValue(21, 40, 30); - assertEquals(value.getType(), ValueType.TIMEOFDAY); - value = TimeOfDayValue.getNullValue(); - assertEquals(value.getType(), ValueType.TIMEOFDAY); - } - - public void testToString() { - TimeOfDayValue value = new TimeOfDayValue(20, 10, 5); - assertEquals(value.toString(), "20:10:05"); - value = new TimeOfDayValue(20, 10, 5, 987); - assertEquals(value.toString(), "20:10:05.987"); - value = TimeOfDayValue.getNullValue(); - assertEquals(value.toString(), "null"); - } - - public void testGetHours() { - TimeOfDayValue value = new TimeOfDayValue(12, 23, 31, 134); - assertTrue(value.getHours() == 12); - } - - public void testGetMinutes() { - TimeOfDayValue value = new TimeOfDayValue(12, 23, 31, 134); - assertTrue(value.getMinutes() == 23); - } - - public void testGetSeconds() { - TimeOfDayValue value = new TimeOfDayValue(12, 23, 31, 134); - assertTrue(value.getSeconds() == 31); - } - - public void testGetMilliseconds() { - TimeOfDayValue value = new TimeOfDayValue(12, 23, 31, 134); - assertTrue(value.getMilliseconds() == 134); - } - - public void testGetHoursNull(){ - TimeOfDayValue val = TimeOfDayValue.getNullValue(); - try { - val.getHours(); - assertFalse(true); - } catch (NullValueException e) { - // Expected behavior. - } - } - - public void testGetMinutesNull(){ - TimeOfDayValue val = TimeOfDayValue.getNullValue(); - try { - val.getMinutes(); - assertFalse(true); - } catch (NullValueException e) { - // Expected behavior. - } - } - - public void testGetSecondsNull(){ - TimeOfDayValue val = TimeOfDayValue.getNullValue(); - try { - val.getSeconds(); - assertFalse(true); - } catch (NullValueException e) { - // Expected behavior. - } - } - - public void testGetMilliNull(){ - TimeOfDayValue val = TimeOfDayValue.getNullValue(); - try { - val.getMilliseconds(); - assertFalse(true); - } catch (NullValueException e) { - // Expected behavior. - } - } - - public void testCompare(){ - // Test hours. - TimeOfDayValue val01 = new TimeOfDayValue(21, 23, 50, 500); - TimeOfDayValue val02 = new TimeOfDayValue(20, 23, 50, 500); - TimeOfDayValue val03 = new TimeOfDayValue(22, 23, 50, 500); - - assertTrue(val01.compareTo(val02) > 0); - assertTrue(val01.compareTo(val03) < 0); - - // Test minutes. - TimeOfDayValue val11 = new TimeOfDayValue(21, 23, 50, 500); - TimeOfDayValue val12 = new TimeOfDayValue(21, 20, 50, 500); - TimeOfDayValue val13 = new TimeOfDayValue(21, 24, 50, 500); - - assertTrue(val11.compareTo(val12) > 0); - assertTrue(val11.compareTo(val13) < 0); - - // Test seconds. - TimeOfDayValue val31 = new TimeOfDayValue(21, 23, 50, 500); - TimeOfDayValue val32 = new TimeOfDayValue(21, 23, 40, 500); - TimeOfDayValue val33 = new TimeOfDayValue(21, 23, 55, 500); - - assertTrue(val31.compareTo(val32) > 0); - assertTrue(val31.compareTo(val33) < 0); - - // Test milliseconds. - TimeOfDayValue val41 = new TimeOfDayValue(21, 23, 50, 600); - TimeOfDayValue val42 = new TimeOfDayValue(21, 23, 50, 500); - TimeOfDayValue val43 = new TimeOfDayValue(21, 23, 50, 780); - - assertTrue(val41.compareTo(val42) > 0); - assertTrue(val41.compareTo(val43) < 0); - - // Test equals - TimeOfDayValue val51 = new TimeOfDayValue(13, 3, 50, 500); - TimeOfDayValue val52 = new TimeOfDayValue(13, 3, 50, 500); - TimeOfDayValue val53 = new TimeOfDayValue(10, 20, 10); - TimeOfDayValue val54 = new TimeOfDayValue(10, 20, 10); - TimeOfDayValue val55 = new TimeOfDayValue(10, 20, 10, 0); - - assertTrue(val51.compareTo(val52) == 0); - assertTrue(val53.compareTo(val54) == 0); - assertTrue(val53.compareTo(val55) == 0); - } - - public void testCompareNullCases() { - // Test null cases and classCast issues. - TimeOfDayValue val = new TimeOfDayValue(13, 3, 50, 500); - try { - val.compareTo(null); - fail(); - } catch (NullPointerException e) { - // Expected behavior. - } - - try { - val.compareTo(BooleanValue.FALSE); - fail(); - } catch (ClassCastException e) { - // Expected behavior. - } - - // Test NULL_VALUE cases. - TimeOfDayValue val1 = new TimeOfDayValue(12, 23, 1, 1); - TimeOfDayValue valNull = TimeOfDayValue.getNullValue(); - - assertTrue(0 < val1.compareTo(valNull)); - assertTrue(0 > valNull.compareTo(val)); - - // Test same object. - assertTrue(0 == valNull.compareTo(TimeOfDayValue.getNullValue())); - assertTrue(0 == val.compareTo(val)); - - // Test that compareTo can cast. - Value val2 = new TimeOfDayValue(13, 43, 50, 500); - assertTrue(0 > val.compareTo(val2)); - Value val3 = TimeOfDayValue.getNullValue(); - assertTrue(0 < val.compareTo(val3)); - } - - /** - * Checks that the hasCode behaves in a reasonable way and does not map 3 different values to the - * same key. - * However, since this might be the case for some different hashCode function - * then in that case these 3 values should be replaced. - */ - public void testHashCode() { - TimeOfDayValue val1 = new TimeOfDayValue(10, 20, 20, 100); - TimeOfDayValue val2 = new TimeOfDayValue(1, 12, 20, 150); - TimeOfDayValue val3 = new TimeOfDayValue(10, 20, 25); - - assertFalse((val1.hashCode() == val2.hashCode()) - || (val1.hashCode() == val3.hashCode())); - - TimeOfDayValue val = TimeOfDayValue.getNullValue(); - assertTrue(val.hashCode() == 0); - } - - public void testGetValueToFormat() { - TimeOfDayValue val1 = new TimeOfDayValue(12, 23, 12, 111); - TimeOfDayValue nullVal = TimeOfDayValue.getNullValue(); - - assertNull(nullVal.getObjectToFormat()); - GregorianCalendar cal = new GregorianCalendar(1899, 11, 30, 12, 23, 12); - cal.set(Calendar.MILLISECOND, 111); - cal.setTimeZone(TimeZone.getTimeZone("GMT")); - assertEquals(cal, val1.getObjectToFormat()); - } - - public void testToQueryString() { - TimeOfDayValue val1 = new TimeOfDayValue(12, 23, 12, 111); - TimeOfDayValue val2 = new TimeOfDayValue(2, 3, 4); - - assertEquals("TIMEOFDAY '12:23:12.111'", val1.toQueryString()); - assertEquals("TIMEOFDAY '2:3:4'", val2.toQueryString()); - } -} \ No newline at end of file diff --git a/src/test/java/com/google/visualization/datasource/datatable/value/ValueTest.java b/src/test/java/com/google/visualization/datasource/datatable/value/ValueTest.java deleted file mode 100644 index c8ea0d4..0000000 --- a/src/test/java/com/google/visualization/datasource/datatable/value/ValueTest.java +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.datatable.value; - -import junit.framework.TestCase; - -/** - * Value Tester. - * - * @author Hillel M. - */ -public class ValueTest extends TestCase { - - public void testCompareTo() { - Value val1 = new DateValue(2007, 1, 23); - Value val2 = new DateValue(2007, 1, 23); - Value val4 = new DateValue(2007, 1, 20); - - Value valTime1 = new TimeOfDayValue(10, 11, 21, 222); - - // Equal objects. - assertTrue(0 == val1.compareTo(val1)); - assertTrue(0 == val1.compareTo(val2)); - assertTrue(0 == val2.compareTo(val1)); - - // Same class x > y. - assertTrue(0 < val2.compareTo(val4)); - assertTrue(0 > val4.compareTo(val2)); - - // Different class x > y. - try { - val2.compareTo(valTime1); - fail(); - } catch (ClassCastException e) { - // Expected behavior. - } - } - - public void testEquals() { - Number number = new Double(-12.3); - Value numberValue1 = new NumberValue(-12.3); - Value numberValue2 = new NumberValue(-12.3); - Value numberValue3 = new NumberValue(12.3343); - Value timeValue = new TimeOfDayValue(12, 1, 2, 3); - - // null == other. - assertFalse(numberValue1.equals(null)); - - // other.Class != this.Class. - assertFalse(numberValue1.equals(timeValue)); - assertFalse(timeValue.equals(numberValue1)); - assertFalse(numberValue1.equals(number)); - - // this == other. - assertTrue(numberValue2.equals(numberValue2)); - - // equal objects. - assertTrue(numberValue1.equals(numberValue2)); - - // not equal Values. - assertFalse(numberValue1.equals(numberValue3)); - assertFalse(numberValue1.equals(timeValue)); - } -} \ No newline at end of file diff --git a/src/test/java/com/google/visualization/datasource/datatable/value/ValueTypeTest.java b/src/test/java/com/google/visualization/datasource/datatable/value/ValueTypeTest.java deleted file mode 100644 index 3f8f3f9..0000000 --- a/src/test/java/com/google/visualization/datasource/datatable/value/ValueTypeTest.java +++ /dev/null @@ -1,208 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.datatable.value; - -import com.google.visualization.datasource.base.TypeMismatchException; - -import com.ibm.icu.util.GregorianCalendar; -import com.ibm.icu.util.TimeZone; -import junit.framework.TestCase; - -/** - * A unit test for ValueType. - * - * @author Yaniv S. - */ -public class ValueTypeTest extends TestCase { - - /** - * Tests ValueType.createValue(); - */ - public void testCreateValue() { - // Test creating a TextValue. - try { - Value v = ValueType.TEXT.createValue("Text value"); - assertTrue(v.getType() == ValueType.TEXT); - TextValue tv = (TextValue) v; - assertEquals(tv.getValue(), "Text value"); - } catch (TypeMismatchException e) { - fail(); - } - - // Verify that an exception is thrown on type mismatch for TextValue. - try { - Value v = ValueType.TEXT.createValue(5); - fail(); - } catch (TypeMismatchException e) { - // Do nothing, this is the expected behavior. - } - - // Test creating a null TextValue. - try { - Value v = ValueType.TEXT.createValue(null); - assertTrue(v.getType() == ValueType.TEXT); - TextValue tv = (TextValue) v; - assertEquals(tv.getValue(), ""); - } catch (TypeMismatchException e) { - // Do nothing, this is the expected behavior. - } - - // Test creating a NumberValue. - try { - Value v = ValueType.NUMBER.createValue(5.3); - assertTrue(v.getType() == ValueType.NUMBER); - NumberValue nv = (NumberValue) v; - assertEquals(nv.getValue(), 5.3); - } catch (TypeMismatchException e) { - fail(); - } - - // Verify that an exception is thrown on type mismatch for NumberValue. - try { - Value v = ValueType.NUMBER.createValue("abc"); - fail(); - } catch (TypeMismatchException e) { - // Do nothing, this is the expected behavior. - } - - // Test creating a null NumberValue. - try { - Value v = ValueType.NUMBER.createValue(null); - assertTrue(v.getType() == ValueType.NUMBER); - NumberValue nv = (NumberValue) v; - assertEquals(nv, NumberValue.getNullValue()); - } catch (TypeMismatchException e) { - // Do nothing, this is the expected behavior. - } - - // Test creating a BooleanValue. - try { - Value v = ValueType.BOOLEAN.createValue(true); - assertTrue(v.getType() == ValueType.BOOLEAN); - BooleanValue bv = (BooleanValue) v; - assertEquals(bv.getValue(), true); - } catch (TypeMismatchException e) { - fail(); - } - - // Verify that an exception is thrown on type mismatch for BooleanValue. - try { - Value v = ValueType.BOOLEAN.createValue("abc"); - fail(); - } catch (TypeMismatchException e) { - // Do nothing, this is the expected behavior. - } - - // Test creating a null BooleanValue. - try { - Value v = ValueType.BOOLEAN.createValue(null); - assertTrue(v.getType() == ValueType.BOOLEAN); - BooleanValue bv = (BooleanValue) v; - assertEquals(bv, BooleanValue.getNullValue()); - } catch (TypeMismatchException e) { - // Do nothing, this is the expected behavior. - } - - // Test creating a DateValue. - try { - GregorianCalendar calendar = new GregorianCalendar(2009, 2, 15); - calendar.setTimeZone(TimeZone.getTimeZone("GMT")); - Value v = ValueType.DATE.createValue(calendar); - assertTrue(v.getType() == ValueType.DATE); - DateValue dv = (DateValue) v; - assertEquals(dv.compareTo(new DateValue(calendar)), 0); - } catch (TypeMismatchException e) { - fail(); - } - - // Verify that an exception is thrown on type mismatch for DateValue. - try { - Value v = ValueType.DATE.createValue("abc"); - fail(); - } catch (TypeMismatchException e) { - // Do nothing, this is the expected behavior. - } - - // Test creating a null DateValue. - try { - Value v = ValueType.DATE.createValue(null); - assertTrue(v.getType() == ValueType.DATE); - DateValue dv = (DateValue) v; - assertEquals(dv, DateValue.getNullValue()); - } catch (TypeMismatchException e) { - // Do nothing, this is the expected behavior. - } - - // Test creating a DateTimeValue. - try { - GregorianCalendar calendar = new GregorianCalendar(2009, 2, 15, 12, 30, 14); - calendar.setTimeZone(TimeZone.getTimeZone("GMT")); - Value v = ValueType.DATETIME.createValue(calendar); - assertTrue(v.getType() == ValueType.DATETIME); - DateTimeValue dtv = (DateTimeValue) v; - assertEquals(dtv.compareTo(new DateTimeValue(calendar)), 0); - } catch (TypeMismatchException e) { - fail(); - } - - // Verify that an exception is thrown on type mismatch for DateTimeValue. - try { - Value v = ValueType.DATETIME.createValue("abc"); - fail(); - } catch (TypeMismatchException e) { - // Do nothing, this is the expected behavior. - } - - // Test creating a null DateTimeValue. - try { - Value v = ValueType.DATETIME.createValue(null); - assertTrue(v.getType() == ValueType.DATETIME); - DateTimeValue dtv = (DateTimeValue) v; - assertEquals(dtv, DateTimeValue.getNullValue()); - } catch (TypeMismatchException e) { - // Do nothing, this is the expected behavior. - } - - // Test creating a TimeOfDayValue. - try { - GregorianCalendar calendar = new GregorianCalendar(2009, 2, 15, 12, 30, 14); - calendar.setTimeZone(TimeZone.getTimeZone("GMT")); - Value v = ValueType.TIMEOFDAY.createValue(calendar); - assertTrue(v.getType() == ValueType.TIMEOFDAY); - TimeOfDayValue todv = (TimeOfDayValue) v; - assertEquals(todv.compareTo(new TimeOfDayValue(calendar)), 0); - } catch (TypeMismatchException e) { - fail(); - } - - // Verify that an exception is thrown on type mismatch for TimeOfDayValue. - try { - Value v = ValueType.DATETIME.createValue("abc"); - fail(); - } catch (TypeMismatchException e) { - // Do nothing, this is the expected behavior. - } - - // Test creating a null DateTimeValue. - try { - Value v = ValueType.TIMEOFDAY.createValue(null); - assertTrue(v.getType() == ValueType.TIMEOFDAY); - TimeOfDayValue todv = (TimeOfDayValue) v; - assertEquals(todv, TimeOfDayValue.getNullValue()); - } catch (TypeMismatchException e) { - // Do nothing, this is the expected behavior. - } - } -} diff --git a/src/test/java/com/google/visualization/datasource/query/ColumnColumnFilterTest.java b/src/test/java/com/google/visualization/datasource/query/ColumnColumnFilterTest.java deleted file mode 100644 index 26a7420..0000000 --- a/src/test/java/com/google/visualization/datasource/query/ColumnColumnFilterTest.java +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query; - -import com.google.visualization.datasource.datatable.ColumnDescription; -import com.google.visualization.datasource.datatable.DataTable; -import com.google.visualization.datasource.datatable.TableCell; -import com.google.visualization.datasource.datatable.TableRow; -import com.google.visualization.datasource.datatable.value.ValueType; - -import junit.framework.TestCase; - - -/** - * Test for ColumnColumnFilter - * - * @author Yonatan B.Y. - */ -public class ColumnColumnFilterTest extends TestCase { - public void testMatch() { - TableRow row = new TableRow(); - row.addCell(new TableCell("a")); - row.addCell(new TableCell(123)); - row.addCell(new TableCell("a")); - - DataTable table = new DataTable(); - table.addColumn(new ColumnDescription("c1", ValueType.TEXT, "c1")); - table.addColumn(new ColumnDescription("c2", ValueType.TEXT, "c2")); - table.addColumn(new ColumnDescription("c3", ValueType.TEXT, "c3")); - - ColumnColumnFilter filter = new ColumnColumnFilter(new SimpleColumn("c1"), - new SimpleColumn("c3"), ComparisonFilter.Operator.LE); - assertTrue(filter.isMatch(table, row)); - } - - public void testNoMatch() { - TableRow row = new TableRow(); - row.addCell(new TableCell("a")); - row.addCell(new TableCell(123)); - row.addCell(new TableCell("a")); - - DataTable table = new DataTable(); - table.addColumn(new ColumnDescription("c1", ValueType.TEXT, "c1")); - table.addColumn(new ColumnDescription("c2", ValueType.TEXT, "c2")); - table.addColumn(new ColumnDescription("c3", ValueType.TEXT, "c3")); - - ColumnColumnFilter filter = new ColumnColumnFilter(new SimpleColumn("c3"), - new SimpleColumn("c1"), ComparisonFilter.Operator.NE); - assertFalse(filter.isMatch(table, row)); - } - - public void testToQueryString() { - ColumnColumnFilter filter1 = new ColumnColumnFilter(new SimpleColumn("c3"), - new AggregationColumn(new SimpleColumn("c4"), AggregationType.AVG), - ComparisonFilter.Operator.NE); - ColumnColumnFilter filter2 = new ColumnColumnFilter( - new AggregationColumn(new SimpleColumn("c4"), AggregationType.SUM), - new SimpleColumn("c1"), ComparisonFilter.Operator.STARTS_WITH); - - assertEquals("`c3` != AVG(`c4`)", filter1.toQueryString()); - assertEquals("SUM(`c4`) STARTS WITH `c1`", filter2.toQueryString()); - } -} diff --git a/src/test/java/com/google/visualization/datasource/query/ColumnValueFilterTest.java b/src/test/java/com/google/visualization/datasource/query/ColumnValueFilterTest.java deleted file mode 100644 index 8a6b16f..0000000 --- a/src/test/java/com/google/visualization/datasource/query/ColumnValueFilterTest.java +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query; - -import com.google.visualization.datasource.datatable.ColumnDescription; -import com.google.visualization.datasource.datatable.DataTable; -import com.google.visualization.datasource.datatable.TableCell; -import com.google.visualization.datasource.datatable.TableRow; -import com.google.visualization.datasource.datatable.value.DateValue; -import com.google.visualization.datasource.datatable.value.NumberValue; -import com.google.visualization.datasource.datatable.value.TextValue; -import com.google.visualization.datasource.datatable.value.ValueType; - -import junit.framework.TestCase; - - -/** - * Test for ColumnValueFilter - * - * @author Yonatan B.Y. - */ -public class ColumnValueFilterTest extends TestCase { - - public void testVariousFilters() { - TableRow row = new TableRow(); - row.addCell(new TableCell("a")); - row.addCell(new TableCell(123)); - row.addCell(new TableCell("a")); - - DataTable table = new DataTable(); - table.addColumn(new ColumnDescription("c1", ValueType.TEXT, "c1")); - table.addColumn(new ColumnDescription("c2", ValueType.TEXT, "c2")); - table.addColumn(new ColumnDescription("c3", ValueType.TEXT, "c3")); - - ColumnValueFilter filter = new ColumnValueFilter(new SimpleColumn("c2"), - new NumberValue(100), ComparisonFilter.Operator.GE); - assertTrue(filter.isMatch(table, row)); - filter = new ColumnValueFilter(new SimpleColumn("c2"), - new NumberValue(100), ComparisonFilter.Operator.LE, true); - assertTrue(filter.isMatch(table, row)); - filter = new ColumnValueFilter(new SimpleColumn("c2"), - new NumberValue(100), ComparisonFilter.Operator.LE); - assertFalse(filter.isMatch(table, row)); - filter = new ColumnValueFilter(new SimpleColumn("c1"), - new TextValue("b"), ComparisonFilter.Operator.GT); - assertFalse(filter.isMatch(table, row)); - filter = new ColumnValueFilter(new SimpleColumn("c1"), - new TextValue("b"), ComparisonFilter.Operator.LT, true); - assertFalse(filter.isMatch(table, row)); - } - - public void testToQueryString() { - ColumnValueFilter filter1 = new ColumnValueFilter(new SimpleColumn("c2"), - new NumberValue(100.23), ComparisonFilter.Operator.GE); - ColumnValueFilter filter2 = new ColumnValueFilter( - new AggregationColumn(new SimpleColumn("c3"), AggregationType.MAX), - new DateValue(2007, 2, 3), ComparisonFilter.Operator.LIKE, true); - - assertEquals("`c2` >= 100.23", filter1.toQueryString()); - assertEquals("DATE '2007-3-3' LIKE MAX(`c3`)", filter2.toQueryString()); - - } -} diff --git a/src/test/java/com/google/visualization/datasource/query/ComparisonFilterTest.java b/src/test/java/com/google/visualization/datasource/query/ComparisonFilterTest.java deleted file mode 100644 index 0ca5783..0000000 --- a/src/test/java/com/google/visualization/datasource/query/ComparisonFilterTest.java +++ /dev/null @@ -1,327 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query; - -import com.google.visualization.datasource.datatable.DataTable; -import com.google.visualization.datasource.datatable.TableRow; -import com.google.visualization.datasource.datatable.value.BooleanValue; -import com.google.visualization.datasource.datatable.value.DateValue; -import com.google.visualization.datasource.datatable.value.NumberValue; -import com.google.visualization.datasource.datatable.value.TextValue; -import com.google.visualization.datasource.datatable.value.Value; - -import junit.framework.TestCase; - -import java.util.List; -import java.util.Set; - - -/** - * Test for ComparisonFilter - * - * @author Yonatan B.Y. - */ -public class ComparisonFilterTest extends TestCase { - - /** - * This is a concrete class deriving from ComparisonFilter. - * It is here for two reasons: - * 1. So we can test the abstract class ComparisonFilter without explicitly - * using one of its known subclasses. - */ - public static class ConcreteComparisonFilter extends ComparisonFilter { - - public ConcreteComparisonFilter(Operator op) { - super(op); - } - - @Override - public boolean isMatch(DataTable table, TableRow row) { - return false; - } - - @Override - public Set getAllColumnIds() { - return null; - } - - @Override - public List getScalarFunctionColumns() { - return null; - } - - @Override - public List getAggregationColumns() { - return null; - } - - protected String getInnerCanonicalString() { - return null; - } - - public String getToken() { - return null; - } - - /** - * This is here to test the protected method isOperatorMatch. - * @param v1 The first value. - * @param v2 The second value. - * @return Whether or not v1 operator v2. - */ - @Override - public boolean isOperatorMatch(Value v1, Value v2) { - return super.isOperatorMatch(v1, v2); - } - - @Override - public String toQueryString() { - return null; - } - - @Override - public boolean equals(Object obj) { - throw new UnsupportedOperationException( - "Equals is not implemented in ComparisonFilterTest"); - } - - @Override - public int hashCode() { - throw new UnsupportedOperationException( - "hashCode is not implemented in ComparisonFilterTest"); - } - } - - /** - * Tests the regular equality and order operators. - */ - public void testCheck() { - ConcreteComparisonFilter equalsFilter = new ConcreteComparisonFilter( - ComparisonFilter.Operator.EQ); - ConcreteComparisonFilter notEqualsFilter = new ConcreteComparisonFilter( - ComparisonFilter.Operator.NE); - ConcreteComparisonFilter lessThanFilter = new ConcreteComparisonFilter( - ComparisonFilter.Operator.LT); - ConcreteComparisonFilter greaterThanFilter = new ConcreteComparisonFilter( - ComparisonFilter.Operator.GT); - ConcreteComparisonFilter lessOrEqualsFilter = new ConcreteComparisonFilter( - ComparisonFilter.Operator.LE); - ConcreteComparisonFilter greaterOrEqualsFilter = - new ConcreteComparisonFilter(ComparisonFilter.Operator.GE); - - assertTrue(equalsFilter.isOperatorMatch(new NumberValue(123), - new NumberValue(123))); - assertTrue(equalsFilter.isOperatorMatch(new TextValue("abc"), - new TextValue("abc"))); - assertTrue(equalsFilter.isOperatorMatch(BooleanValue.TRUE, - BooleanValue.TRUE)); - assertFalse(equalsFilter.isOperatorMatch(new NumberValue(123), - new NumberValue(345))); - assertFalse(equalsFilter.isOperatorMatch(new TextValue("ab"), - new TextValue("abc"))); - - assertTrue(lessThanFilter.isOperatorMatch(new NumberValue(123.123), - new NumberValue(123.124))); - assertTrue(lessThanFilter.isOperatorMatch(new TextValue("abc"), - new TextValue("abd"))); - assertTrue(lessThanFilter.isOperatorMatch(BooleanValue.FALSE, - BooleanValue.TRUE)); - assertFalse(lessThanFilter.isOperatorMatch(new NumberValue(7), - new NumberValue(-14))); - assertFalse(lessThanFilter.isOperatorMatch(new TextValue("bbb"), - new TextValue("aaa"))); - assertFalse(lessThanFilter.isOperatorMatch(BooleanValue.TRUE, - BooleanValue.FALSE)); - - assertTrue(lessOrEqualsFilter.isOperatorMatch(new NumberValue(123), - new NumberValue(123))); - assertTrue(lessOrEqualsFilter.isOperatorMatch(new TextValue("abc"), - new TextValue("abc"))); - assertTrue(lessOrEqualsFilter.isOperatorMatch(BooleanValue.TRUE, - BooleanValue.TRUE)); - assertTrue(lessOrEqualsFilter.isOperatorMatch(new NumberValue(123.123), - new NumberValue(123.124))); - assertTrue(lessOrEqualsFilter.isOperatorMatch(new TextValue("abc"), - new TextValue("abd"))); - assertTrue(lessOrEqualsFilter.isOperatorMatch(BooleanValue.FALSE, - BooleanValue.TRUE)); - assertFalse(lessOrEqualsFilter.isOperatorMatch(new NumberValue(123), - new NumberValue(122.2))); - assertFalse(lessOrEqualsFilter.isOperatorMatch(new TextValue("ab"), - new TextValue("aa"))); - assertFalse(lessOrEqualsFilter.isOperatorMatch(new NumberValue(7), - new NumberValue(-14))); - assertFalse(lessOrEqualsFilter.isOperatorMatch(new TextValue("bbb"), - new TextValue("aaa"))); - assertFalse(lessOrEqualsFilter.isOperatorMatch(BooleanValue.TRUE, - BooleanValue.FALSE)); - - assertFalse(notEqualsFilter.isOperatorMatch(new NumberValue(123), - new NumberValue(123))); - assertFalse(notEqualsFilter.isOperatorMatch(new TextValue("abc"), - new TextValue("abc"))); - assertFalse(notEqualsFilter.isOperatorMatch(BooleanValue.TRUE, - BooleanValue.TRUE)); - assertTrue(notEqualsFilter.isOperatorMatch(new NumberValue(123), - new NumberValue(345))); - assertTrue(notEqualsFilter.isOperatorMatch(new TextValue("ab"), - new TextValue("abc"))); - - assertFalse(greaterOrEqualsFilter.isOperatorMatch(new NumberValue(123.123), - new NumberValue(123.124))); - assertFalse(greaterOrEqualsFilter.isOperatorMatch(new TextValue("abc"), - new TextValue("abd"))); - assertFalse(greaterOrEqualsFilter.isOperatorMatch(BooleanValue.FALSE, - BooleanValue.TRUE)); - assertTrue(greaterOrEqualsFilter.isOperatorMatch(new NumberValue(7), - new NumberValue(-14))); - assertTrue(greaterOrEqualsFilter.isOperatorMatch(new TextValue("bbb"), - new TextValue("aaa"))); - assertTrue(greaterOrEqualsFilter.isOperatorMatch(BooleanValue.TRUE, - BooleanValue.FALSE)); - - assertFalse(greaterThanFilter.isOperatorMatch(new NumberValue(123), - new NumberValue(123))); - assertFalse(greaterThanFilter.isOperatorMatch(new TextValue("abc"), - new TextValue("abc"))); - assertFalse(greaterThanFilter.isOperatorMatch(BooleanValue.TRUE, - BooleanValue.TRUE)); - assertFalse(greaterThanFilter.isOperatorMatch(new NumberValue(123.123), - new NumberValue(123.124))); - assertFalse(greaterThanFilter.isOperatorMatch(new TextValue("abc"), - new TextValue("abd"))); - assertFalse(greaterThanFilter.isOperatorMatch(BooleanValue.FALSE, - BooleanValue.TRUE)); - assertTrue(greaterThanFilter.isOperatorMatch(new NumberValue(123), - new NumberValue(122.2))); - assertTrue(greaterThanFilter.isOperatorMatch(new TextValue("ab"), - new TextValue("aa"))); - assertTrue(greaterThanFilter.isOperatorMatch(new NumberValue(7), - new NumberValue(-14))); - assertTrue(greaterThanFilter.isOperatorMatch(new TextValue("bbb"), - new TextValue("aaa"))); - assertTrue(greaterThanFilter.isOperatorMatch(BooleanValue.TRUE, - BooleanValue.FALSE)); - - // Test type mismatch: - assertFalse(greaterThanFilter.isOperatorMatch(new TextValue("blah"), - new NumberValue(123))); - assertFalse(equalsFilter.isOperatorMatch(new DateValue(2000, 3, 3), - BooleanValue.TRUE)); - } - - /** - * Tests the string-related operators. - */ - public void testStringOperators() { - ConcreteComparisonFilter containsFilter = new ConcreteComparisonFilter( - ComparisonFilter.Operator.CONTAINS); - ConcreteComparisonFilter startsWithFilter = new ConcreteComparisonFilter( - ComparisonFilter.Operator.STARTS_WITH); - ConcreteComparisonFilter endsWithFilter = new ConcreteComparisonFilter( - ComparisonFilter.Operator.ENDS_WITH); - ConcreteComparisonFilter matchesFilter = new ConcreteComparisonFilter( - ComparisonFilter.Operator.MATCHES); - ConcreteComparisonFilter likeFilter = new ConcreteComparisonFilter( - ComparisonFilter.Operator.LIKE); - - assertTrue(containsFilter.isOperatorMatch(new TextValue("blah blah"), - new TextValue("ah bl"))); - assertTrue(containsFilter.isOperatorMatch(new TextValue("foo bar"), - new TextValue("foo "))); - assertTrue(containsFilter.isOperatorMatch(new TextValue("foo bar"), - new TextValue(" bar"))); - assertFalse(containsFilter.isOperatorMatch(new TextValue("abc123"), - new TextValue("bd"))); - - assertTrue(startsWithFilter.isOperatorMatch(new TextValue("this is a " + - "text value"), new TextValue("this is"))); - assertFalse(startsWithFilter.isOperatorMatch(new TextValue("foo bar"), - new TextValue("oo bar"))); - - assertTrue(endsWithFilter.isOperatorMatch(new TextValue("this is a " + - "text value"), new TextValue("text value"))); - assertFalse(endsWithFilter.isOperatorMatch(new TextValue("foo bar"), - new TextValue("foo ba"))); - - assertTrue(matchesFilter.isOperatorMatch(new TextValue("aaaaaa123"), - new TextValue("a*123"))); - assertTrue(matchesFilter.isOperatorMatch(new TextValue("abcdefghijk"), - new TextValue("[a-k]+"))); - assertFalse(matchesFilter.isOperatorMatch(new TextValue("abc1234"), - new TextValue("a*123"))); - assertFalse(matchesFilter.isOperatorMatch(new TextValue("blah blah"), - new TextValue("%^@%!%$#^*&*$!@#$(((("))); - // Test partial - assertFalse(matchesFilter.isOperatorMatch(new TextValue("aaaaaaa123"), - new TextValue("a*"))); - - assertTrue(likeFilter.isOperatorMatch(new TextValue("aaaabbbccc"), - new TextValue("a%b_b%c"))); - assertFalse(likeFilter.isOperatorMatch(new TextValue("aaaabbbccc"), - new TextValue("aaqqb_c%c"))); - assertTrue(likeFilter.isOperatorMatch(new TextValue("aaaabbbccc"), - new TextValue("a%%b_b%c"))); - assertTrue(likeFilter.isOperatorMatch(new TextValue("aaaabbbccc"), - new TextValue("%"))); - assertTrue(likeFilter.isOperatorMatch(new TextValue("foo bar"), - new TextValue("foo_bar"))); - assertTrue(likeFilter.isOperatorMatch(new TextValue("foo%bar"), - new TextValue("foo_bar"))); - assertFalse(likeFilter.isOperatorMatch(new TextValue("blah blah"), - new TextValue("bla%b%aa"))); - assertTrue(likeFilter.isOperatorMatch(new TextValue("foobar"), - new TextValue("foo__r"))); - assertFalse(likeFilter.isOperatorMatch(new TextValue("foobr"), - new TextValue("foo__r"))); - assertFalse(likeFilter.isOperatorMatch(new TextValue("foobaar"), - new TextValue("foo__r"))); - assertTrue(likeFilter.isOperatorMatch(new TextValue("foobaar"), - new TextValue("foo__%_r"))); - assertTrue(likeFilter.isOperatorMatch(new TextValue("foobaaar"), - new TextValue("foo__%_r"))); - assertTrue(likeFilter.isOperatorMatch(new TextValue("foobaaaar"), - new TextValue("foo__%_r"))); - assertFalse(likeFilter.isOperatorMatch(new TextValue("foobar"), - new TextValue("foo__%_r"))); - assertFalse(likeFilter.isOperatorMatch(new TextValue("foobr"), - new TextValue("foo__%_r"))); - - // Partial match: - assertFalse(likeFilter.isOperatorMatch(new TextValue("blah blah"), - new TextValue("bla%b%a"))); - - // Test non-strings: - assertTrue(containsFilter.isOperatorMatch(new NumberValue(123), - new NumberValue(3))); - assertTrue(containsFilter.isOperatorMatch(new NumberValue(123.45), - new TextValue("23.4"))); - assertFalse(containsFilter.isOperatorMatch(new NumberValue(23423), - BooleanValue.TRUE)); - - assertTrue(startsWithFilter.isOperatorMatch(BooleanValue.FALSE, - new TextValue("fa"))); - - assertTrue(endsWithFilter.isOperatorMatch(new NumberValue(123.456), - new TextValue("456"))); - - assertTrue(matchesFilter.isOperatorMatch(new NumberValue(123), - new TextValue(".*"))); - - assertTrue(likeFilter.isOperatorMatch(new NumberValue(123), - new TextValue("_2%"))); - } - -} diff --git a/src/test/java/com/google/visualization/datasource/query/CompoundFilterTest.java b/src/test/java/com/google/visualization/datasource/query/CompoundFilterTest.java deleted file mode 100644 index 2928235..0000000 --- a/src/test/java/com/google/visualization/datasource/query/CompoundFilterTest.java +++ /dev/null @@ -1,162 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query; - -import com.google.common.collect.Lists; -import com.google.visualization.datasource.datatable.ColumnDescription; -import com.google.visualization.datasource.datatable.DataTable; -import com.google.visualization.datasource.datatable.TableCell; -import com.google.visualization.datasource.datatable.TableRow; -import com.google.visualization.datasource.datatable.value.BooleanValue; -import com.google.visualization.datasource.datatable.value.NumberValue; -import com.google.visualization.datasource.datatable.value.ValueType; - -import junit.framework.TestCase; - -import java.util.List; -import java.util.Set; - -/** - * Test for CompoundFilter. - * - * @author Yonatan B.Y. - */ -public class CompoundFilterTest extends TestCase { - public void testAndFilter() { - TableRow trueRow = new TableRow(); - trueRow.addCell(new TableCell("a")); - trueRow.addCell(new TableCell(123)); - trueRow.addCell(new TableCell("a")); - TableRow falseRow = new TableRow(); - falseRow.addCell(new TableCell("a")); - falseRow.addCell(new TableCell(123)); - falseRow.addCell(new TableCell("b")); - - DataTable table = new DataTable(); - table.addColumn(new ColumnDescription("c1", ValueType.TEXT, "c1")); - table.addColumn(new ColumnDescription("c2", ValueType.TEXT, "c2")); - table.addColumn(new ColumnDescription("c3", ValueType.TEXT, "c3")); - - ColumnColumnFilter filter1 = new ColumnColumnFilter(new SimpleColumn("c1"), - new SimpleColumn("c3"), ComparisonFilter.Operator.EQ); - ColumnValueFilter filter2 = new ColumnValueFilter(new SimpleColumn("c2"), - new NumberValue(100), ComparisonFilter.Operator.GT); - List subfilterList = Lists.newArrayList(); - subfilterList.add(filter1); - subfilterList.add(filter2); - CompoundFilter compoundFilter = new CompoundFilter( - CompoundFilter.LogicalOperator.AND, subfilterList); - assertTrue(compoundFilter.isMatch(table, trueRow)); - assertFalse(compoundFilter.isMatch(table, falseRow)); - } - - public void testOrFilter() { - TableRow falseRow = new TableRow(); - falseRow.addCell(new TableCell("a")); - falseRow.addCell(new TableCell(123)); - falseRow.addCell(new TableCell("a")); - TableRow trueRow = new TableRow(); - trueRow.addCell(new TableCell("a")); - trueRow.addCell(new TableCell(123)); - trueRow.addCell(new TableCell("b")); - - DataTable table = new DataTable(); - table.addColumn(new ColumnDescription("c1", ValueType.TEXT, "c1")); - table.addColumn(new ColumnDescription("c2", ValueType.TEXT, "c2")); - table.addColumn(new ColumnDescription("c3", ValueType.TEXT, "c3")); - - ColumnColumnFilter filter1 = new ColumnColumnFilter(new SimpleColumn("c1"), - new SimpleColumn("c3"), ComparisonFilter.Operator.NE); - ColumnValueFilter filter2 = new ColumnValueFilter(new SimpleColumn("c2"), - new NumberValue(1000), ComparisonFilter.Operator.GT); - List subfilterList = Lists.newArrayList(); - subfilterList.add(filter1); - subfilterList.add(filter2); - CompoundFilter compoundFilter = new CompoundFilter( - CompoundFilter.LogicalOperator.OR, subfilterList); - assertTrue(compoundFilter.isMatch(table, trueRow)); - assertFalse(compoundFilter.isMatch(table, falseRow)); - } - - public void testGetAllColumnIds() { - SimpleColumn col1 = new SimpleColumn("c1"); - SimpleColumn col2 = new SimpleColumn("c2"); - SimpleColumn col3 = new SimpleColumn("c3"); - SimpleColumn col4 = new SimpleColumn("c4"); - ColumnColumnFilter filter1 = new ColumnColumnFilter(col1, col3, - ComparisonFilter.Operator.NE); - ColumnValueFilter filter2 = new ColumnValueFilter(col2, - new NumberValue(1000), ComparisonFilter.Operator.GT); - ColumnColumnFilter filter3 = new ColumnColumnFilter(col1, col4, - ComparisonFilter.Operator.LE); - ColumnValueFilter filter4 = new ColumnValueFilter(col3, - BooleanValue.TRUE, ComparisonFilter.Operator.GT); - List subfilterList1 = Lists.newArrayList(); - subfilterList1.add(filter1); - subfilterList1.add(filter2); - CompoundFilter compoundFilter1 = new CompoundFilter( - CompoundFilter.LogicalOperator.OR, subfilterList1); - List subfilterList2 = Lists.newArrayList(); - subfilterList2.add(filter3); - subfilterList2.add(filter4); - CompoundFilter compoundFilter2 = new CompoundFilter( - CompoundFilter.LogicalOperator.AND, subfilterList2); - List subfilterList3 = Lists.newArrayList(); - subfilterList3.add(compoundFilter1); - subfilterList3.add(compoundFilter2); - CompoundFilter compoundFilter3 = new CompoundFilter( - CompoundFilter.LogicalOperator.OR, subfilterList3); - - Set allColumnIds = compoundFilter3.getAllColumnIds(); - assertTrue(allColumnIds.containsAll(Lists.newArrayList("c1", - "c2", "c3", "c4"))); - } - - public void testToQueryString() { - SimpleColumn col1 = new SimpleColumn("c1"); - AggregationColumn col2 = new AggregationColumn(new SimpleColumn("c2"), - AggregationType.COUNT); - SimpleColumn col3 = new SimpleColumn("c3"); - SimpleColumn col4 = new SimpleColumn("c4"); - ColumnColumnFilter filter1 = new ColumnColumnFilter(col1, col3, - ComparisonFilter.Operator.NE); - ColumnValueFilter filter2 = new ColumnValueFilter(col2, - new NumberValue(1000), ComparisonFilter.Operator.GT); - ColumnColumnFilter filter3 = new ColumnColumnFilter(col1, col4, - ComparisonFilter.Operator.CONTAINS); - ColumnValueFilter filter4 = new ColumnValueFilter(col3, - BooleanValue.TRUE, ComparisonFilter.Operator.GT, true); - List subfilterList1 = Lists.newArrayList(); - subfilterList1.add(filter1); - subfilterList1.add(filter2); - subfilterList1.add(filter3); - CompoundFilter compoundFilter1 = new CompoundFilter( - CompoundFilter.LogicalOperator.OR, subfilterList1); - List subfilterList2 = Lists.newArrayList(); - subfilterList2.add(filter3); - subfilterList2.add(filter4); - CompoundFilter compoundFilter2 = new CompoundFilter( - CompoundFilter.LogicalOperator.AND, subfilterList2); - List subfilterList3 = Lists.newArrayList(); - subfilterList3.add(compoundFilter1); - subfilterList3.add(compoundFilter2); - CompoundFilter compoundFilter3 = new CompoundFilter( - CompoundFilter.LogicalOperator.OR, subfilterList3); - - assertEquals("((`c1` != `c3`) OR (COUNT(`c2`) > 1000.0) OR (`c1` CONTAINS " - + "`c4`)) OR ((`c1` CONTAINS `c4`) AND (true > `c3`))", - compoundFilter3.toQueryString()); - } -} diff --git a/src/test/java/com/google/visualization/datasource/query/QueryTest.java b/src/test/java/com/google/visualization/datasource/query/QueryTest.java deleted file mode 100644 index 25e4af7..0000000 --- a/src/test/java/com/google/visualization/datasource/query/QueryTest.java +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query; - - -import com.google.common.collect.Lists; -import com.google.visualization.datasource.base.InvalidQueryException; -import com.google.visualization.datasource.datatable.value.TextValue; -import com.google.visualization.datasource.query.CompoundFilter.LogicalOperator; -import com.google.visualization.datasource.query.scalarfunction.Lower; -import com.google.visualization.datasource.query.scalarfunction.Quotient; - -import junit.framework.TestCase; - -/** - * A test for the Query class. - * - * @author Yonatan B.Y. - */ -public class QueryTest extends TestCase { - - /** - * A default query used for most of the tests. - */ - private Query q; - - /** - * Sets up the default query. - */ - @Override - public void setUp() throws Exception { - q = new Query(); - QuerySelection selection = new QuerySelection(); - selection.addColumn(new SimpleColumn("A")); - selection.addColumn(new AggregationColumn(new SimpleColumn("B"), AggregationType.MAX)); - q.setSelection(selection); - QuerySort sort = new QuerySort(); - sort.addSort(new ColumnSort(new SimpleColumn("A"), SortOrder.DESCENDING)); - q.setSort(sort); - QueryFilter filter = new ColumnValueFilter(new SimpleColumn("A"), new TextValue("foo"), - ComparisonFilter.Operator.GT); - q.setFilter(filter); - q.setRowLimit(7); - q.setRowOffset(17); - QueryLabels labels = new QueryLabels(); - labels.addLabel(new SimpleColumn("A"), "bar"); - q.setLabels(labels); - QueryFormat format = new QueryFormat(); - format.addPattern(new SimpleColumn("A"), "foo"); - q.setUserFormatOptions(format); - QueryGroup group = new QueryGroup(); - group.addColumn(new SimpleColumn("A")); - q.setGroup(group); - QueryPivot pivot = new QueryPivot(); - pivot.addColumn(new SimpleColumn("C")); - q.setPivot(pivot); - } - - /** - * Tests a validation that should not throw any exception. - */ - public void testValidatePositive() throws Exception { - q.validate(); - } - - /** - * Tests that duplicates are not allowed in the select clause. - */ - public void testValidateDuplicates() { - q.getSelection().addColumn(new SimpleColumn("D")); - try { - q.validate(); - fail(); - } catch (InvalidQueryException ex) { - // Do nothing. - } - } - - /** - * Tests that grouping and pivoting by the same column is not allowed. - */ - public void testValidateGroupAndPivotBySameColumn() { - q.getPivot().addColumn(new SimpleColumn("A")); - try { - q.validate(); - fail(); - } catch (InvalidQueryException ex) { - //Expected behavior. - } - } - - public void testAggregationsNotAllowedInGroup() throws Exception { - q.getGroup().addColumn(new AggregationColumn(new SimpleColumn("A"), AggregationType.AVG)); - try { - q.validate(); - fail(); - } catch (InvalidQueryException ex) { - // Great. - } - } - - public void testAggregationsNotAllowedInPivot() throws Exception { - q.getPivot().addColumn(new AggregationColumn(new SimpleColumn("A"), AggregationType.AVG)); - try { - q.validate(); - fail(); - } catch (InvalidQueryException ex) { - // Great. - } - } - - public void testAggregationsNotAllowedInFilter() throws Exception { - q.setFilter(new ColumnIsNullFilter( - new AggregationColumn(new SimpleColumn("A"), AggregationType.AVG))); - try { - q.validate(); - fail(); - } catch (InvalidQueryException ex) { - // Great. - } - } - - /** - * Tests toQueryString(). - */ - public void testToQueryString() { - q.setFilter(new CompoundFilter(LogicalOperator.AND, Lists.newArrayList( - new ColumnIsNullFilter(new ScalarFunctionColumn(Lists.newArrayList( - new SimpleColumn("F B")), Lower.getInstance())), - new ColumnIsNullFilter(new ScalarFunctionColumn(Lists.newArrayList( - new SimpleColumn("F"), new SimpleColumn("B")), Quotient.getInstance())), - q.getFilter()))); - assertEquals("SELECT `A`, MAX(`B`) WHERE (lower(`F B`) IS NULL) AND ((`F` / `B`) IS NULL) AND " - + "(`A` > \"foo\") GROUP BY `A` PIVOT `C` ORDER BY `A` DESC LIMIT 7 OFFSET 17 " - + "LABEL `A` \"bar\" FORMAT `A` \"foo\"", q.toQueryString()); - assertEquals("", new Query().toQueryString()); - } -} diff --git a/src/test/java/com/google/visualization/datasource/query/ScalarFunctionColumnTest.java b/src/test/java/com/google/visualization/datasource/query/ScalarFunctionColumnTest.java deleted file mode 100644 index 446601f..0000000 --- a/src/test/java/com/google/visualization/datasource/query/ScalarFunctionColumnTest.java +++ /dev/null @@ -1,190 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query; - -import com.google.common.collect.Lists; -import com.google.visualization.datasource.base.DataSourceException; -import com.google.visualization.datasource.datatable.ColumnDescription; -import com.google.visualization.datasource.datatable.DataTable; -import com.google.visualization.datasource.datatable.TableCell; -import com.google.visualization.datasource.datatable.TableRow; -import com.google.visualization.datasource.datatable.value.DateTimeValue; -import com.google.visualization.datasource.datatable.value.DateValue; -import com.google.visualization.datasource.datatable.value.NumberValue; -import com.google.visualization.datasource.datatable.value.TimeOfDayValue; -import com.google.visualization.datasource.datatable.value.Value; -import com.google.visualization.datasource.datatable.value.ValueType; -import com.google.visualization.datasource.query.scalarfunction.ScalarFunction; -import com.google.visualization.datasource.query.scalarfunction.TimeComponentExtractor; - -import junit.framework.TestCase; - -import java.util.List; - -/** - * Tests for ScalarFunctionColumn. - * - * @author Liron L. - */ -public class ScalarFunctionColumnTest extends TestCase { - - private ScalarFunctionColumn scalarFunctionColumn; - - @Override - public void setUp() throws Exception { - super.setUp(); - List columns1 = Lists.newArrayList(); - ScalarFunction scalarFunction1 = TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.MONTH); - - columns1.add(new SimpleColumn("col1")); - columns1.add(new SimpleColumn("col2")); - columns1.add(new AggregationColumn(new SimpleColumn("col3"), - AggregationType.getByCode("sum"))); - - ScalarFunctionColumn innerScalarFunctionColumn = - new ScalarFunctionColumn(columns1, scalarFunction1); - - List columns = Lists.newArrayList(); - ScalarFunction scalarFunction = TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.YEAR); - - columns.add(new SimpleColumn("col4")); - columns.add(new SimpleColumn("col5")); - columns.add(innerScalarFunctionColumn); - columns.add(new AggregationColumn(new SimpleColumn("col6"), - AggregationType.getByCode("sum"))); - columns.add(new SimpleColumn("col7")); - - scalarFunctionColumn = new ScalarFunctionColumn(columns, scalarFunction); - } - - public void testGetAllSimpleColumnIds() { - List expectedColumnIds = Lists.newArrayList("col4", "col5", "col1", - "col2", "col3", "col6", "col7"); - List columnIds = scalarFunctionColumn.getAllSimpleColumnIds(); - assertEquals(expectedColumnIds, columnIds); - } - - public void testGetValue() { - ScalarFunction scalarFunction = TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.YEAR); - - DataTable table = new DataTable(); - table.addColumn(new ColumnDescription("dateCol", ValueType.DATE, "dateCol")); - table.addColumn(new ColumnDescription("numberCol", ValueType.NUMBER, "numberCol")); - table.addColumn(new ColumnDescription("timeOfDayCol", ValueType.TIMEOFDAY, "timeOfDayCol")); - table.addColumn(new ColumnDescription("dateTimeCol", ValueType.DATETIME, "dateTimeCol")); - - TableRow row = new TableRow(); - row.addCell(new TableCell(new DateValue(2008, 5, 3))); - row.addCell(new TableCell(new NumberValue(23))); - row.addCell(new TableCell(new TimeOfDayValue(13, 12, 11))); - row.addCell(new TableCell(new DateTimeValue(2007, 3, 4, 2, 6, 23, 120))); - - // Check date value. - List columns = - Lists.newArrayList((AbstractColumn) new SimpleColumn("dateCol")); - ScalarFunctionColumn sfc = - new ScalarFunctionColumn(columns, scalarFunction); - DataTableColumnLookup lookup = new DataTableColumnLookup(table); - Value value = sfc.getValue(lookup, row); - Value expectedValueFromDate = new NumberValue(2008); - assertEquals(expectedValueFromDate, value); - - // Check datetime value. - List columns1 = - Lists.newArrayList((AbstractColumn) new SimpleColumn("dateTimeCol")); - sfc = new ScalarFunctionColumn(columns1, scalarFunction); - lookup = new DataTableColumnLookup(table); - value = sfc.getValue(lookup, row); - Value expectedValueFromDateTime = new NumberValue(2007); - assertEquals(value, expectedValueFromDateTime); - - // Check bad input (timeofday value). - List columns2 = - Lists.newArrayList((AbstractColumn) new SimpleColumn("timeOfDayCol")); - sfc = new ScalarFunctionColumn(columns2, scalarFunction); - try { - sfc.validateColumn(table); - } catch (DataSourceException e) { - // Expected behavior. - } - } - - public void testGetAllSimpleColumns() { - List simpleColumns = - scalarFunctionColumn.getAllSimpleColumns(); - List expectedSimpleColumns = Lists.newArrayList(); - expectedSimpleColumns.add(new SimpleColumn("col4")); - expectedSimpleColumns.add(new SimpleColumn("col5")); - expectedSimpleColumns.add(new SimpleColumn("col1")); - expectedSimpleColumns.add(new SimpleColumn("col2")); - expectedSimpleColumns.add(new SimpleColumn("col7")); - assertEquals(expectedSimpleColumns, simpleColumns); - } - - public void testGetAllAggregationColumns() { - List aggregationColumns = - scalarFunctionColumn.getAllAggregationColumns(); - List expectedAggregationColumns = Lists.newArrayList(); - expectedAggregationColumns.add(new AggregationColumn( - new SimpleColumn("col3"), AggregationType.getByCode("sum"))); - expectedAggregationColumns.add( - new AggregationColumn(new SimpleColumn("col6"), - AggregationType.getByCode("sum"))); - assertEquals(expectedAggregationColumns, aggregationColumns); - } - - public void testGetAllScalarFunctionColumns() { - List scalarFunctionColumns = - scalarFunctionColumn.getAllScalarFunctionColumns(); - List expectedScalarFunctionColumns = - Lists.newArrayList(); - - List columns1 = Lists.newArrayList(); - ScalarFunction scalarFunction1 = TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.MONTH); - - columns1.add(new SimpleColumn("col1")); - columns1.add(new SimpleColumn("col2")); - columns1.add(new AggregationColumn(new SimpleColumn("col3"), - AggregationType.getByCode("sum"))); - - ScalarFunctionColumn innerScalarFunctionColumn = - new ScalarFunctionColumn(columns1, scalarFunction1); - - expectedScalarFunctionColumns.add(scalarFunctionColumn); - expectedScalarFunctionColumns.add(innerScalarFunctionColumn); - assertEquals(expectedScalarFunctionColumns, scalarFunctionColumns); - } - - public void testGetValueType() { - ScalarFunction scalarFunction = TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.YEAR); - DataTable table = new DataTable(); - table.addColumn(new ColumnDescription("dateCol", ValueType.DATE, "dateCol")); - List columns = - Lists.newArrayList((AbstractColumn) new SimpleColumn("dateCol")); - ScalarFunctionColumn sfc = new ScalarFunctionColumn(columns, scalarFunction); - ValueType valueType = sfc.getValueType(table); - assertEquals(ValueType.NUMBER, valueType); - } - - public void testGetId() { - assertEquals("year_col4,col5,month_col1,col2,sum-col3,sum-col6,col7", - scalarFunctionColumn.getId()); - } -} diff --git a/src/test/java/com/google/visualization/datasource/query/engine/AggregationNodeTest.java b/src/test/java/com/google/visualization/datasource/query/engine/AggregationNodeTest.java deleted file mode 100644 index 4e43c3f..0000000 --- a/src/test/java/com/google/visualization/datasource/query/engine/AggregationNodeTest.java +++ /dev/null @@ -1,162 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query.engine; - -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; -import com.google.visualization.datasource.datatable.value.NumberValue; -import com.google.visualization.datasource.datatable.value.TextValue; -import com.google.visualization.datasource.datatable.value.Value; -import com.google.visualization.datasource.datatable.value.ValueType; -import com.google.visualization.datasource.query.AggregationType; -import com.google.visualization.datasource.query.mocks.MockDataSource; - -import junit.framework.TestCase; - -import java.util.Map; -import java.util.NoSuchElementException; -import java.util.Set; - -/** - * Tests to AggregationNode.java. - * - * @author Yoav G. - */ - -public class AggregationNodeTest extends TestCase { - - /** - * Mapping the columns to aggregate. - */ - /* package */ static Set columnsToAggregate; - - /** - * Creating the column aggregation map (suits table2 and table3 in - * mockDataSource). - */ - protected static final void createColumnAggregationMap() { - columnsToAggregate = Sets.newHashSet("Band", "Sales"); - } - - /** - * Creates a new aggregation node. - * - * @return A new aggregation node. - */ - protected static final AggregationNode newAggregationNode() { - return new AggregationNode(columnsToAggregate, MockDataSource.getData(1)); - } - - /** - * Adds a child to a given node. - * - * @param node The node to add a child to. - * @param value The value representing the node to add. - */ - protected static final void addChildToNode(AggregationNode node, Value value) - { - node.addChild(value, columnsToAggregate, MockDataSource.getData(1)); - } - - - /** - * Creates a column to value map according to a string array. - * - * @param values A string array. - * - * @return A column to value map. - */ - protected static final Map createValueMap(String[] values) { - Map result = Maps.newHashMap(); - result.put("Band", MockDataSource.toValue(values[0], ValueType.TEXT)); - result.put("Sales", MockDataSource.toValue(values[1], ValueType.NUMBER)); - return result; - - } - - @Override - public void setUp() throws Exception { - super.setUp(); - createColumnAggregationMap(); - } - - @Override - public void tearDown() throws Exception { - super.tearDown(); - } - - /** - * Tests the functionality of {@code AggregationNode.containsChild}. - */ - public void testContainsChild() { - AggregationNode node = newAggregationNode(); - node.addChild(new NumberValue(3), columnsToAggregate, MockDataSource.getData(1)); - assertEquals(true, node.containsChild(new NumberValue(3))); - assertEquals(false, node.containsChild(new NumberValue(4))); - } - - /** - * Tests the functionality of {@code AggregationNode.getChild}. - */ - public void testGetChild() { - AggregationNode node = newAggregationNode(); - addChildToNode(node, new NumberValue(3)); - assertNotNull(node.getChild(new NumberValue(3))); - try { - node.getChild(new NumberValue(4)); - fail(); - } catch (NoSuchElementException e) { - // Expected behavior. - } - } - - /** - * Tests the functionality of {@code AggregationNode.addChild}. - */ - public void testAddChild() { - AggregationNode node = newAggregationNode(); - addChildToNode(node, new NumberValue(3)); - try { - addChildToNode(node, new NumberValue(3)); - fail(); - } catch (IllegalArgumentException e) { - // Expected behavior. - } - } - - /** - * Tests empty aggregation. - */ - public void testEmptyAggregation() { - AggregationNode node = newAggregationNode(); - Map valuesByColumn = Maps.newHashMap(); - node.aggregate(valuesByColumn); - assertEquals("0.0", node.getAggregationValue( - "Band", AggregationType.COUNT).toString()); - } - - /** - * Tests whether the node aggregates properly. - */ - public void testAggregation() { - AggregationNode node = newAggregationNode(); - node.aggregate(createValueMap(new String[]{"A", "100"})); - node.aggregate(createValueMap(new String[]{"B", "50"})); - assertEquals(new TextValue("B"), node.getAggregationValue( - "Band", AggregationType.MAX)); - assertEquals("75.0", node.getAggregationValue( - "Sales", AggregationType.AVG).toString()); - } -} diff --git a/src/test/java/com/google/visualization/datasource/query/engine/AggregationPathTest.java b/src/test/java/com/google/visualization/datasource/query/engine/AggregationPathTest.java deleted file mode 100644 index 8b698e7..0000000 --- a/src/test/java/com/google/visualization/datasource/query/engine/AggregationPathTest.java +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query.engine; - -import com.google.visualization.datasource.datatable.value.NumberValue; -import com.google.visualization.datasource.datatable.value.Value; - -import junit.framework.TestCase; - -import java.util.List; - -/** - * Tests for the AggregationPath class - * - * @author Yoav G. - */ - -public class AggregationPathTest extends TestCase { - - public void simpleTest() { - AggregationPath path = new AggregationPath(); - path.add(new NumberValue(3)); - path.add(new NumberValue(4)); - List values = path.getValues(); - assertEquals(3.0, ((NumberValue) values.get(0)).getValue()); - assertEquals(4.0, ((NumberValue) values.get(1)).getValue()); - } - - public void testReverse() { - AggregationPath path = new AggregationPath(); - path.add(new NumberValue(3)); - path.add(new NumberValue(4)); - path.reverse(); - List values = path.getValues(); - assertEquals(4.0, ((NumberValue) values.get(0)).getValue()); - assertEquals(3.0, ((NumberValue) values.get(1)).getValue()); - } - - public void testEmptyPath() { - AggregationPath path = new AggregationPath(); - path.reverse(); - List values = path.getValues(); - assertEquals(0, values.size()); - } - -} \ No newline at end of file diff --git a/src/test/java/com/google/visualization/datasource/query/engine/AggregationTreeTest.java b/src/test/java/com/google/visualization/datasource/query/engine/AggregationTreeTest.java deleted file mode 100644 index e51361f..0000000 --- a/src/test/java/com/google/visualization/datasource/query/engine/AggregationTreeTest.java +++ /dev/null @@ -1,152 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query.engine; - -import com.google.visualization.datasource.datatable.value.NumberValue; -import com.google.visualization.datasource.datatable.value.TextValue; -import com.google.visualization.datasource.datatable.value.Value; -import com.google.visualization.datasource.datatable.value.ValueType; -import com.google.visualization.datasource.query.AggregationType; -import com.google.visualization.datasource.query.mocks.MockDataSource; - -import junit.framework.Assert; -import junit.framework.TestCase; - -import java.util.List; -import java.util.NoSuchElementException; -import java.util.Set; - -/** - * Tests for AggregationTree.java. - * - * @author Yoav G. - */ - -public class AggregationTreeTest extends TestCase { - - /** - * Column types suits for table2 and table3 in mockDataSource. - */ - private static final ValueType[] types = new ValueType[] { - ValueType.TEXT, ValueType.NUMBER, ValueType.NUMBER - }; - - @Override - public void setUp() throws Exception { - super.setUp(); - AggregationNodeTest.createColumnAggregationMap(); - } - - @Override - public void tearDown() throws Exception { - super.tearDown(); - } - - /** - * @return an aggregation tree. - */ - protected static final AggregationTree newAggregationTree() { - return new AggregationTree(AggregationNodeTest.columnsToAggregate, MockDataSource.getData(1)); - } - - /** - * Creates a tree path from string input. - * @param values The values. - * @return Tree path. - */ - protected static final AggregationPath createPath(String [] values) { - AggregationPath result = new AggregationPath(); - for (int i = 0; i < values.length; i++) { - result.add(MockDataSource.toValue(values[i], types[i])); - } - return result; - } - - /** - * Tests that non existing nodes cause an exception (and that existing nodes - * function properly). - */ - public void testGetNode() { - AggregationTree tree = newAggregationTree(); - tree.aggregate(createPath(new String[] {"Bla", "3"}), - AggregationNodeTest.createValueMap(new String[]{"A", "100"})); - tree.getNode(createPath(new String[] {"Bla", "3"})); - try { - tree.getNode(createPath(new String[] {"B", "3"})); - fail(); - } catch (NoSuchElementException e) { - // Expected behavior. - - } - - try { - tree.getNode(createPath(new String[] {"Bla", "3", "5"})); - fail(); - } catch (NoSuchElementException e) { - // Expected behavior. - } - } - - /** - * Tests aggregations of empty and non empty paths in the tree. - */ - public void testAggregation() { - AggregationTree tree = newAggregationTree(); - tree.aggregate(createPath(new String[] {"Bla", "3"}), - AggregationNodeTest.createValueMap(new String[]{"A", "100"})); - tree.aggregate(createPath(new String[] {"Bla", "3", "5"}), - AggregationNodeTest.createValueMap(new String[]{"B", "50"})); - tree.aggregate(createPath(new String[]{"4"}), - AggregationNodeTest.createValueMap(new String[]{"C", "10"})); - - Assert.assertEquals(new TextValue("A"), - tree.getNode(createPath(new String[] {})) - .getAggregationValue("Band", AggregationType.MIN)); - - assertEquals("75.0", tree.getNode(createPath( - new String[] {"Bla", "3"})).getAggregationValue( - "Sales", AggregationType.AVG).toString()); - - assertEquals("160.0", tree.getNode(createPath( - new String[] {})).getAggregationValue( - "Sales", AggregationType.SUM).toString()); - } - - /** - * Test the getPathsToLeaves functionality. - */ - public void testPathsToLeaves() { - AggregationTree tree = newAggregationTree(); - tree.aggregate(createPath(new String[] {"Bla", "3"}), - AggregationNodeTest.createValueMap(new String[]{"A", "100"})); - tree.aggregate(createPath(new String[] {"Bla", "3", "5"}), - AggregationNodeTest.createValueMap(new String[]{"B", "50"})); - tree.aggregate(createPath(new String[]{"4"}), - AggregationNodeTest.createValueMap(new String[]{"C", "10"})); - Set paths = tree.getPathsToLeaves(); - assertEquals(2, paths.size()); - for (AggregationPath path : paths) { - List curPath = path.getValues(); - if (curPath.size() == 3) { - assertEquals("Bla", ((TextValue) curPath.get(0)).toString()); - assertEquals(3.0, ((NumberValue) curPath.get(1)).getValue()); - assertEquals(5.0, ((NumberValue) curPath.get(2)).getValue()); - } else { - assertEquals(1, curPath.size()); - assertEquals("4", ((TextValue) curPath.get(0)).toString()); - } - } - } -} diff --git a/src/test/java/com/google/visualization/datasource/query/engine/ColumnTitleTest.java b/src/test/java/com/google/visualization/datasource/query/engine/ColumnTitleTest.java deleted file mode 100644 index e890f3a..0000000 --- a/src/test/java/com/google/visualization/datasource/query/engine/ColumnTitleTest.java +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query.engine; - -import com.google.common.collect.Lists; -import com.google.visualization.datasource.datatable.ColumnDescription; -import com.google.visualization.datasource.datatable.value.BooleanValue; -import com.google.visualization.datasource.datatable.value.NumberValue; -import com.google.visualization.datasource.datatable.value.Value; -import com.google.visualization.datasource.datatable.value.ValueType; -import com.google.visualization.datasource.query.AggregationColumn; -import com.google.visualization.datasource.query.AggregationType; -import com.google.visualization.datasource.query.SimpleColumn; - -import junit.framework.TestCase; - -/** - * Tests the functionality of ColumnTitle class. - * - * @author Yoav G. - */ -public class ColumnTitleTest extends TestCase { - - @Override - public void setUp() throws Exception { - super.setUp(); - } - - /** - * Tests the createAggregationColumnDescription. - */ - public void testCreateAggregationColumnDescription() { - ColumnDescription columnDescription = new ColumnDescription("id", - ValueType.TEXT, "label"); - - - ColumnTitle columnTitleCount = new ColumnTitle(Lists.newArrayList(), - new AggregationColumn(new SimpleColumn("id"), - AggregationType.COUNT), false); - - ColumnTitle columnTitleMin = new ColumnTitle(Lists.newArrayList(), - new AggregationColumn(new SimpleColumn("id"), - AggregationType.MIN), true); - - ColumnTitle columnTitleCountWithPivot = - new ColumnTitle(Lists.newArrayList(new NumberValue(3.14), - BooleanValue.TRUE), new AggregationColumn(new SimpleColumn("id"), - AggregationType.COUNT), false); - - ColumnTitle columnTitleMinWithPivot = - new ColumnTitle(Lists.newArrayList(new NumberValue(3.14), - BooleanValue.TRUE), new AggregationColumn(new SimpleColumn("id"), - AggregationType.MIN), true); - - - ColumnDescription resultColumnDescriptionCount = - columnTitleCount.createAggregationColumnDescription(columnDescription); - - ColumnDescription resultColumnDescriptionMin = - columnTitleMin.createAggregationColumnDescription(columnDescription); - - ColumnDescription resultColumnDescriptionCountWithPivot = - columnTitleCountWithPivot.createAggregationColumnDescription(columnDescription); - - ColumnDescription resultColumnDescriptionMinWithPivot = - columnTitleMinWithPivot.createAggregationColumnDescription(columnDescription); - - // Check the creation of result column description with aggregation - // type count. - assertEquals("count-id", resultColumnDescriptionCount.getId()); - assertEquals("count label", resultColumnDescriptionCount.getLabel()); - assertEquals(ValueType.NUMBER, resultColumnDescriptionCount.getType()); - - // Check the creation of result column description with aggregation - // type min. - assertEquals("min-id", resultColumnDescriptionMin.getId()); - assertEquals("min label", resultColumnDescriptionMin.getLabel()); - assertEquals(ValueType.TEXT, resultColumnDescriptionMin.getType()); - - // Check the creation of result column description with aggregation - // type count with pivot and single aggregation. - assertEquals("3.14,true count-id", resultColumnDescriptionCountWithPivot.getId()); - assertEquals("3.14,true", resultColumnDescriptionCountWithPivot.getLabel()); - assertEquals(ValueType.NUMBER, resultColumnDescriptionCountWithPivot.getType()); - - // Check the creation of result column description with aggregation - // type min with pivot, multi-aggregation. - assertEquals("3.14,true min-id", - resultColumnDescriptionMinWithPivot.getId()); - assertEquals("3.14,true min label", - resultColumnDescriptionMinWithPivot.getLabel()); - assertEquals(ValueType.TEXT, resultColumnDescriptionMinWithPivot.getType()); - } -} diff --git a/src/test/java/com/google/visualization/datasource/query/engine/ColumnValueAggregatorTest.java b/src/test/java/com/google/visualization/datasource/query/engine/ColumnValueAggregatorTest.java deleted file mode 100644 index 71091ef..0000000 --- a/src/test/java/com/google/visualization/datasource/query/engine/ColumnValueAggregatorTest.java +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query.engine; - -import com.google.visualization.datasource.datatable.value.DateValue; -import com.google.visualization.datasource.datatable.value.NumberValue; -import com.google.visualization.datasource.datatable.value.TextValue; -import com.google.visualization.datasource.datatable.value.ValueType; -import com.google.visualization.datasource.query.AggregationType; - -import junit.framework.TestCase; - -/** - * Tests for ColumnValueAggregator.java. - * - * @author Yoav G. - */ - -public class ColumnValueAggregatorTest extends TestCase { - - /** - * Test all functionalities by aggregating two numbers. - */ - public void testNumberAggregation() { - ValueAggregator aggregator = new ValueAggregator(ValueType.NUMBER); - aggregator.aggregate(new NumberValue(1)); - aggregator.aggregate(new NumberValue(3)); - - assertEquals(new NumberValue(4.0), aggregator.getValue(AggregationType.SUM)); - assertEquals(new NumberValue(2.0), aggregator.getValue(AggregationType.AVG)); - assertEquals(new NumberValue(2), aggregator.getValue(AggregationType.COUNT)); - assertEquals(new NumberValue(1.0), aggregator.getValue(AggregationType.MIN)); - assertEquals(new NumberValue(3.0), aggregator.getValue(AggregationType.MAX)); - } - - /** - * Test string aggregation. - */ - public void testStringAggregation() { - ValueAggregator aggregator = new ValueAggregator(ValueType.TEXT); - aggregator.aggregate(new TextValue("a")); - aggregator.aggregate(new TextValue("b")); - - try { - aggregator.getValue(AggregationType.SUM); - fail(); - } catch (UnsupportedOperationException e) { - // Expected behavior. - } - try { - aggregator.getValue(AggregationType.AVG); - fail(); - } catch (UnsupportedOperationException e) { - // Expected behavior. - } - - assertEquals(new NumberValue(2), aggregator.getValue(AggregationType.COUNT)); - assertEquals(new TextValue("a"), aggregator.getValue(AggregationType.MIN)); - assertEquals(new TextValue("b"), aggregator.getValue(AggregationType.MAX)); - - } - - public void testGetValueFromEmptyAggregation() { - ValueAggregator aggregator = new ValueAggregator(ValueType.DATE); - DateValue dateNull = DateValue.getNullValue(); - NumberValue numberNull = NumberValue.getNullValue(); - - assertEquals(new NumberValue(0), aggregator.getValue(AggregationType.COUNT)); - - assertEquals(dateNull, aggregator.getValue(AggregationType.MIN)); - assertEquals(dateNull, aggregator.getValue(AggregationType.MAX)); - - assertEquals(numberNull, aggregator.getValue(AggregationType.AVG)); - assertEquals(numberNull, aggregator.getValue(AggregationType.SUM)); - } -} \ No newline at end of file diff --git a/src/test/java/com/google/visualization/datasource/query/engine/QueryEngineTest.java b/src/test/java/com/google/visualization/datasource/query/engine/QueryEngineTest.java deleted file mode 100644 index 010601a..0000000 --- a/src/test/java/com/google/visualization/datasource/query/engine/QueryEngineTest.java +++ /dev/null @@ -1,1670 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query.engine; - -import com.google.common.collect.Lists; -import com.google.visualization.datasource.base.InvalidQueryException; -import com.google.visualization.datasource.datatable.ColumnDescription; -import com.google.visualization.datasource.datatable.DataTable; -import com.google.visualization.datasource.datatable.TableCell; -import com.google.visualization.datasource.datatable.TableRow; -import com.google.visualization.datasource.datatable.value.BooleanValue; -import com.google.visualization.datasource.datatable.value.NumberValue; -import com.google.visualization.datasource.datatable.value.TextValue; -import com.google.visualization.datasource.datatable.value.ValueType; -import com.google.visualization.datasource.query.AbstractColumn; -import com.google.visualization.datasource.query.AggregationColumn; -import com.google.visualization.datasource.query.AggregationType; -import com.google.visualization.datasource.query.ColumnSort; -import com.google.visualization.datasource.query.ColumnValueFilter; -import com.google.visualization.datasource.query.ComparisonFilter; -import com.google.visualization.datasource.query.Query; -import com.google.visualization.datasource.query.QueryFilter; -import com.google.visualization.datasource.query.QueryFormat; -import com.google.visualization.datasource.query.QueryGroup; -import com.google.visualization.datasource.query.QueryLabels; -import com.google.visualization.datasource.query.QueryPivot; -import com.google.visualization.datasource.query.QuerySelection; -import com.google.visualization.datasource.query.QuerySort; -import com.google.visualization.datasource.query.ScalarFunctionColumn; -import com.google.visualization.datasource.query.SimpleColumn; -import com.google.visualization.datasource.query.SortOrder; -import com.google.visualization.datasource.query.mocks.MockDataSource; -import com.google.visualization.datasource.query.parser.QueryBuilder; -import com.google.visualization.datasource.query.scalarfunction.Constant; -import com.google.visualization.datasource.query.scalarfunction.DateDiff; -import com.google.visualization.datasource.query.scalarfunction.Difference; -import com.google.visualization.datasource.query.scalarfunction.Modulo; -import com.google.visualization.datasource.query.scalarfunction.Product; -import com.google.visualization.datasource.query.scalarfunction.Quotient; -import com.google.visualization.datasource.query.scalarfunction.Sum; -import com.google.visualization.datasource.query.scalarfunction.TimeComponentExtractor; - -import com.ibm.icu.util.ULocale; - -import junit.framework.TestCase; - -import java.util.Arrays; -import java.util.List; - -/** - * Unit tests for DataTableDataSourceTest. - * - * @author Yoah B.D. - */ -public class QueryEngineTest extends TestCase { - - private static void assertStringArraysEqual(String[] expected, - String[] found) { - assertTrue("Expected: " + Arrays.toString(expected) + " but found: " - + Arrays.toString(found), Arrays.equals(expected, found)); - } - - private DataTable input; - - @Override - public void setUp() throws Exception { - super.setUp(); - - input = new DataTable(); - input.addColumn(new ColumnDescription("name", ValueType.TEXT, "label0")); - input.addColumn(new ColumnDescription("weight", ValueType.NUMBER, "label1")); - input.addColumn(new ColumnDescription("isPig", ValueType.BOOLEAN, "label2")); - - TableRow row; - - row = new TableRow(); - row.addCell(new TableCell(new TextValue("aaa"))); - row.addCell(new TableCell(new NumberValue(222))); - row.addCell(new TableCell(BooleanValue.TRUE, "T")); - input.addRow(row); - - row = new TableRow(); - row.addCell(new TableCell(new TextValue("ccc"))); - row.addCell(new TableCell(new NumberValue(111))); - row.addCell(new TableCell(BooleanValue.TRUE, "T")); - input.addRow(row); - - row = new TableRow(); - row.addCell(new TableCell(new TextValue("bbb"))); - row.addCell(new TableCell(new NumberValue(333))); - row.addCell(new TableCell(BooleanValue.FALSE, "F")); - input.addRow(row); - } - - @Override - public void tearDown() throws Exception { - super.tearDown(); - } - - /** - * Test an empty query, no modification from input to output, - */ - public void testEmptyQuery() throws Exception { - Query q = new Query(); - DataTable res = QueryEngine.executeQuery(q, input, ULocale.US); - List cols = res.getColumnDescriptions(); - assertEquals(3, cols.size()); - assertEquals("name", cols.get(0).getId()); - assertEquals("weight", cols.get(1).getId()); - assertEquals("isPig", cols.get(2).getId()); - assertEquals(ValueType.TEXT, cols.get(0).getType()); - assertEquals(ValueType.NUMBER, cols.get(1).getType()); - assertEquals(ValueType.BOOLEAN, cols.get(2).getType()); - assertEquals("label0", cols.get(0).getLabel()); - assertEquals("label1", cols.get(1).getLabel()); - assertEquals("label2", cols.get(2).getLabel()); - - assertEquals(3, res.getRows().size()); - } - - /** - * Test sorting by a number column. - */ - public void testSortByNumberAscending() throws Exception { - Query q = new Query(); - QuerySort sort = new QuerySort(); - sort.addSort(new ColumnSort(new SimpleColumn("weight"), - SortOrder.ASCENDING)); - q.setSort(sort); - DataTable res = QueryEngine.executeQuery(q, input, ULocale.US); - - assertEquals(3, res.getRows().size()); - assertEquals("111.0", res.getRows().get(0).getCells().get(1).toString()); - assertEquals("222.0", res.getRows().get(1).getCells().get(1).toString()); - assertEquals("333.0", res.getRows().get(2).getCells().get(1).toString()); - } - - /** - * Test sorting by a number column. - */ - public void testSortByNumberDescending() throws Exception { - Query q = new Query(); - QuerySort sort = new QuerySort(); - sort.addSort(new ColumnSort(new SimpleColumn("weight"), - SortOrder.DESCENDING)); - q.setSort(sort); - DataTable res = QueryEngine.executeQuery(q, input, ULocale.US); - - assertEquals(3, res.getRows().size()); - assertEquals("333.0", res.getRows().get(0).getCells().get(1).toString()); - assertEquals("222.0", res.getRows().get(1).getCells().get(1).toString()); - assertEquals("111.0", res.getRows().get(2).getCells().get(1).toString()); - } - - /** - * Test sorting by a text column. - */ - public void testSortByTextAscending() throws Exception { - Query q = new Query(); - QuerySort sort = new QuerySort(); - sort.addSort(new ColumnSort(new SimpleColumn("name"), SortOrder.ASCENDING)); - q.setSort(sort); - DataTable res = QueryEngine.executeQuery(q, input, ULocale.US); - - assertEquals(3, res.getRows().size()); - assertEquals("aaa", res.getRows().get(0).getCells().get(0).toString()); - assertEquals("bbb", res.getRows().get(1).getCells().get(0).toString()); - assertEquals("ccc", res.getRows().get(2).getCells().get(0).toString()); - } - - /** - * Test sorting by a text column. - */ - public void testSortByTextDescnding() throws Exception { - Query q = new Query(); - QuerySort sort = new QuerySort(); - sort.addSort(new ColumnSort(new SimpleColumn("name"), - SortOrder.DESCENDING)); - q.setSort(sort); - DataTable res = QueryEngine.executeQuery(q, input, ULocale.US); - - assertEquals(3, res.getRows().size()); - assertEquals("ccc", res.getRows().get(0).getCells().get(0).toString()); - assertEquals("bbb", res.getRows().get(1).getCells().get(0).toString()); - assertEquals("aaa", res.getRows().get(2).getCells().get(0).toString()); - } - - /** - * Test selection of no cols (should be as select all). - */ - public void testSelectWithNoCols() throws Exception { - Query q = new Query(); - QuerySelection sel = new QuerySelection(); - q.setSelection(sel); - DataTable res = QueryEngine.executeQuery(q, input, ULocale.US); - List cols = res.getColumnDescriptions(); - - assertEquals(3, cols.size()); - assertEquals("name", cols.get(0).getId()); - assertEquals("weight", cols.get(1).getId()); - assertEquals("isPig", cols.get(2).getId()); - - assertEquals(3, res.getRows().size()); - assertEquals(3, res.getRows().get(0).getCells().size()); - } - - /** - * Test selection of the first col only. - */ - public void testSelectionOfFirstCol() throws Exception { - Query q = new Query(); - QuerySelection sel = new QuerySelection(); - sel.addColumn(new SimpleColumn("name")); - q.setSelection(sel); - DataTable res = QueryEngine.executeQuery(q, input, ULocale.US); - List cols = res.getColumnDescriptions(); - - assertEquals(1, cols.size()); - assertEquals("name", cols.get(0).getId()); - - assertEquals(3, res.getRows().size()); - assertEquals(1, res.getRows().get(0).getCells().size()); - } - - /** - * Test selection of all but the first col. - */ - public void testSelectionOfAllButFirstCol() throws Exception { - Query q = new Query(); - QuerySelection sel = new QuerySelection(); - sel.addColumn(new SimpleColumn("weight")); - sel.addColumn(new SimpleColumn("isPig")); - q.setSelection(sel); - DataTable res = QueryEngine.executeQuery(q, input, ULocale.US); - List cols = res.getColumnDescriptions(); - - assertEquals(2, cols.size()); - assertEquals("weight", cols.get(0).getId()); - assertEquals("isPig", cols.get(1).getId()); - - assertEquals(3, res.getRows().size()); - assertEquals(2, res.getRows().get(0).getCells().size()); - - // Verify that formatted values survive the selection. - assertEquals("T", res.getCell(0, 1).getFormattedValue()); - } - - /** - * Test sorting by a text column, while this is the only selected column. - */ - public void testSelectionAndSortByTextDescending() throws Exception { - Query q = new Query(); - QuerySort sort = new QuerySort(); - sort.addSort(new ColumnSort(new SimpleColumn("name"), - SortOrder.DESCENDING)); - q.setSort(sort); - - QuerySelection selection = new QuerySelection(); - selection.addColumn(new SimpleColumn("name")); - q.setSelection(selection); - DataTable res = QueryEngine.executeQuery(q, input, ULocale.US); - List cols = res.getColumnDescriptions(); - - assertEquals(1, cols.size()); - assertEquals("name", cols.get(0).getId()); - - assertEquals(3, res.getRows().size()); - assertEquals("ccc", res.getRows().get(0).getCells().get(0).toString()); - assertEquals("bbb", res.getRows().get(1).getCells().get(0).toString()); - assertEquals("aaa", res.getRows().get(2).getCells().get(0).toString()); - } - - public void testGrouping() throws Exception { - - DataTable res = MockDataSource.getData(1); - - // select max(songs), min(songs), year, avg(songs), sum(sales) - // group by year, band - Query q = new Query(); - QueryGroup group = new QueryGroup(); - group.addColumn(new SimpleColumn("Year")); - group.addColumn(new SimpleColumn("Band")); - q.setGroup(group); - QuerySelection selection = new QuerySelection(); - selection.addColumn(new AggregationColumn(new SimpleColumn("Songs"), - AggregationType.MAX)); - selection.addColumn(new AggregationColumn(new SimpleColumn("Songs"), - AggregationType.MIN)); - selection.addColumn(new SimpleColumn("Year")); - selection.addColumn(new AggregationColumn(new SimpleColumn("Songs"), - AggregationType.AVG)); - selection.addColumn(new AggregationColumn(new SimpleColumn("Sales"), - AggregationType.SUM)); - q.setSelection(selection); - q.validate(); - - DataTable result = QueryEngine.executeQuery(q, res, ULocale.US); - // Test column description - List cols = result.getColumnDescriptions(); - - assertEquals(5, cols.size()); - assertEquals("max Number of new songs", cols.get(0).getLabel()); - assertEquals("min Number of new songs", cols.get(1).getLabel()); - assertEquals("Just year", cols.get(2).getLabel()); - assertEquals("avg Number of new songs", cols.get(3).getLabel()); - assertEquals("sum Number of new sales", cols.get(4).getLabel()); - - assertEquals("max-Songs", cols.get(0).getId()); - assertEquals("min-Songs", cols.get(1).getId()); - assertEquals("Year", cols.get(2).getId()); - assertEquals("avg-Songs", cols.get(3).getId()); - assertEquals("sum-Sales", cols.get(4).getId()); - - // Test data - String[][] resultStrings = MockDataSource.queryResultToStringMatrix(result); - assertStringArraysEqual(new String[]{"4.0", "2.0", "1994", - "2.6666666666666665", "24.0"}, resultStrings[0]); - assertStringArraysEqual(new String[]{"4.0", "2.0", "1994", - "2.2222222222222223", "36.0"}, resultStrings[1]); - assertStringArraysEqual(new String[]{"2.0", "2.0", "1996", - "2.0", "70.0"}, resultStrings[2]); - assertStringArraysEqual(new String[]{"4.0", "2.0", "1996", - "2.5", "32.0"}, resultStrings[3]); - assertStringArraysEqual(new String[]{"2.0", "2.0", "2003", - "2.0", "67.0"}, resultStrings[4]); - } - - public void testGroupingWithPivoting() throws Exception { - DataTable res = MockDataSource.getData(1); - // select max(sales), year, min(sales), avg(fans) - // group by year - // pivot by band, songs - Query q = new Query(); - QueryGroup group = new QueryGroup(); - group.addColumn(new SimpleColumn("Year")); - q.setGroup(group); - QueryPivot pivot = new QueryPivot(); - pivot.addColumn(new SimpleColumn("Band")); - pivot.addColumn(new SimpleColumn("Songs")); - q.setPivot(pivot); - QuerySelection selection = new QuerySelection(); - selection.addColumn(new AggregationColumn(new SimpleColumn("Sales"), - AggregationType.MAX)); - selection.addColumn(new SimpleColumn("Year")); - selection.addColumn(new AggregationColumn(new SimpleColumn("Sales"), - AggregationType.MIN)); - selection.addColumn(new AggregationColumn(new SimpleColumn("Fans"), - AggregationType.AVG)); - q.setSelection(selection); - q.validate(); - - DataTable result = QueryEngine.executeQuery(q, res, ULocale.US); - - // Test column description - List cols = result.getColumnDescriptions(); - - assertEquals(16, cols.size()); - assertEquals("Collection,2.0 max-Sales", cols.get(0).getId()); - assertEquals("Contraband,2.0 max-Sales", cols.get(1).getId()); - assertEquals("Contraband,4.0 max-Sales", cols.get(2).getId()); - assertEquals("Youthanasia,2.0 max-Sales", cols.get(3).getId()); - assertEquals("Youthanasia,4.0 max-Sales", cols.get(4).getId()); - assertEquals("Year", cols.get(5).getId()); - assertEquals("Collection,2.0 min-Sales", cols.get(6).getId()); - assertEquals("Contraband,2.0 min-Sales", cols.get(7).getId()); - assertEquals("Contraband,4.0 min-Sales", cols.get(8).getId()); - assertEquals("Youthanasia,2.0 min-Sales", cols.get(9).getId()); - assertEquals("Youthanasia,4.0 min-Sales", cols.get(10).getId()); - assertEquals("Collection,2.0 avg-Fans", cols.get(11).getId()); - assertEquals("Contraband,2.0 avg-Fans", cols.get(12).getId()); - assertEquals("Contraband,4.0 avg-Fans", cols.get(13).getId()); - assertEquals("Youthanasia,2.0 avg-Fans", cols.get(14).getId()); - assertEquals("Youthanasia,4.0 avg-Fans", cols.get(15).getId()); - - String[][] resultStrings = MockDataSource.queryResultToStringMatrix(result); - assertEquals(3, resultStrings.length); - - assertStringArraysEqual(new String[]{"null", "4.0", "4.0", "4.0", "4.0", - "1994", "null", "4.0", "4.0", "4.0", "4.0", "null", "2575.0", "1900.0", - "2686.75", "20.0"}, resultStrings[0]); - assertStringArraysEqual(new String[]{"null", "46.0", "null", "4.0", "4.0", - "1996", "null", "4.0", "null", "4.0", "4.0", "null", - "10626.142857142857", "null", "1122.8333333333333", "3250.0"}, - resultStrings[1]); - assertStringArraysEqual(new String[]{"8.0", "null", "null", "null", "null", - "2003", "4.0", "null", "null", "null", "null", "2249.733333333333", - "null", "null", "null", "null"}, resultStrings[2]); - } - - public void testGroupingByScalarFunction() throws Exception { - DataTable res = MockDataSource.getData(3); - - // select sum(age), count(dept), hour(lunchTime) group by hour(lunchtime) - Query q = new Query(); - - // Add selection. - QuerySelection selection = new QuerySelection(); - selection.addColumn(new AggregationColumn(new SimpleColumn("age"), - AggregationType.SUM)); - selection.addColumn(new AggregationColumn(new SimpleColumn("dept"), - AggregationType.COUNT)); - selection.addColumn(new ScalarFunctionColumn( - Lists.newArrayList((AbstractColumn) new SimpleColumn("lunchTime")), - TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.HOUR))); - q.setSelection(selection); - - // Add group. - QueryGroup group = new QueryGroup(); - group.addColumn(new ScalarFunctionColumn( - Lists.newArrayList((AbstractColumn) new SimpleColumn("lunchTime")), - TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.HOUR))); - q.setGroup(group); - - q.validate(); - - DataTable result = QueryEngine.executeQuery(q, res.clone(), ULocale.US); - - // Test column description - List cols = - result.getColumnDescriptions(); - - assertEquals(3, cols.size()); - assertEquals("sum-age", cols.get(0).getId()); - assertEquals("count-dept", cols.get(1).getId()); - assertEquals("hour_lunchTime", cols.get(2).getId()); - - String[][] resultStrings = MockDataSource.queryResultToStringMatrix(result); - assertEquals(2, resultStrings.length); - - assertStringArraysEqual(new String[]{"119.0", "4.0", "12.0"}, - resultStrings[0]); - assertStringArraysEqual(new String[]{"54.0", "2.0", "13.0"}, - resultStrings[1]); - - // Select sum(age), count(name), datediff(hireDate, seniorityStartTime), - // dept group by datediff(hireDate, seniorityStartTime), dept. - q = new Query(); - - // Add selection. - selection = new QuerySelection(); - selection.addColumn(new AggregationColumn(new SimpleColumn("age"), - AggregationType.SUM)); - selection.addColumn(new AggregationColumn(new SimpleColumn("name"), - AggregationType.COUNT)); - selection.addColumn(new ScalarFunctionColumn( - Lists.newArrayList( - new SimpleColumn("seniorityStartTime"), - new SimpleColumn("hireDate")), DateDiff.getInstance())); - selection.addColumn(new SimpleColumn("dept")); - q.setSelection(selection); - - // Add group. - group = new QueryGroup(); - group.addColumn(new ScalarFunctionColumn( - Lists.newArrayList( - new SimpleColumn("seniorityStartTime"), - new SimpleColumn("hireDate")), DateDiff.getInstance())); - group.addColumn(new SimpleColumn("dept")); - q.setGroup(group); - - q.validate(); - - result = QueryEngine.executeQuery(q, res.clone(), ULocale.US); - - // Test column description - cols = result.getColumnDescriptions(); - - assertEquals(4, cols.size()); - assertEquals("sum-age", cols.get(0).getId()); - assertEquals("count-name", cols.get(1).getId()); - assertEquals("dateDiff_seniorityStartTime,hireDate", cols.get(2).getId()); - assertEquals("dept", cols.get(3).getId()); - - resultStrings = MockDataSource.queryResultToStringMatrix(result); - assertEquals(5, resultStrings.length); - - assertStringArraysEqual(new String[]{"57.0", "2.0", "null", "Eng"}, - resultStrings[0]); - assertStringArraysEqual(new String[]{"25.0", "1.0", "null", "Sales"}, - resultStrings[1]); - assertStringArraysEqual(new String[]{"32.0", "1.0", "891.0", "Sales"}, - resultStrings[2]); - assertStringArraysEqual(new String[]{"24.0", "1.0", "1084.0", "Marketing"}, - resultStrings[3]); - assertStringArraysEqual(new String[]{"35.0", "1.0", "1180.0", "Eng"}, - resultStrings[4]); - } - - public void testPivotingByScalarFunction() throws Exception { - DataTable res = MockDataSource.getData(3); - - // select sum(age), count(dept) pivot hour(lunchtime) - Query q = new Query(); - - // Add selection. - QuerySelection selection = new QuerySelection(); - selection.addColumn(new AggregationColumn(new SimpleColumn("age"), - AggregationType.SUM)); - selection.addColumn(new AggregationColumn(new SimpleColumn("dept"), - AggregationType.COUNT)); - q.setSelection(selection); - - // Add pivot. - QueryPivot pivot = new QueryPivot(); - pivot.addColumn(new ScalarFunctionColumn( - Lists.newArrayList((AbstractColumn) new SimpleColumn("lunchTime")), - TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.HOUR))); - q.setPivot(pivot); - - q.validate(); - DataTable result = QueryEngine.executeQuery(q, res.clone(), ULocale.US); - // Test column description - List cols = result.getColumnDescriptions(); - - assertEquals(4, cols.size()); - assertEquals("12.0 sum-age", cols.get(0).getId()); - assertEquals("13.0 sum-age", cols.get(1).getId()); - assertEquals("12.0 count-dept", cols.get(2).getId()); - assertEquals("13.0 count-dept", cols.get(3).getId()); - - String[][] resultStrings = MockDataSource.queryResultToStringMatrix(result); - assertEquals(1, resultStrings.length); - - assertStringArraysEqual(new String[]{"119.0", "54.0", "4.0", "2.0"}, - resultStrings[0]); - - // select count(dept) pivot hour(lunchtime), datediff(hireDate, - // seniorityStartTime) - Query q1 = new Query(); - - // Add selection. - QuerySelection selection1 = new QuerySelection(); - selection1.addColumn(new AggregationColumn(new SimpleColumn("dept"), - AggregationType.COUNT)); - q1.setSelection(selection1); - - // Add pivot. - QueryPivot pivot1 = new QueryPivot(); - pivot1.addColumn(new ScalarFunctionColumn( - Lists.newArrayList((AbstractColumn) new SimpleColumn("lunchTime")), - TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.HOUR))); - pivot1.addColumn(new ScalarFunctionColumn( - Lists.newArrayList( - new SimpleColumn("seniorityStartTime"), - new SimpleColumn("hireDate")), DateDiff.getInstance())); - q1.setPivot(pivot1); - - q1.validate(); - - DataTable result1 = QueryEngine.executeQuery(q1, res.clone(), ULocale.US); - - // Test column description - List cols1 = result1.getColumnDescriptions(); - - assertEquals(5, cols1.size()); - assertEquals("12.0,null count-dept", cols1.get(0).getId()); - assertEquals("12.0,891.0 count-dept", cols1.get(1).getId()); - assertEquals("12.0,1180.0 count-dept", cols1.get(2).getId()); - assertEquals("13.0,null count-dept", cols1.get(3).getId()); - assertEquals("13.0,1084.0 count-dept", cols1.get(4).getId()); - - resultStrings = MockDataSource.queryResultToStringMatrix(result1); - assertEquals(1, resultStrings.length); - - assertStringArraysEqual(new String[]{"2.0", "1.0", "1.0", "1.0", "1.0"}, - resultStrings[0]); - } - - public void testGroupingByScalarFunctionWithPivoting() throws Exception { - DataTable res = MockDataSource.getData(3); - - // select sum(age), count(dept), hour(lunchTime) group by hour(lunchtime) - // pivot isSenior. - Query q = new Query(); - - // Add selection. - QuerySelection selection = new QuerySelection(); - selection.addColumn(new AggregationColumn(new SimpleColumn("age"), - AggregationType.SUM)); - selection.addColumn(new AggregationColumn(new SimpleColumn("dept"), - AggregationType.COUNT)); - selection.addColumn(new ScalarFunctionColumn( - Lists.newArrayList((AbstractColumn) new SimpleColumn("lunchTime")), - TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.HOUR))); - q.setSelection(selection); - - // Add group. - QueryGroup group = new QueryGroup(); - group.addColumn(new ScalarFunctionColumn( - Lists.newArrayList((AbstractColumn) new SimpleColumn("lunchTime")), - TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.HOUR))); - q.setGroup(group); - - // Add pivot. - QueryPivot pivot = new QueryPivot(); - pivot.addColumn(new SimpleColumn("isSenior")); - q.setPivot(pivot); - - q.validate(); - - DataTable result = QueryEngine.executeQuery(q, res, ULocale.US); - - // Test column description - List cols = result.getColumnDescriptions(); - - assertEquals(5, cols.size()); - assertEquals("false sum-age", cols.get(0).getId()); - assertEquals("true sum-age", cols.get(1).getId()); - assertEquals("false count-dept", cols.get(2).getId()); - assertEquals("true count-dept", cols.get(3).getId()); - assertEquals("hour_lunchTime", cols.get(4).getId()); - - String[][] resultStrings = MockDataSource.queryResultToStringMatrix(result); - assertEquals(2, resultStrings.length); - - assertStringArraysEqual(new String[]{"52.0", "67.0", "2.0", "2.0", "12.0"}, - resultStrings[0]); - assertStringArraysEqual(new String[]{"30.0", "24.0", "1.0", "1.0", "13.0"}, - resultStrings[1]); - - res = MockDataSource.getData(3); - - // select count(dept), datediff(hireDate, seniorityStartTime) group by - // datediff(hireDate, seniorityStartTime) pivot isSenior. - q = new Query(); - - // Add selection. - selection = new QuerySelection(); - selection.addColumn(new AggregationColumn(new SimpleColumn("dept"), - AggregationType.COUNT)); - selection.addColumn(new ScalarFunctionColumn( - Lists.newArrayList( - new SimpleColumn("seniorityStartTime"), - new SimpleColumn("hireDate")), DateDiff.getInstance())); - q.setSelection(selection); - - // Add group. - group = new QueryGroup(); - group.addColumn(new ScalarFunctionColumn( - Lists.newArrayList( - new SimpleColumn("seniorityStartTime"), - new SimpleColumn("hireDate")), DateDiff.getInstance())); - q.setGroup(group); - - // Add pivot. - pivot = new QueryPivot(); - pivot.addColumn(new SimpleColumn("isSenior")); - q.setPivot(pivot); - - q.validate(); - - result = QueryEngine.executeQuery(q, res, ULocale.US); - - // Test column description - cols = result.getColumnDescriptions(); - - assertEquals(3, cols.size()); - assertEquals("false count-dept", cols.get(0).getId()); - assertEquals("true count-dept", cols.get(1).getId()); - assertEquals("dateDiff_seniorityStartTime,hireDate", cols.get(2).getId()); - - resultStrings = MockDataSource.queryResultToStringMatrix(result); - assertEquals(4, resultStrings.length); - - assertStringArraysEqual(new String[]{"3.0", "null", "null"}, - resultStrings[0]); - assertStringArraysEqual(new String[]{"null", "1.0", "891.0"}, - resultStrings[1]); - assertStringArraysEqual(new String[]{"null", "1.0", "1084.0"}, - resultStrings[2]); - assertStringArraysEqual(new String[]{"null", "1.0", "1180.0"}, - resultStrings[3]); - } - - public void testPivotingByScalarFunctionWithGrouping() throws Exception { - DataTable res = MockDataSource.getData(3); - - // select sum(age), count(dept) group by isSenior pivot hour(lunchtime) - Query q = new Query(); - - // Add selection. - QuerySelection selection = new QuerySelection(); - selection.addColumn(new AggregationColumn(new SimpleColumn("age"), - AggregationType.SUM)); - selection.addColumn(new AggregationColumn(new SimpleColumn("dept"), - AggregationType.COUNT)); - selection.addColumn(new SimpleColumn("isSenior")); - q.setSelection(selection); - - // Add Group. - QueryGroup group = new QueryGroup(); - group.addColumn(new SimpleColumn("isSenior")); - q.setGroup(group); - - // Add pivot. - QueryPivot pivot = new QueryPivot(); - pivot.addColumn(new ScalarFunctionColumn( - Lists.newArrayList((AbstractColumn) new SimpleColumn("lunchTime")), - TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.HOUR))); - q.setPivot(pivot); - - q.validate(); - - DataTable result = QueryEngine.executeQuery(q, res, ULocale.US); - - // Test column description - List cols = result.getColumnDescriptions(); - - assertEquals(5, cols.size()); - assertEquals("12.0 sum-age", cols.get(0).getId()); - assertEquals("13.0 sum-age", cols.get(1).getId()); - assertEquals("12.0 count-dept", cols.get(2).getId()); - assertEquals("13.0 count-dept", cols.get(3).getId()); - assertEquals("isSenior", cols.get(4).getId()); - - String[][] resultStrings = MockDataSource.queryResultToStringMatrix(result); - assertEquals(2, resultStrings.length); - - assertStringArraysEqual(new String[]{"52.0", "30.0", "2.0", "1.0", - "false"}, resultStrings[0]); - assertStringArraysEqual(new String[]{"67.0", "24.0", "2.0", "1.0", - "true"}, resultStrings[1]); - - // selectcount(dept) group by isSenior pivot datediff(hireDate, - // seniorityStartTime) - q = new Query(); - res = MockDataSource.getData(3); - - // Add selection. - selection = new QuerySelection(); - selection.addColumn(new AggregationColumn(new SimpleColumn("dept"), - AggregationType.COUNT)); - selection.addColumn(new SimpleColumn("isSenior")); - q.setSelection(selection); - - // Add Group. - group = new QueryGroup(); - group.addColumn(new SimpleColumn("isSenior")); - q.setGroup(group); - - // Add pivot. - pivot = new QueryPivot(); - pivot.addColumn(new ScalarFunctionColumn( - Lists.newArrayList( - new SimpleColumn("seniorityStartTime"), - new SimpleColumn("hireDate")), DateDiff.getInstance())); - q.setPivot(pivot); - - q.validate(); - - result = QueryEngine.executeQuery(q, res, ULocale.US); - - // Test column description - cols = result.getColumnDescriptions(); - - assertEquals(5, cols.size()); - assertEquals("null count-dept", cols.get(0).getId()); - assertEquals("891.0 count-dept", cols.get(1).getId()); - assertEquals("1084.0 count-dept", cols.get(2).getId()); - assertEquals("1180.0 count-dept", cols.get(3).getId()); - assertEquals("isSenior", cols.get(4).getId()); - - resultStrings = MockDataSource.queryResultToStringMatrix(result); - assertEquals(2, resultStrings.length); - - assertStringArraysEqual(new String[]{"3.0", "null", "null", "null", - "false"}, resultStrings[0]); - assertStringArraysEqual(new String[]{"null", "1.0", "1.0", "1.0", - "true"}, resultStrings[1]); - } - - public void testGroupingAndPivotingByScalarFunction() throws Exception { - DataTable res = MockDataSource.getData(3); - - // select count(dept), year(seniorityStartTime) group by - // year(seniorityStartTime) pivot hour(lunchtime) - Query q = new Query(); - - // Add selection. - QuerySelection selection = new QuerySelection(); - selection.addColumn(new AggregationColumn(new SimpleColumn("dept"), - AggregationType.COUNT)); - selection.addColumn(new ScalarFunctionColumn( - Lists.newArrayList((AbstractColumn) - new SimpleColumn("seniorityStartTime")), TimeComponentExtractor. - getInstance(TimeComponentExtractor.TimeComponent.YEAR))); - - q.setSelection(selection); - - // Add Group. - QueryGroup group = new QueryGroup(); - group.addColumn(new ScalarFunctionColumn(Lists.newArrayList((AbstractColumn) - new SimpleColumn("seniorityStartTime")), TimeComponentExtractor. - getInstance(TimeComponentExtractor.TimeComponent.YEAR))); - q.setGroup(group); - - // Add pivot. - QueryPivot pivot = new QueryPivot(); - pivot.addColumn(new ScalarFunctionColumn(Lists.newArrayList( - (AbstractColumn) new SimpleColumn("lunchTime")), - TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.HOUR))); - q.setPivot(pivot); - - q.validate(); - - DataTable result = QueryEngine.executeQuery(q, res, ULocale.US); - - // Test column description - List cols = result.getColumnDescriptions(); - - assertEquals(3, cols.size()); - assertEquals("12.0 count-dept", cols.get(0).getId()); - assertEquals("13.0 count-dept", cols.get(1).getId()); - assertEquals("year_seniorityStartTime", cols.get(2).getId()); - - String[][] resultStrings = MockDataSource.queryResultToStringMatrix(result); - assertEquals(3, resultStrings.length); - - assertStringArraysEqual(new String[]{"2.0", "1.0", "null"}, - resultStrings[0]); - assertStringArraysEqual(new String[]{"1.0", "null", "2005.0"}, - resultStrings[1]); - assertStringArraysEqual(new String[]{"1.0", "1.0", "2007.0"}, - resultStrings[2]); - } - - public void testSelectionOfScalarFunction() throws Exception { - DataTable res = MockDataSource.getData(3); - - // select name, dept, hour(lunchTime) - Query q = new Query(); - QuerySelection selection = new QuerySelection(); - selection.addColumn(new SimpleColumn("name")); - selection.addColumn(new SimpleColumn("dept")); - selection.addColumn(new ScalarFunctionColumn( - Lists.newArrayList((AbstractColumn) new SimpleColumn("lunchTime")), - TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.HOUR))); - - q.setSelection(selection); - q.validate(); - DataTable result = QueryEngine.executeQuery(q, res, ULocale.US); - - // Test column description - List cols = result.getColumnDescriptions(); - - assertEquals(3, cols.size()); - assertEquals("name", cols.get(0).getId()); - assertEquals("dept", cols.get(1).getId()); - assertEquals("hour_lunchTime", cols.get(2).getId()); - - String[][] resultStrings = MockDataSource.queryResultToStringMatrix(result); - assertEquals(6, resultStrings.length); - - assertStringArraysEqual(new String[]{"John", "Eng", "12.0"}, - resultStrings[0]); - assertStringArraysEqual(new String[]{"Dave", "Eng", "12.0"}, - resultStrings[1]); - assertStringArraysEqual(new String[]{"Sally", "Eng", "13.0"}, - resultStrings[2]); - assertStringArraysEqual(new String[]{"Ben", "Sales", "12.0"}, - resultStrings[3]); - assertStringArraysEqual(new String[]{"Dana", "Sales", "12.0"}, - resultStrings[4]); - assertStringArraysEqual(new String[]{"Mike", "Marketing", "13.0"}, - resultStrings[5]); - } - - public void testSelectionOfScalarFunctionWithGrouping() throws Exception { - DataTable res = MockDataSource.getData(3); - - // select sum(age), dept, hour(min(lunchTime)) group by dept - Query q = new Query(); - - // Add selection. - QuerySelection selection = new QuerySelection(); - selection.addColumn(new AggregationColumn(new SimpleColumn("age"), - AggregationType.SUM)); - selection.addColumn(new SimpleColumn("dept")); - selection.addColumn(new ScalarFunctionColumn( - Lists.newArrayList((AbstractColumn) new AggregationColumn( - new SimpleColumn("lunchTime"), AggregationType.MIN)), - TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.HOUR))); - q.setSelection(selection); - - // Add group. - QueryGroup group = new QueryGroup(); - group.addColumn(new SimpleColumn("dept")); - q.setGroup(group); - - q.validate(); - - DataTable result = QueryEngine.executeQuery(q, res, ULocale.US); - - // Test column description - List cols = result.getColumnDescriptions(); - - assertEquals(3, cols.size()); - assertEquals("sum-age", cols.get(0).getId()); - assertEquals("dept", cols.get(1).getId()); - assertEquals("hour_min-lunchTime", cols.get(2).getId()); - - String[][] resultStrings = MockDataSource.queryResultToStringMatrix(result); - assertEquals(3, resultStrings.length); - - assertStringArraysEqual(new String[]{"92.0", "Eng", "12.0"}, - resultStrings[0]); - assertStringArraysEqual(new String[]{"24.0", "Marketing", "13.0"}, - resultStrings[1]); - assertStringArraysEqual(new String[]{"57.0", "Sales", "12.0"}, - resultStrings[2]); - - // Test group-by column with scalar function in the selection: - // select count(name), hour(lunchTime) group by lunchtime - q = new Query(); - // Add selection - QuerySelection selection1 = new QuerySelection(); - selection1.addColumn(new AggregationColumn(new SimpleColumn("name"), - AggregationType.COUNT)); - selection1.addColumn(new ScalarFunctionColumn( - Lists.newArrayList((AbstractColumn) new SimpleColumn("lunchTime")), - TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.HOUR))); - q.setSelection(selection1); - - // Add group. - QueryGroup group1 = new QueryGroup(); - group1.addColumn(new SimpleColumn("lunchTime")); - q.setGroup(group1); - - q.validate(); - - DataTable result1 = QueryEngine.executeQuery(q, res, ULocale.US); - - // Test column description - List cols1 = result1.getColumnDescriptions(); - - assertEquals(2, cols1.size()); - assertEquals("count-name", cols1.get(0).getId()); - assertEquals("hour_lunchTime", cols1.get(1).getId()); - - String[][] resultStrings1 = - MockDataSource.queryResultToStringMatrix(result1); - assertEquals(2, resultStrings1.length); - - assertStringArraysEqual(new String[]{"4.0", "12.0"}, - resultStrings1[0]); - assertStringArraysEqual(new String[]{"2.0", "13.0"}, - resultStrings1[1]); - } - - public void testSelectionOfScalarFunctionWithPivoting() throws Exception { - DataTable res = MockDataSource.getData(3); - - // select sum(age), hour(min(lunchTime)) pivot dept - Query q = new Query(); - - // Add selection. - QuerySelection selection = new QuerySelection(); - selection.addColumn(new AggregationColumn(new SimpleColumn("age"), - AggregationType.SUM)); - selection.addColumn(new ScalarFunctionColumn( - Lists.newArrayList((AbstractColumn) new AggregationColumn( - new SimpleColumn("lunchTime"), AggregationType.MIN)), - TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.HOUR))); - q.setSelection(selection); - - // Add pivot. - QueryPivot pivot = new QueryPivot(); - pivot.addColumn(new SimpleColumn("dept")); - q.setPivot(pivot); - - q.validate(); - - DataTable result = QueryEngine.executeQuery(q, res, ULocale.US); - - // Test column description - List cols = result.getColumnDescriptions(); - - assertEquals(6, cols.size()); - assertEquals("Eng sum-age", cols.get(0).getId()); - assertEquals("Marketing sum-age", cols.get(1).getId()); - assertEquals("Sales sum-age", cols.get(2).getId()); - assertEquals("Eng hour_min-lunchTime", cols.get(3).getId()); - assertEquals("Marketing hour_min-lunchTime", cols.get(4).getId()); - assertEquals("Sales hour_min-lunchTime", cols.get(5).getId()); - - String[][] resultStrings = MockDataSource.queryResultToStringMatrix(result); - assertEquals(1, resultStrings.length); - - assertStringArraysEqual(new String[]{"92.0", "24.0", "57.0", "12.0", "13.0", - "12.0"}, resultStrings[0]); - } - - public void testSelectionOfScalarFunctionWithGroupingAndPivoting() - throws Exception { - DataTable res = MockDataSource.getData(3); - - // select sum(age), day(hireDate), hour(min(lunchTime)) group by hireDate - // pivot dept - Query q = new Query(); - - // Add selection. - QuerySelection selection = new QuerySelection(); - selection.addColumn(new AggregationColumn(new SimpleColumn("age"), - AggregationType.SUM)); - selection.addColumn(new ScalarFunctionColumn( - Lists.newArrayList((AbstractColumn) new SimpleColumn("hireDate")), - TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.DAY))); - selection.addColumn(new ScalarFunctionColumn( - Lists.newArrayList((AbstractColumn) new AggregationColumn( - new SimpleColumn("lunchTime"), AggregationType.MIN)), - TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.HOUR))); - q.setSelection(selection); - - //Add group. - QueryGroup group = new QueryGroup(); - group.addColumn(new SimpleColumn("hireDate")); - q.setGroup(group); - - // Add pivot. - QueryPivot pivot = new QueryPivot(); - pivot.addColumn(new SimpleColumn("dept")); - q.setPivot(pivot); - - q.validate(); - - DataTable result = QueryEngine.executeQuery(q, res, ULocale.US); - - // Test column description - List cols = result.getColumnDescriptions(); - - assertEquals(7, cols.size()); - assertEquals("Eng sum-age", cols.get(0).getId()); - assertEquals("Marketing sum-age", cols.get(1).getId()); - assertEquals("Sales sum-age", cols.get(2).getId()); - assertEquals("day_hireDate", cols.get(3).getId()); - assertEquals("Eng hour_min-lunchTime", cols.get(4).getId()); - assertEquals("Marketing hour_min-lunchTime", cols.get(5).getId()); - assertEquals("Sales hour_min-lunchTime", cols.get(6).getId()); - - String[][] resultStrings = MockDataSource.queryResultToStringMatrix(result); - assertEquals(4, resultStrings.length); - - assertStringArraysEqual(new String[]{"null", "null", "32.0", "10.0", "null", - "null", "12.0"}, resultStrings[0]); - assertStringArraysEqual(new String[]{"35.0", "null", "25.0", "8.0", "12.0", - "null", "12.0"}, resultStrings[1]); - assertStringArraysEqual(new String[]{"null", "24.0", "null", "10.0", "null", - "13.0", "null"}, resultStrings[2]); - assertStringArraysEqual(new String[]{"57.0", "null", "null", "10.0", "12.0", - "null", "null"}, resultStrings[3]); - } - - public void testSelectionOfScalarFunctionWithEmptyTable() throws Exception { - DataTable res = MockDataSource.getData(3); - - // select sum(age), day(hireDate), hour(min(lunchTime)) where name="liron" - // group by hireDate pivot dept - Query q = new Query(); - - // Add selection. - QuerySelection selection = new QuerySelection(); - selection.addColumn(new AggregationColumn(new SimpleColumn("age"), - AggregationType.SUM)); - selection.addColumn(new ScalarFunctionColumn( - Lists.newArrayList((AbstractColumn) new SimpleColumn("hireDate")), - TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.DAY))); - selection.addColumn(new ScalarFunctionColumn( - Lists.newArrayList((AbstractColumn) new AggregationColumn( - new SimpleColumn("lunchTime"), AggregationType.MIN)), - TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.HOUR))); - q.setSelection(selection); - - //Add filter. - QueryFilter filter = new ColumnValueFilter(new SimpleColumn("name"), - new TextValue("name"), ComparisonFilter.Operator.EQ); - q.setFilter(filter); - - //Add group. - QueryGroup group = new QueryGroup(); - group.addColumn(new SimpleColumn("hireDate")); - q.setGroup(group); - - // Add pivot. - QueryPivot pivot = new QueryPivot(); - pivot.addColumn(new SimpleColumn("dept")); - q.setPivot(pivot); - - q.validate(); - - DataTable result = QueryEngine.executeQuery(q, res, ULocale.US); - // Test column description - List cols = result.getColumnDescriptions(); - - assertEquals(3, cols.size()); - String[][] resultStrings = MockDataSource.queryResultToStringMatrix(result); - assertEquals(0, resultStrings.length); - } - - public void testOrderByScalarFunction() throws Exception { - DataTable res = MockDataSource.getData(3); - - // select day(hireDate), hireDate, age order by day(hireDate) - Query q = new Query(); - - // Add selection. - QuerySelection selection = new QuerySelection(); - selection.addColumn(new ScalarFunctionColumn( - Lists.newArrayList((AbstractColumn) new SimpleColumn("hireDate")), - TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.DAY))); - selection.addColumn(new SimpleColumn("hireDate")); - selection.addColumn(new SimpleColumn("age")); - q.setSelection(selection); - - // Add sort. - QuerySort sort = new QuerySort(); - sort.addSort(new ScalarFunctionColumn( - Lists.newArrayList((AbstractColumn) new SimpleColumn("hireDate")), - TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.DAY)), SortOrder.ASCENDING); - q.setSort(sort); - - q.validate(); - - DataTable result = QueryEngine.executeQuery(q, res, ULocale.US); - - // Test column description - List cols = result.getColumnDescriptions(); - - assertEquals(3, cols.size()); - assertEquals("day_hireDate", cols.get(0).getId()); - assertEquals("hireDate", cols.get(1).getId()); - assertEquals("age", cols.get(2).getId()); - - String[][] resultStrings = MockDataSource.queryResultToStringMatrix(result); - assertEquals(6, resultStrings.length); - - assertStringArraysEqual(new String[]{"8.0", "2004-09-08", "35.0"}, - resultStrings[0]); - assertStringArraysEqual(new String[]{"8.0", "2004-09-08", "25.0"}, - resultStrings[1]); - assertStringArraysEqual(new String[]{"10.0", "2005-10-10", "27.0"}, - resultStrings[2]); - assertStringArraysEqual(new String[]{"10.0", "2005-10-10", "30.0"}, - resultStrings[3]); - assertStringArraysEqual(new String[]{"10.0", "2002-10-10", "32.0"}, - resultStrings[4]); - assertStringArraysEqual(new String[]{"10.0", "2005-01-10", "24.0"}, - resultStrings[5]); - } - - public void testSelectionOfArithmeticExpression() throws Exception { - DataTable res = MockDataSource.getData(3); - - // select day(hireDate) + age * hour(seniorityStartTime), age - Query q = new Query(); - - // Add selection. - QuerySelection selection = new QuerySelection(); - AbstractColumn col1 = new ScalarFunctionColumn( - Lists.newArrayList(new SimpleColumn("hireDate")), - TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.DAY)); - AbstractColumn col2 = new SimpleColumn("age"); - AbstractColumn col3 = new ScalarFunctionColumn( - Lists.newArrayList( - new SimpleColumn("seniorityStartTime")), - TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.HOUR)); - AbstractColumn col4 = new ScalarFunctionColumn( - Lists.newArrayList(col2, col3), Product.getInstance()); - AbstractColumn col5 = new ScalarFunctionColumn( - Lists.newArrayList(col1, col4), Sum.getInstance()); - selection.addColumn(col5); - selection.addColumn(new SimpleColumn("age")); - q.setSelection(selection); - q.validate(); - - DataTable result = QueryEngine.executeQuery(q, res, ULocale.US); - - // Test column description - List cols = result.getColumnDescriptions(); - - assertEquals(2, cols.size()); - assertEquals("sum_day_hireDate,product_age,hour_seniorityStartTime", - cols.get(0).getId()); - assertEquals("age", cols.get(1).getId()); - - String[][] resultStrings = MockDataSource.queryResultToStringMatrix(result); - assertEquals(6, resultStrings.length); - - assertStringArraysEqual(new String[]{"533.0", "35.0"}, - resultStrings[0]); - assertStringArraysEqual(new String[]{"null", "27.0"}, - resultStrings[1]); - assertStringArraysEqual(new String[]{"null", "30.0"}, - resultStrings[2]); - assertStringArraysEqual(new String[]{"394.0", "32.0"}, - resultStrings[3]); - assertStringArraysEqual(new String[]{"null", "25.0"}, - resultStrings[4]); - assertStringArraysEqual(new String[]{"346.0", "24.0"}, - resultStrings[5]); - } - - public void testGroupByArithmeticExpression() throws Exception { - DataTable res = MockDataSource.getData(3); - - // select sum(age), day(hireDate) - hour(seniorityStartTime) - // group by day(hireDate) - hour(seniorityStartTime) - Query q = new Query(); - - AbstractColumn col1 = new ScalarFunctionColumn( - Lists.newArrayList(new SimpleColumn("hireDate")), - TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.DAY)); - AbstractColumn col2 = new ScalarFunctionColumn( - Lists.newArrayList( - new SimpleColumn("seniorityStartTime")), - TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.HOUR)); - AbstractColumn col3 = new ScalarFunctionColumn( - Lists.newArrayList(col1, col2), - Difference.getInstance()); - - // Add selection - QuerySelection selection = new QuerySelection(); - selection.addColumn(new AggregationColumn(new SimpleColumn("age"), - AggregationType.SUM)); - selection.addColumn(col3); - q.setSelection(selection); - - // Add group - QueryGroup group = new QueryGroup(); - group.addColumn(col3); - q.setGroup(group); - - q.validate(); - - DataTable result = QueryEngine.executeQuery(q, res, ULocale.US); - - // Test column description - List cols = result.getColumnDescriptions(); - - assertEquals(2, cols.size()); - assertEquals("sum-age", cols.get(0).getId()); - assertEquals("difference_day_hireDate,hour_seniorityStartTime", - cols.get(1).getId()); - - String[][] resultStrings = MockDataSource.queryResultToStringMatrix(result); - assertEquals(4, resultStrings.length); - - assertStringArraysEqual(new String[]{"82.0", "null"}, - resultStrings[0]); - assertStringArraysEqual(new String[]{"35.0", "-7.0"}, - resultStrings[1]); - assertStringArraysEqual(new String[]{"24.0", "-4.0"}, - resultStrings[2]); - assertStringArraysEqual(new String[]{"32.0", "-2.0"}, - resultStrings[3]); - } - - public void testFilterArithmeticExpression() throws Exception { - DataTable res = MockDataSource.getData(3); - - // select day(hireDate), hour(seniorityStartTime) where - // day(hireDate) - hour(seniorityStartTime) < -5 - // group by day(hireDate) - hour(seniorityStartTime) - Query q = new Query(); - - AbstractColumn col1 = new ScalarFunctionColumn( - Lists.newArrayList(new SimpleColumn("hireDate")), - TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.DAY)); - AbstractColumn col2 = new ScalarFunctionColumn( - Lists.newArrayList( - new SimpleColumn("seniorityStartTime")), - TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.HOUR)); - AbstractColumn col3 = new ScalarFunctionColumn( - Lists.newArrayList(col1, col2), - Difference.getInstance()); - - // Add selection - QuerySelection selection = new QuerySelection(); - selection.addColumn(col1); - selection.addColumn(col2); - q.setSelection(selection); - - // Add Filter - QueryFilter filter = new ColumnValueFilter(col3, new NumberValue(-5), - ComparisonFilter.Operator.GT); - q.setFilter(filter); - - q.validate(); - - DataTable result = QueryEngine.executeQuery(q, res, ULocale.US); - - // Test column description - List cols = result.getColumnDescriptions(); - - assertEquals(2, cols.size()); - assertEquals("day_hireDate", cols.get(0).getId()); - assertEquals("hour_seniorityStartTime", cols.get(1).getId()); - - String[][] resultStrings = MockDataSource.queryResultToStringMatrix(result); - assertEquals(2, resultStrings.length); - - assertStringArraysEqual(new String[]{"10.0", "12.0"}, - resultStrings[0]); - assertStringArraysEqual(new String[]{"10.0", "14.0"}, - resultStrings[1]); - } - - public void testModuloInSelection() throws Exception { - DataTable res = MockDataSource.getData(0); - - // selection with modulo ('weight' is a column id): "select weight, weight % 10" - Query q = new Query(); - - AbstractColumn col1 = new ScalarFunctionColumn( - Lists.newArrayList(), new Constant(new NumberValue(10))); - AbstractColumn col2 = new ScalarFunctionColumn( - Lists.newArrayList(new SimpleColumn("weight"), col1), - Modulo.getInstance()); - - // Add selection - QuerySelection selection = new QuerySelection(); - selection.addColumn(new SimpleColumn("weight")); - selection.addColumn(col2); - q.setSelection(selection); - - q.validate(); - - DataTable result = QueryEngine.executeQuery(q, res, ULocale.US); - - // Test column description - List cols = result.getColumnDescriptions(); - - assertEquals(2, cols.size()); - assertEquals("weight", cols.get(0).getId()); - assertEquals("modulo_weight,10.0_", cols.get(1).getId()); - - String[][] resultStrings = MockDataSource.queryResultToStringMatrix(result); - assertEquals(7, resultStrings.length); - - assertStringArraysEqual(new String[]{"222.0", "2.0"}, - resultStrings[0]); - assertStringArraysEqual(new String[]{"111.0", "1.0"}, - resultStrings[1]); - assertStringArraysEqual(new String[]{"333.0", "3.0"}, - resultStrings[2]); - assertStringArraysEqual(new String[]{"222.0", "2.0"}, - resultStrings[3]); - assertStringArraysEqual(new String[]{"1234.0", "4.0"}, - resultStrings[4]); - assertStringArraysEqual(new String[]{"1234.0", "4.0"}, - resultStrings[5]); - assertStringArraysEqual(new String[]{"222.0", "2.0"}, - resultStrings[6]); - } - - public void testModuloInFilter() throws Exception { - DataTable res = MockDataSource.getData(0); - - // Create a query with filter clause using module: - // select name, weight where weight%2=0.0 - Query q = new Query(); - - // Add selection - QuerySelection selection = new QuerySelection(); - selection.addColumn(new SimpleColumn("name")); - selection.addColumn(new SimpleColumn("weight")); - q.setSelection(selection); - - AbstractColumn col1 = new ScalarFunctionColumn( - Lists.newArrayList(), new Constant(new NumberValue(2))); - AbstractColumn col2 = new ScalarFunctionColumn( - Lists.newArrayList(new SimpleColumn("weight"), col1), - Modulo.getInstance()); - - QueryFilter filter = new ColumnValueFilter(col2, - new NumberValue(0), ComparisonFilter.Operator.EQ); - q.setFilter(filter); - - q.validate(); - - DataTable result = QueryEngine.executeQuery(q, res, ULocale.US); - - // Test column description - List cols = result.getColumnDescriptions(); - - assertEquals(2, cols.size()); - assertEquals("name", cols.get(0).getId()); - assertEquals("weight", cols.get(1).getId()); - - String[][] resultStrings = MockDataSource.queryResultToStringMatrix(result); - assertEquals(5, resultStrings.length); - - assertStringArraysEqual(new String[]{"aaa", "222.0"}, - resultStrings[0]); - assertStringArraysEqual(new String[]{"ddd", "222.0"}, - resultStrings[1]); - assertStringArraysEqual(new String[]{"eee", "1234.0"}, - resultStrings[2]); - assertStringArraysEqual(new String[]{"eee", "1234.0"}, - resultStrings[3]); - assertStringArraysEqual(new String[]{"bbb", "222.0"}, - resultStrings[4]); - } - - public void testLabels() throws Exception { - Query query = new Query(); - - DataTable data = MockDataSource.getData(0); - - QuerySelection selection = new QuerySelection(); - selection.addColumn(new SimpleColumn("name")); - selection.addColumn(new SimpleColumn("isAlive")); - query.setSelection(selection); - - QueryLabels labels = new QueryLabels(); - labels.addLabel(new SimpleColumn("isAlive"), - "New isAlive Label"); - query.setLabels(labels); - - DataTable res = QueryEngine.executeQuery(query, data, ULocale.US); - - assertEquals("Pet Name", res.getColumnDescription("name").getLabel()); - assertEquals("New isAlive Label", res.getColumnDescription("isAlive").getLabel()); - } - - public void testFormatAndLabelOnPivotColumns() throws Exception { - Query query = new Query(); - QuerySelection selection = new QuerySelection(); // SELECT (sum(sales) / 7) - List columns = Lists.newArrayList(); - columns.add(new AggregationColumn(new SimpleColumn("Sales"), AggregationType.SUM)); - columns.add(new ScalarFunctionColumn(Lists.newArrayList(), - new Constant(new NumberValue(7)))); - AbstractColumn selectedColumn = new ScalarFunctionColumn(columns, Quotient.getInstance()); - selection.addColumn(selectedColumn); - - query.setSelection(selection); - QueryGroup group = new QueryGroup(); - group.addColumn(new SimpleColumn("Year")); - query.setGroup(group); - QueryPivot pivot = new QueryPivot(); - pivot.addColumn(new SimpleColumn("Band")); - pivot.addColumn(new SimpleColumn("Songs")); - query.setPivot(pivot); - QueryLabels labels = new QueryLabels(); - labels.addLabel(selectedColumn, "foo"); - query.setLabels(labels); - QueryFormat format = new QueryFormat(); - format.addPattern(selectedColumn, "'$'@@@"); - query.setUserFormatOptions(format); - - DataTable data = MockDataSource.getData(1); - - // Also tests different locale (note the commas in the numbers) - DataTable res = QueryEngine.executeQuery(query, data, ULocale.FRENCH); - - List columnDescriptions = res.getColumnDescriptions(); - assertEquals(5, columnDescriptions.size()); - assertEquals("", res.getRow(0).getCell(0).getFormattedValue()); // null - assertEquals("$2,29", res.getRow(0).getCell(1).getFormattedValue()); - assertEquals("$1,14", res.getRow(0).getCell(2).getFormattedValue()); - assertEquals("$4,57", res.getRow(0).getCell(3).getFormattedValue()); - assertEquals("$0,571", res.getRow(0).getCell(4).getFormattedValue()); - assertEquals("Collection,2.0 foo", columnDescriptions.get(0).getLabel()); - assertEquals("Contraband,2.0 foo", columnDescriptions.get(1).getLabel()); - assertEquals("Contraband,4.0 foo", columnDescriptions.get(2).getLabel()); - assertEquals("Youthanasia,2.0 foo", columnDescriptions.get(3).getLabel()); - assertEquals("Youthanasia,4.0 foo", columnDescriptions.get(4).getLabel()); - } - - // We used to have a bug with this throwing a runtime exception - public void testAggregationAppearsTwice() throws Exception { - Query q = QueryBuilder.getInstance().parseQuery("SELECT isAlive, sum(weight), sum(weight)+1" - + " GROUP BY isAlive"); - DataTable data = MockDataSource.getData(0); - DataTable res = QueryEngine.executeQuery(q, data, ULocale.US); - assertEquals(2, res.getNumberOfRows()); - assertEquals("false", res.getRow(0).getCell(0).getValue().toString()); - assertEquals("2011.0", res.getRow(0).getCell(1).getValue().toString()); - assertEquals("2012.0", res.getRow(0).getCell(2).getValue().toString()); - assertEquals("true", res.getRow(1).getCell(0).getValue().toString()); - assertEquals("1567.0", res.getRow(1).getCell(1).getValue().toString()); - assertEquals("1568.0", res.getRow(1).getCell(2).getValue().toString()); - } - - // Tests that the format operation saves the pattern on the column description. - public void testFormatStoresPattern() throws Exception { - Query q = QueryBuilder.getInstance().parseQuery("FORMAT weight 'a#'"); - DataTable data = MockDataSource.getData(0); - DataTable res = QueryEngine.executeQuery(q, data, ULocale.US); - assertEquals("a#", res.getColumnDescription("weight").getPattern()); - } - - public void testQueryDoesntRuinDataSourcePatterns() throws Exception { - Query q = QueryBuilder.getInstance().parseQuery("SELECT isAlive, weight WHERE height > 20 " - + "ORDER BY weight LIMIT 3 OFFSET 2"); - DataTable data = MockDataSource.getData(0).clone(); - data.getColumnDescription("weight").setPattern("f#"); - DataTable res = QueryEngine.executeQuery(q, data, ULocale.US); - assertEquals("f#", res.getColumnDescription("weight").getPattern()); - } - - public void testQueryWithLikeOperator() throws InvalidQueryException { - Query q = QueryBuilder.getInstance().parseQuery("SELECT Band WHERE Band like 'Co%'"); - DataTable data = MockDataSource.getData(1).clone(); - DataTable res = QueryEngine.executeQuery(q, data, ULocale.US); - assertEquals(28, res.getNumberOfRows()); - for (int i = 0; i < res.getNumberOfRows(); i++) { - assertTrue(res.getValue(i, 0).toString().startsWith("Co")); - } - } - - public void testScalarFunctions() throws InvalidQueryException { - Query q = QueryBuilder.getInstance().parseQuery("SELECT upper(name),salary format salary '$0'"); - DataTable data = MockDataSource.getData(3); - DataTable res = QueryEngine.executeQuery(q, data, ULocale.US); - assertEquals("JOHN", res.getValue(0, 0).toString()); - assertEquals("$1000", res.getCell(0, 1).getFormattedValue()); - } - - public void testSkipping() throws Exception { - DataTable res = MockDataSource.getData(1); - - // The returned mock data table should consist of 45 rows - assertEquals(45, res.getNumberOfRows()); - - Query q = QueryBuilder.getInstance().parseQuery("SELECT Year, Band, Songs SKIPPING 10"); - - q.validate(); - - DataTable result = QueryEngine.executeQuery(q, res, ULocale.US); - - // Test column description - List cols = result.getColumnDescriptions(); - - assertEquals(3, cols.size()); - assertEquals("Year", cols.get(0).getId()); - assertEquals("Band", cols.get(1).getId()); - assertEquals("Songs", cols.get(2).getId()); - - String[][] resultStrings = MockDataSource.queryResultToStringMatrix(result); - - // Querying a table of 45 rows with skipping value set to 10 should - // result in a 5 rows data table - assertEquals(5, resultStrings.length); - - // The selected rows should be 0, 10, 20... - assertStringArraysEqual(new String[]{"1994", "Contraband", "2.0"}, - resultStrings[0]); - assertStringArraysEqual(new String[]{"1994", "Youthanasia", "2.0"}, - resultStrings[1]); - assertStringArraysEqual(new String[]{"1996", "Contraband", "2.0"}, - resultStrings[2]); - assertStringArraysEqual(new String[]{"2003", "Collection", "2.0"}, - resultStrings[3]); - assertStringArraysEqual(new String[]{"2003", "Collection", "2.0"}, - resultStrings[4]); - } - - public void testSkippingWithPagination() throws Exception { - DataTable res = MockDataSource.getData(1); - - // The returned mock data table should consist of 45 rows - assertEquals(45, res.getNumberOfRows()); - - Query q = QueryBuilder.getInstance().parseQuery("SELECT Year, Band, Songs " + - "SKIPPING 4 LIMIT 4 OFFSET 4"); - - q.validate(); - - DataTable result = QueryEngine.executeQuery(q, res, ULocale.US); - - // Test column description - List cols = result.getColumnDescriptions(); - - assertEquals(3, cols.size()); - assertEquals("Year", cols.get(0).getId()); - assertEquals("Band", cols.get(1).getId()); - assertEquals("Songs", cols.get(2).getId()); - - String[][] resultStrings = MockDataSource.queryResultToStringMatrix(result); - - // Querying a table of 45 rows with skipping value set to 4 should - // result in a 13 rows data table. Limit value set to 4 should result in - // 4 rows subset of the 13 rows. Offset value set to 4 dictates that the - // subset will be rows 4-7 of the 13 rows. - assertEquals(4, resultStrings.length); - - assertStringArraysEqual(new String[]{"1996", "Contraband", "2.0"}, - resultStrings[0]); - assertStringArraysEqual(new String[]{"1996", "Contraband", "2.0"}, - resultStrings[1]); - assertStringArraysEqual(new String[]{"1996", "Youthanasia", "2.0"}, - resultStrings[2]); - assertStringArraysEqual(new String[]{"1996", "Youthanasia", "2.0"}, - resultStrings[3]); - } - - public void testSkippingWithFiltering() throws Exception { - DataTable res = MockDataSource.getData(1); - - // The returned mock data table should consist of 45 rows - assertEquals(45, res.getNumberOfRows()); - - Query q = QueryBuilder.getInstance().parseQuery("SELECT Year, Band, Songs " + - "WHERE Fans <= 3000 SKIPPING 10"); - - q.validate(); - - DataTable result = QueryEngine.executeQuery(q, res, ULocale.US); - - // Test column description - List cols = result.getColumnDescriptions(); - - assertEquals(3, cols.size()); - assertEquals("Year", cols.get(0).getId()); - assertEquals("Band", cols.get(1).getId()); - assertEquals("Songs", cols.get(2).getId()); - - String[][] resultStrings = MockDataSource.queryResultToStringMatrix(result); - - // The WHERE clause reduce the result number of rows to 31. - // Skipping value is set to 10, so the resulting table should - // consist of 4 rows. - assertEquals(4, resultStrings.length); - - assertStringArraysEqual(new String[]{"1994", "Contraband", "2.0"}, - resultStrings[0]); - assertStringArraysEqual(new String[]{"1996", "Contraband", "2.0"}, - resultStrings[1]); - assertStringArraysEqual(new String[]{"2003", "Collection", "2.0"}, - resultStrings[2]); - assertStringArraysEqual(new String[]{"2003", "Collection", "2.0"}, - resultStrings[3]); - } -} diff --git a/src/test/java/com/google/visualization/datasource/query/engine/ScalarFunctionColumnTitleTest.java b/src/test/java/com/google/visualization/datasource/query/engine/ScalarFunctionColumnTitleTest.java deleted file mode 100644 index 94a81d7..0000000 --- a/src/test/java/com/google/visualization/datasource/query/engine/ScalarFunctionColumnTitleTest.java +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query.engine; - -import com.google.common.collect.Lists; -import com.google.visualization.datasource.datatable.ColumnDescription; -import com.google.visualization.datasource.datatable.DataTable; -import com.google.visualization.datasource.datatable.value.BooleanValue; -import com.google.visualization.datasource.datatable.value.NumberValue; -import com.google.visualization.datasource.datatable.value.Value; -import com.google.visualization.datasource.datatable.value.ValueType; -import com.google.visualization.datasource.query.AbstractColumn; -import com.google.visualization.datasource.query.AggregationColumn; -import com.google.visualization.datasource.query.AggregationType; -import com.google.visualization.datasource.query.ScalarFunctionColumn; -import com.google.visualization.datasource.query.SimpleColumn; -import com.google.visualization.datasource.query.scalarfunction.TimeComponentExtractor; - -import junit.framework.TestCase; - -import java.util.List; - -/** - * Tests the ScalarFunctionColumnTitleTest class. - * - * @author Liron L. - */ -public class ScalarFunctionColumnTitleTest extends TestCase { - - @Override - public void setUp() throws Exception { - super.setUp(); - } - - /** - * Tests the createColumnDescription method. - */ - public void testCreateColumnDescription() { - ColumnDescription simpleColumnDescription = - new ColumnDescription("simpleColumn", ValueType.DATE, "simpleLabel"); - ColumnDescription aggreationColumnDescription = - new ColumnDescription("min-simpleColumn", ValueType.DATE, - "aggLabel"); - DataTable table = new DataTable(); - table.addColumn(simpleColumnDescription); - table.addColumn(aggreationColumnDescription); - - List simpleColumns = - Lists.newArrayList((AbstractColumn) new SimpleColumn("simpleColumn")); - List aggregationColumns = - Lists.newArrayList((AbstractColumn) new AggregationColumn( - new SimpleColumn("simpleColumn"), AggregationType.MIN)); - ScalarFunctionColumnTitle titleYear = - new ScalarFunctionColumnTitle(Lists.newArrayList(), - new ScalarFunctionColumn(simpleColumns, - TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.YEAR))); - - ScalarFunctionColumnTitle titleSecondWithAggregation = - new ScalarFunctionColumnTitle(Lists.newArrayList(), - new ScalarFunctionColumn(aggregationColumns, - TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.SECOND))); - - ScalarFunctionColumnTitle titleMonthWithPivot = - new ScalarFunctionColumnTitle(Lists.newArrayList(new NumberValue(3.14), - BooleanValue.TRUE), new ScalarFunctionColumn(simpleColumns, - TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.MONTH))); - - ScalarFunctionColumnTitle titleDayWithPivotAndAgg = - new ScalarFunctionColumnTitle(Lists.newArrayList(new NumberValue(3.14), - BooleanValue.TRUE), new ScalarFunctionColumn(aggregationColumns, - TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.DAY))); - - ColumnDescription resultColumnDescriptionYear = titleYear.createColumnDescription(table); - - ColumnDescription resultColumnDescriptionSecondWithAgg = - titleSecondWithAggregation.createColumnDescription(table); - - ColumnDescription resultColumnDescriptionMonthWithPivot = - titleMonthWithPivot.createColumnDescription(table); - - ColumnDescription resultColumnDescriptionDayWithPivotAndAgg = - titleDayWithPivotAndAgg.createColumnDescription(table); - - // Check the creation of result column description with year. - assertEquals("year_simpleColumn", resultColumnDescriptionYear.getId()); - assertEquals(" year(simpleLabel)", resultColumnDescriptionYear.getLabel()); - assertEquals(ValueType.NUMBER, resultColumnDescriptionYear.getType()); - - // Check the creation of result column description with aggregation. - assertEquals("second_min-simpleColumn", - resultColumnDescriptionSecondWithAgg.getId()); - assertEquals(" second(aggLabel)", - resultColumnDescriptionSecondWithAgg.getLabel()); - assertEquals(ValueType.NUMBER, - resultColumnDescriptionSecondWithAgg.getType()); - - // Check the creation of result column description with pivot. - assertEquals("3.14,true month_simpleColumn", - resultColumnDescriptionMonthWithPivot.getId()); - assertEquals("3.14,true month(simpleLabel)", - resultColumnDescriptionMonthWithPivot.getLabel()); - assertEquals(ValueType.NUMBER, - resultColumnDescriptionMonthWithPivot.getType()); - - // Check the creation of result column description with aggregation - // and pivot. - assertEquals("3.14,true day_min-simpleColumn", - resultColumnDescriptionDayWithPivotAndAgg.getId()); - assertEquals("3.14,true day(aggLabel)", - resultColumnDescriptionDayWithPivotAndAgg.getLabel()); - assertEquals(ValueType.NUMBER, - resultColumnDescriptionDayWithPivotAndAgg.getType()); - } -} diff --git a/src/test/java/com/google/visualization/datasource/query/engine/TableAggregatorTest.java b/src/test/java/com/google/visualization/datasource/query/engine/TableAggregatorTest.java deleted file mode 100644 index 0ae047f..0000000 --- a/src/test/java/com/google/visualization/datasource/query/engine/TableAggregatorTest.java +++ /dev/null @@ -1,211 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query.engine; - -import com.google.common.collect.Lists; -import com.google.visualization.datasource.datatable.DataTable; -import com.google.visualization.datasource.datatable.TableRow; -import com.google.visualization.datasource.datatable.value.NumberValue; -import com.google.visualization.datasource.datatable.value.TextValue; -import com.google.visualization.datasource.datatable.value.Value; -import com.google.visualization.datasource.datatable.value.ValueType; -import com.google.visualization.datasource.query.AggregationType; -import com.google.visualization.datasource.query.mocks.MockDataSource; - -import junit.framework.Assert; -import junit.framework.TestCase; - -import java.util.List; -import java.util.NoSuchElementException; - -/** - * Tests for TableAggregator.java. - * - * @author Yoav G. - */ - -public class TableAggregatorTest extends TestCase { - - /** - * An ordered list of columns to group by. - */ - /* package */ List groupByColumns; - - @Override - public void setUp() throws Exception { - super.setUp(); - AggregationNodeTest.createColumnAggregationMap(); - groupByColumns = Lists.newArrayList(); - groupByColumns.add("Year"); - groupByColumns.add("Songs"); - - } - - @Override - public void tearDown() throws Exception { - super.tearDown(); - } - - /** - * Creates a column to value map according to a string array. - * - * @param values A string array. - * - * @return A column to value map. - */ - protected static final AggregationPath generatePath(String[] values) { - AggregationPath result = new AggregationPath(); - if (values.length > 0) { - result.add(MockDataSource.toValue(values[0], ValueType.TEXT)); - } - if (values.length > 1) { - result.add(MockDataSource.toValue(values[1], ValueType.NUMBER)); - } - return result; - } - - /** - * Tests that a group which does not exist in the table causes an exeption. - */ - public void testNoSuchElement() { - TableAggregator tableAggregator = newTableAggregator(1); - try { - tableAggregator.getAggregationValue(generatePath( - new String[]{"1995", "2"}), "Sales", AggregationType.COUNT); - fail(); - } catch (NoSuchElementException e) { - // Expected behavior. - } - } - - /** - * Tests that a column that is not aggregated causes an exception. - */ - public void testNoSuchColumn () { - TableAggregator tableAggregator = newTableAggregator(1); - - try { - assertNull(tableAggregator.getAggregationValue(generatePath( - new String[]{"1994", "2"}), "Saless", AggregationType.COUNT)); - fail(); - } catch (IllegalArgumentException e) { - // Expected behavior. - } - - try { - assertNull(tableAggregator.getAggregationValue(generatePath( - new String[]{"1994", "2"}), "Songs", AggregationType.COUNT)); - fail(); - } catch (IllegalArgumentException e) { - // Expected behavior. - } - } - - /** - * Tests aggregation values on short paths - */ - public void testShortPath () { - TableAggregator tableAggregator = newTableAggregator(1); - - assertEquals("60.0", tableAggregator.getAggregationValue( - generatePath(new String[]{"1994"}), "Sales", - AggregationType.SUM).toString()); - - Assert.assertEquals(new TextValue("Youthanasia"), tableAggregator. - getAggregationValue(generatePath(new String[]{}), "Band", - AggregationType.MAX)); - } - - /** - * Tests aggregation value of a tree leaf. - */ - public void testlongPath() { - TableAggregator tableAggregator = newTableAggregator(1); - assertEquals("48.0", tableAggregator.getAggregationValue( - generatePath(new String[]{"1994", "2"}), "Sales", - AggregationType.SUM).toString()); - } - - /** - * Tests that null values are ignored in aggregation. - */ - public void testNullValues() { - TableAggregator tableAggregator = newTableAggregator(2); - - assertEquals("4.0", tableAggregator.getAggregationValue( - generatePath(new String[]{"1994"}), "Sales", - AggregationType.SUM).toString()); - assertEquals("4.0", tableAggregator.getAggregationValue( - generatePath(new String[]{"1994", "2"}), "Sales", - AggregationType.SUM).toString()); - assertEquals("4.0", tableAggregator.getAggregationValue( - generatePath(new String[]{}), "Sales", - AggregationType.SUM).toString()); - } - /** - * Tests that a null value is considered a group by value. - */ - public void testElementNull() { - TableAggregator tableAggregator = newTableAggregator(2); - - assertEquals("0.0", tableAggregator.getAggregationValue( - generatePath(new String[]{"1994", null}), "Sales", - AggregationType.SUM).toString()); - } - - /** - * Tests that a null value is considered a group by value (that in this case - * does not exist). - */ - public void testNoElementNull() { - TableAggregator tableAggregator = newTableAggregator(2); - try { - tableAggregator.getAggregationValue(generatePath - (new String[]{"2003", null}), "Sales", AggregationType.SUM); - fail(); - } catch (NoSuchElementException e) { - // Expected behavior. - } - } - - /** - * Creates a table aggregator based on a mock data base. - * - * @param tableNum The table number. - * - * @return A table aggregator. - */ - private TableAggregator newTableAggregator(int tableNum) { - return new TableAggregator(groupByColumns, - AggregationNodeTest.columnsToAggregate, - MockDataSource.getData(tableNum)); - } - - public void testGetRowPath() { - TableAggregator aggregator = newTableAggregator(1); - DataTable table = MockDataSource.getData(1); - TableRow row = table.getRow(0); - List path = aggregator.getRowPath(row, table, 0).getValues(); - assertEquals(1, path.size()); - assertEquals("1994", path.get(0).toString()); - - row = table.getRow(6); - path = aggregator.getRowPath(row, table, 1).getValues(); - assertEquals(2, path.size()); - assertEquals("1994", path.get(0).toString()); - assertEquals(2.0, ((NumberValue) path.get(1)).getValue()); - } - -} diff --git a/src/test/java/com/google/visualization/datasource/query/mocks/MockDataSource.java b/src/test/java/com/google/visualization/datasource/query/mocks/MockDataSource.java deleted file mode 100644 index 4f1b951..0000000 --- a/src/test/java/com/google/visualization/datasource/query/mocks/MockDataSource.java +++ /dev/null @@ -1,356 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query.mocks; - -import com.google.visualization.datasource.base.TypeMismatchException; -import com.google.visualization.datasource.datatable.ColumnDescription; -import com.google.visualization.datasource.datatable.DataTable; -import com.google.visualization.datasource.datatable.TableCell; -import com.google.visualization.datasource.datatable.TableRow; -import com.google.visualization.datasource.datatable.value.BooleanValue; -import com.google.visualization.datasource.datatable.value.DateTimeValue; -import com.google.visualization.datasource.datatable.value.DateValue; -import com.google.visualization.datasource.datatable.value.NumberValue; -import com.google.visualization.datasource.datatable.value.TextValue; -import com.google.visualization.datasource.datatable.value.TimeOfDayValue; -import com.google.visualization.datasource.datatable.value.Value; -import com.google.visualization.datasource.datatable.value.ValueType; - - -import java.util.List; -import java.util.Random; - - -/** - * A mock data source for unit tests. - * This data source always caches it's tables. This helps see if at some point - * we ruin the datasource's data table. - * - * @author Yonatan B.Y. - */ -public class MockDataSource { - - /** - * Private constructor, to prevent initialization. - */ - private MockDataSource() {} - - /** - * A random number generator. - */ - private static Random random = null; - - private static final Object[][][] columnData = - { - { - {"name", ValueType.TEXT, "Pet Name"}, - {"weight", ValueType.NUMBER, "Pet Weight"}, - {"isAlive", ValueType.BOOLEAN, "Is Still Alive"}, - {"height", ValueType.NUMBER, "Pet height"} - }, { - {"Year", ValueType.TEXT, "Just year"}, - {"Band", ValueType.TEXT, "Name of Band"}, - {"Songs", ValueType.NUMBER, "Number of new songs"}, - {"Sales", ValueType.NUMBER, "Number of new sales"}, - {"Fans", ValueType.NUMBER, "Number of fans worldwide"} - }, { - {"Year", ValueType.TEXT, "Just year"}, - {"Band", ValueType.TEXT, "Name of Band"}, - {"Songs", ValueType.NUMBER, "Number of new songs"}, - {"Sales", ValueType.NUMBER, "Number of new sales"}, - {"Fans", ValueType.NUMBER, "Number of fans worldwide"} - }, { - {"name", ValueType.TEXT, "Name of employee"}, - {"dept", ValueType.TEXT, "Department"}, - {"lunchTime", ValueType.TIMEOFDAY, "Lunch hour"}, - {"salary", ValueType.NUMBER, "Salary"}, - {"hireDate", ValueType.DATE, "Date commencing employment"}, - {"age", ValueType.NUMBER, "Age"}, - {"isSenior", ValueType.BOOLEAN, "Is the employee senior?"}, - {"seniorityStartTime", ValueType.DATETIME, "Seniority start time"} - } - }; - - private static final String[][][] ROW_DATA = - { - { - {"aaa", "222", "true", "222"}, - {"ccc", "111", "true", "222"}, - {"bbb", "333", "false", "222"}, - {"ddd", "222", "false", "1234"}, - {"eee", "1234", "true", "1234"}, - {"eee", "1234", "false", "1234"}, - {"bbb", "222", "false", "1234"} - }, { - {"1994", "Contraband", "2", "4", "3000"}, - {"1994", "Contraband", "2", "4", "300"}, - {"1994", "Contraband", "4", "4", "3300"}, - {"1994", "Contraband", "4", "4", "500"}, - {"1994", "Contraband", "2", "4", "3600"}, - {"1994", "Contraband", "2", "4", "3400"}, - {"1994", "Youthanasia", "2", "4", "3200"}, - {"1994", "Youthanasia", "2", "4", "10000"}, - {"1994", "Youthanasia", "2", "4", "400"}, - {"1994", "Youthanasia", "4", "4", "20"}, - {"1994", "Youthanasia", "2", "4", "340"}, - {"1994", "Youthanasia", "2", "4", "3060"}, - {"1994", "Youthanasia", "2", "4", "334"}, - {"1994", "Youthanasia", "2", "4", "360"}, - {"1994", "Youthanasia", "2", "4", "3800"}, - {"1996", "Contraband", "2", "4", "3099"}, - {"1996", "Contraband", "2", "4", "390"}, - {"1996", "Contraband", "2", "4", "36700"}, - {"1996", "Contraband", "2", "4", "3230"}, - {"1996", "Contraband", "2", "4", "304"}, - {"1996", "Contraband", "2", "4", "30540"}, - {"1996", "Contraband", "2", "46", "120"}, - {"1996", "Youthanasia", "2", "4", "40"}, - {"1996", "Youthanasia", "2", "4", "7"}, - {"1996", "Youthanasia", "2", "4", "3000"}, - {"1996", "Youthanasia", "4", "4", "3500"}, - {"1996", "Youthanasia", "4", "4", "3000"}, - {"1996", "Youthanasia", "2", "4", "320"}, - {"1996", "Youthanasia", "2", "4", "3000"}, - {"1996", "Youthanasia", "2", "4", "370"}, - {"2003", "Collection", "2", "5", "3000"}, - {"2003", "Collection", "2", "4", "370"}, - {"2003", "Collection", "2", "4", "3000"}, - {"2003", "Collection", "2", "8", "33"}, - {"2003", "Collection", "2", "4", "3000"}, - {"2003", "Collection", "2", "4", "800"}, - {"2003", "Collection", "2", "4", "3000"}, - {"2003", "Collection", "2", "4", "660"}, - {"2003", "Collection", "2", "4", "3000"}, - {"2003", "Collection", "2", "4", "456"}, - {"2003", "Collection", "2", "4", "3000"}, - {"2003", "Collection", "2", "4", "3987"}, - {"2003", "Collection", "2", "4", "3000"}, - {"2003", "Collection", "2", "6", "3440"}, - {"2003", "Collection", "2", "4", "3000"} - }, { - {"1994", "Contraband", "2", "4", "100"}, - {"1994", "Contraband", null, "0", null}, - {"2003", "Collection", "2", null, null}, - }, { - {"John", "Eng", "12:00:00", "1000", "2004-09-08", "35", "true", "2007-12-02 15:56:00"}, - {"Dave", "Eng", "12:00:00", "500", "2005-10-10", "27", "false", null}, - {"Sally", "Eng", "13:00:00", "600", "2005-10-10", "30", "false", null}, - {"Ben", "Sales", "12:00:00", "400", "2002-10-10", "32", "true", "2005-03-19 12:30:00"}, - {"Dana", "Sales", "12:00:00", "350", "2004-09-08", "25", "false", null}, - {"Mike", "Marketing", "13:00:00", "800", "2005-01-10", "24", "true", "2007-12-30 14:40:00"} - } - }; - - private static DataTable[] dataTables; - - /** - * Static constructor to initialize the TableDescriptions and DataTables - */ - static { - if (columnData.length != ROW_DATA.length) { - throw new RuntimeException("Cannot happen. Fix tests."); - } - dataTables = new DataTable[ROW_DATA.length]; - for (int i = 0; i < columnData.length; i++) { - dataTables[i] = new DataTable(); - for (int j = 0; j < columnData[i].length; j++) { - if (columnData[i][j].length != 3) { - throw new RuntimeException("Cannot happen. Fix tests."); - } - String id = (String) columnData[i][j][0]; - ValueType type = (ValueType) columnData[i][j][1]; - String label = (String) columnData[i][j][2]; - ColumnDescription colDesc = new ColumnDescription(id, type, label); - dataTables[i].addColumn(colDesc); - } - } - - for (int i = 0; i < ROW_DATA.length; i++) { - buildTable(dataTables[i], ROW_DATA[i]); - } - } - - public static DataTable getData(int tableNum) { - return dataTables[tableNum].clone(); - } - - public static DataTable getRandomDataTable(int tableNum, int numRows, - long randomSeed) { - random = new Random(randomSeed); - DataTable res = new DataTable(); - res.addColumns(dataTables[tableNum].getColumnDescriptions()); - res = res.clone(); // Clones the column descriptions. - try { - for (int i = 0; i < numRows; i++) { - TableRow row = new TableRow(); - for (ColumnDescription colDesc : res.getColumnDescriptions()) { - Value value = toRandomValue(colDesc.getType()); - row.addCell(new TableCell(value)); - } - res.addRow(row); - } - } catch (TypeMismatchException e) { - // Should not happen, as we control the types. - } - return res; - } - - /** - * Converts a string to a value. - * - * @param content The content. - * @param type The column Type. - * - * @return A value. - */ - public static Value toValue (String content, ValueType type){ - if (content == null) { - return Value.getNullValueFromValueType(type); - } - Value value; - switch (type) { - case NUMBER: - return new NumberValue(Double.parseDouble(content)); - case BOOLEAN: - return BooleanValue.getInstance(Boolean.parseBoolean(content)); - case TEXT: - return new TextValue(content); - case DATETIME: - String[] mainSplit = content.split(" "); - String[] dateSplit = mainSplit[0].split("-"); - String[] timeSplit = mainSplit[1].split(":"); - int year = Integer.parseInt(dateSplit[0]); - int month = Integer.parseInt(dateSplit[1]); - month--; // normalize 1-12 to 0-11. - int day = Integer.parseInt(dateSplit[2]); - int hour = Integer.parseInt(timeSplit[0]); - int minute = Integer.parseInt(timeSplit[1]); - int second; - int milli = 0; - if (timeSplit[2].contains(".")) { - String[] secondMilliSplit = timeSplit[2].split("\\."); - second = Integer.parseInt(secondMilliSplit[0]); - milli = Integer.parseInt(secondMilliSplit[1]); - } else { - second = Integer.parseInt(timeSplit[2]); - } - return new DateTimeValue(year, month, day, hour, minute, second, milli); - case DATE: - String[] split = content.split("-"); - year = Integer.parseInt(split[0]); - month = Integer.parseInt(split[1]); - month--; // normalize 1-12 to 0-11. - day = Integer.parseInt(split[2]); - return new DateValue(year, month, day); - case TIMEOFDAY: - split = content.split(":"); - hour = Integer.parseInt(split[0]); - minute = Integer.parseInt(split[1]); - if (split[2].contains(".")) { - String[] secondMilliSplit = split[2].split("\\."); - second = Integer.parseInt(secondMilliSplit[0]); - milli = Integer.parseInt(secondMilliSplit[1]); - return new TimeOfDayValue(hour, minute, second, milli); - } else { - second = Integer.parseInt(split[2]); - return new TimeOfDayValue(hour, minute, second); - } - - default: - throw new RuntimeException("We do not support other types " - + "for now"); - } - } - - public static Value toRandomValue(ValueType type) { - if (random.nextInt(10) == 0) { - return Value.getNullValueFromValueType(type); - } - switch (type) { - case NUMBER: - return new NumberValue(random.nextDouble() * 10000 * - (random.nextInt(2) * 2 - 1)); - case BOOLEAN: - return BooleanValue.getInstance(random.nextBoolean()); - case TEXT: - StringBuilder builder = new StringBuilder(); - int numLetters = random.nextInt(100) + 1; - for (int i = 0; i < numLetters; i++) { - builder.append('a' + random.nextInt(26)); - } - return new TextValue(builder.toString()); - case DATETIME: - return new DateTimeValue(random.nextInt(200) + 1900, random.nextInt(12), - random.nextInt(28) + 1, random.nextInt(24), random.nextInt(60), - random.nextInt(60), random.nextInt(999)); - case DATE: - return new DateValue(random.nextInt(200) + 1900, random.nextInt(12), - random.nextInt(28) + 1); - case TIMEOFDAY: - return new TimeOfDayValue(random.nextInt(24), random.nextInt(60), - random.nextInt(60), random.nextInt(999)); - default: - throw new RuntimeException("Invalid type"); - } - } - - /** - * Adds all content to the query result. - * - * @param res The query result. - * @param content A double string array for the content of the table. - */ - private static void buildTable (DataTable res, String[][] content) { - List descriptions = res.getColumnDescriptions(); - try { - for (String[] curRow : content) { - res.addRow(createNewTableRow(curRow, descriptions)); - } - } catch (TypeMismatchException e) { - // Shouldn't happen, as we control the types. - } - } - - /** - * Constructs a table row according to string input. - * - * @param content A string array containing the content. - * @param descriptors The column descriptors. - * - * @return A table row. - */ - public static TableRow createNewTableRow(String[] content, - List descriptors) { - TableRow result = new TableRow(); - for (int i = 0; i < content.length; i++) { - Value value = toValue(content[i], descriptors.get(i).getType()); - result.addCell(new TableCell(value)); - } - return result; - } - - public static String[][] queryResultToStringMatrix(DataTable table) { - int numRows = table.getNumberOfRows(); - int numCols = table.getNumberOfColumns(); - String[][] result = new String[numRows][]; - for (int i = 0; i < numRows; i++) { - result[i] = new String[numCols]; - for (int j = 0; j < numCols; j++) { - result[i][j] = table.getRows().get(i).getCells().get(j).toString(); - } - } - return result; - } -} diff --git a/src/test/java/com/google/visualization/datasource/query/parser/QueryBuilderTest.java b/src/test/java/com/google/visualization/datasource/query/parser/QueryBuilderTest.java deleted file mode 100644 index 32eb808..0000000 --- a/src/test/java/com/google/visualization/datasource/query/parser/QueryBuilderTest.java +++ /dev/null @@ -1,1112 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query.parser; - -import com.google.common.collect.Lists; -import com.google.common.collect.Sets; -import com.google.visualization.datasource.base.InvalidQueryException; -import com.google.visualization.datasource.datatable.value.BooleanValue; -import com.google.visualization.datasource.datatable.value.DateTimeValue; -import com.google.visualization.datasource.datatable.value.DateValue; -import com.google.visualization.datasource.datatable.value.NumberValue; -import com.google.visualization.datasource.datatable.value.TextValue; -import com.google.visualization.datasource.datatable.value.TimeOfDayValue; -import com.google.visualization.datasource.datatable.value.Value; -import com.google.visualization.datasource.datatable.value.ValueType; -import com.google.visualization.datasource.query.AbstractColumn; -import com.google.visualization.datasource.query.AggregationColumn; -import com.google.visualization.datasource.query.AggregationType; -import com.google.visualization.datasource.query.ColumnColumnFilter; -import com.google.visualization.datasource.query.ColumnIsNullFilter; -import com.google.visualization.datasource.query.ColumnSort; -import com.google.visualization.datasource.query.ColumnValueFilter; -import com.google.visualization.datasource.query.ComparisonFilter; -import com.google.visualization.datasource.query.CompoundFilter; -import com.google.visualization.datasource.query.NegationFilter; -import com.google.visualization.datasource.query.Query; -import com.google.visualization.datasource.query.QueryFilter; -import com.google.visualization.datasource.query.QueryFormat; -import com.google.visualization.datasource.query.QueryGroup; -import com.google.visualization.datasource.query.QueryLabels; -import com.google.visualization.datasource.query.QueryOptions; -import com.google.visualization.datasource.query.QueryPivot; -import com.google.visualization.datasource.query.QuerySelection; -import com.google.visualization.datasource.query.QuerySort; -import com.google.visualization.datasource.query.ScalarFunctionColumn; -import com.google.visualization.datasource.query.SimpleColumn; -import com.google.visualization.datasource.query.SortOrder; -import com.google.visualization.datasource.query.scalarfunction.Difference; -import com.google.visualization.datasource.query.scalarfunction.Lower; -import com.google.visualization.datasource.query.scalarfunction.Product; -import com.google.visualization.datasource.query.scalarfunction.Quotient; -import com.google.visualization.datasource.query.scalarfunction.Sum; -import com.google.visualization.datasource.query.scalarfunction.TimeComponentExtractor; -import com.google.visualization.datasource.query.scalarfunction.Upper; - -import junit.framework.TestCase; - -import java.util.List; -import java.util.Set; - -/** - * Tests for QueryBuilder. - * - * @author Yonatan B.Y. - */ -public class QueryBuilderTest extends TestCase { - - @Override - public void setUp() throws Exception { - super.setUp(); - } - - @Override - public void tearDown() throws Exception { - super.tearDown(); - } - - public void testSelect() throws Exception { - Query query = QueryBuilder.getInstance().parseQuery("SeLeCt c1,c2 , c3 "); - - assertEquals(null, query.getSort()); - QuerySelection selection = query.getSelection(); - assertEquals(Lists.newArrayList(new SimpleColumn("c1"), - new SimpleColumn("c2"), new SimpleColumn("c3")), - selection.getColumns()); - } - - public void testSelectAll() throws Exception { - Query query = QueryBuilder.getInstance().parseQuery("Select *"); - assertTrue(query.isEmpty()); - } - - public void testUnicodeInput() throws Exception { - // Select aleph, bet, gimmel. (Hebrew). - Query query = QueryBuilder.getInstance().parseQuery("SELECT `\u05d0`,`\u05d1`,`\u05d2` "); - - assertEquals(null, query.getSort()); - QuerySelection selection = query.getSelection(); - assertEquals(Lists.newArrayList(new SimpleColumn("\u05d0"), - new SimpleColumn("\u05d1"), new SimpleColumn("\u05d2")), - selection.getColumns()); - - query = QueryBuilder.getInstance().parseQuery("SELECT * WHERE c='\u311e'"); - QueryFilter filter = query.getFilter(); - assertTrue(filter instanceof ColumnValueFilter); - ColumnValueFilter cvf = (ColumnValueFilter) filter; - assertEquals("c", cvf.getColumn().getId()); - Value v = cvf.getValue(); - assertEquals(ValueType.TEXT, v.getType()); - assertEquals("\u311e", ((TextValue) cvf.getValue()).getValue()); - } - - public void testOrderBy() throws Exception { - Query query = QueryBuilder.getInstance().parseQuery( - "OrDeR bY c1,c2 desc , c3 ASC"); - assertEquals(null, query.getSelection()); - QuerySort sort = query.getSort(); - List columnSorts = sort.getSortColumns(); - assertEquals(3, columnSorts.size()); - assertEquals(new SimpleColumn("c1"), columnSorts.get(0).getColumn()); - assertEquals(new SimpleColumn("c2"), columnSorts.get(1).getColumn()); - assertEquals(new SimpleColumn("c3"), columnSorts.get(2).getColumn()); - assertEquals(SortOrder.ASCENDING, columnSorts.get(0).getOrder()); - assertEquals(SortOrder.DESCENDING, columnSorts.get(1).getOrder()); - assertEquals(SortOrder.ASCENDING, columnSorts.get(2).getOrder()); - } - - public void testSelectAndOrderBy() throws Exception { - Query query = QueryBuilder.getInstance().parseQuery( - "SELect c1 , c2 , c3 ORDER BY c4 DESC"); - QuerySelection selection = query.getSelection(); - assertEquals(Lists.newArrayList(new SimpleColumn("c1"), - new SimpleColumn("c2"), new SimpleColumn("c3")), - selection.getColumns()); - QuerySort sort = query.getSort(); - List columnSorts = sort.getSortColumns(); - assertEquals(1, columnSorts.size()); - assertEquals(new SimpleColumn("c4"), columnSorts.get(0).getColumn()); - assertEquals(SortOrder.DESCENDING, columnSorts.get(0).getOrder()); - } - - public void testOptions() throws Exception { - Query query = QueryBuilder.getInstance().parseQuery( - " OpTiOnS nO_ValUes "); - - QueryOptions options = query.getOptions(); - assertTrue(options.isNoValues()); - assertFalse(options.isNoFormat()); - } - - public void testGroupingAndPivoting() throws Exception { - Query query = QueryBuilder.getInstance().parseQuery( - " SELECT a, min(c1), b, avg(c2) group by a,b pivot c,d"); - QuerySelection selection = query.getSelection(); - QueryGroup group = query.getGroup(); - QueryPivot pivot = query.getPivot(); - assertEquals(Lists.newArrayList(new SimpleColumn("a"), - new AggregationColumn(new SimpleColumn("c1"), AggregationType.MIN), - new SimpleColumn("b"), - new AggregationColumn(new SimpleColumn("c2"), AggregationType.AVG)), - selection.getColumns()); - assertEquals(Lists.newArrayList("a", "b"), group.getColumnIds()); - assertEquals(Lists.newArrayList("c", "d"), pivot.getColumnIds()); - } - - public void testStrangeAggregations() throws Exception { - Query query = QueryBuilder.getInstance().parseQuery( - " SELECT `a, b`, avg, min(min), max(max) group by `a, b`, avg " - + " pivot count"); - QuerySelection selection = query.getSelection(); - QueryGroup group = query.getGroup(); - QueryPivot pivot = query.getPivot(); - assertEquals(Lists.newArrayList(new SimpleColumn("a, b"), - new SimpleColumn("avg"), - new AggregationColumn(new SimpleColumn("min"), AggregationType.MIN), - new AggregationColumn(new SimpleColumn("max"), AggregationType.MAX)), - selection.getColumns()); - assertEquals(Lists.newArrayList("a, b", "avg"), group.getColumnIds()); - assertEquals(Lists.newArrayList("count"), pivot.getColumnIds()); - } - - public void testEmptyQuery() throws Exception { - Query query = QueryBuilder.getInstance().parseQuery(" "); - assertEquals(null, query.getSelection()); - assertEquals(null, query.getSort()); - } - - public void testNullQuery() throws Exception { - Query query = QueryBuilder.getInstance().parseQuery(null); - assertEquals(null, query.getSelection()); - assertEquals(null, query.getSort()); - } - - public void testBadQuery1() throws Exception { - try { - QueryBuilder.getInstance().parseQuery("order by c1 asc desc"); - fail("Should have thrown an exception."); - } catch (InvalidQueryException e) { - // Expected behavior. - } - } - - public void testBadQuery2() throws Exception { - try { - QueryBuilder.getInstance().parseQuery("select c1,,c2"); - fail("Should have thrown an exception."); - } catch (InvalidQueryException e) { - // Expected behavior. - } - } - - // LIMIT and OFFSET tests - - public void testValidLimit() throws Exception { - Query query = QueryBuilder.getInstance().parseQuery(" limit 100 "); - assertEquals(100, query.getRowLimit()); - } - - public void testInvalidLimit() throws Exception { - try { - Query query = QueryBuilder.getInstance().parseQuery(" limit 100.5 "); - fail("Should have thrown an exception."); - } catch (InvalidQueryException e) { - // Expected behavior. - } - } - - public void testInvalidLimit2() throws Exception { - try { - Query query = QueryBuilder.getInstance().parseQuery(" limit gaga "); - fail("Should have thrown an exception."); - } catch (InvalidQueryException e) { - // Expected behavior. - } - } - - public void testUnspecifiedLimit() throws Exception { - try { - Query query = QueryBuilder.getInstance().parseQuery(" limit "); - fail("Should have thrown an exception."); - } catch (InvalidQueryException e) { - // Expected behavior. - } - } - - public void testValidOffset() throws Exception { - Query query = QueryBuilder.getInstance().parseQuery(" offset 100 "); - assertEquals(100, query.getRowOffset()); - } - - public void testInvalidOffset() throws Exception { - try { - Query query = QueryBuilder.getInstance().parseQuery(" offset 100.5 "); - fail("Should have thrown an exception."); - } catch (InvalidQueryException e) { - // Expected behavior. - } - } - - public void testInvalidOffset2() throws Exception { - try { - Query query = QueryBuilder.getInstance().parseQuery(" offset gaga "); - fail("Should have thrown an exception."); - } catch (InvalidQueryException e) { - // Expected behavior. - } - } - - public void testUnspecifiedOffset() throws Exception { - try { - Query query = QueryBuilder.getInstance().parseQuery(" offset "); - fail("Should have thrown an exception."); - } catch (InvalidQueryException e) { - // Expected behavior. - } - } - - public void testLimitAndOffset() throws Exception { - Query query = QueryBuilder.getInstance().parseQuery(" limit 100 offset 10 "); - assertEquals(100, query.getRowLimit()); - assertEquals(10, query.getRowOffset()); - } - - public void testReverseLimitAndOffset() throws Exception { - try { - Query query = QueryBuilder.getInstance().parseQuery(" offset 10 limit 10 "); - fail("Should have thrown an exception."); - } catch (InvalidQueryException e) { - // Expected behavior. - } - } - - public void testNegativeLimit() throws Exception { - try { - Query query = QueryBuilder.getInstance().parseQuery(" offset -10 "); - fail("Should have thrown an exception."); - } catch (InvalidQueryException e) { - // Expected behavior. - } - } - - public void testNegativeOffset() throws Exception { - try { - Query query = QueryBuilder.getInstance().parseQuery(" offset -1 "); - fail("Should have thrown an exception."); - } catch (InvalidQueryException e) { - // Expected behavior. - } - } - - // SKIPPING tests - - public void testSkipping() throws Exception { - Query query = QueryBuilder.getInstance().parseQuery(" skipping 10 "); - assertEquals(10, query.getRowSkipping()); - } - - public void testNegativeSkipping() throws Exception { - try { - Query query = QueryBuilder.getInstance().parseQuery(" skipping -1 "); - fail("Should have thrown an exception."); - } catch (InvalidQueryException e) { - // Expected behavior. - } - } - - public void testZeroSkipping() throws Exception { - // Zero value is OK, it means no skipping - Query query = QueryBuilder.getInstance().parseQuery(" skipping 0 "); - assertEquals(0, query.getRowSkipping()); - } - - public void testSkippingLimitAndOffset() throws Exception { - Query query = QueryBuilder.getInstance().parseQuery(" skipping 10 limit 100 offset 10 "); - assertEquals(10, query.getRowSkipping()); - assertEquals(100, query.getRowLimit()); - assertEquals(10, query.getRowOffset()); - } - - public void testUnorderedLimitSkippingAndOffset() throws Exception { - try { - Query query = QueryBuilder.getInstance().parseQuery(" limit 100 skipping 10 offset 10 "); - fail("Should have thrown an exception."); - } - catch (InvalidQueryException e) { - // Expected behavior. - } - } - - // LABEL clause tests - - public void testOneValidLabelWithDoubleQuotes() throws Exception { - Query query = QueryBuilder.getInstance().parseQuery("select c1 label c1 \"Label 1\" "); - QueryLabels labels = query.getLabels(); - assertEquals("Label 1", labels.getLabel(new SimpleColumn("c1"))); - } - - public void testOneValidLabelWithSingleQuote() throws Exception { - Query query = QueryBuilder.getInstance().parseQuery("select c1 label c1 'Label 1' "); - QueryLabels labels = query.getLabels(); - assertEquals("Label 1", labels.getLabel(new SimpleColumn("c1"))); - } - - public void testTwoValidLabels() throws Exception { - Query query = QueryBuilder.getInstance().parseQuery( - "select c1,c2 label c1 'Label 1', c2 'Label 2' "); - QueryLabels labels = query.getLabels(); - assertEquals("Label 1", labels.getLabel(new SimpleColumn("c1"))); - assertEquals("Label 2", labels.getLabel(new SimpleColumn("c2"))); - } - - public void testInvalidLabel() throws Exception { - try { - Query query = QueryBuilder.getInstance().parseQuery("select c1 label c1 gaga "); - fail("Should have thrown an exception."); - } catch (InvalidQueryException e) { - // Expected behavior. - } - } - - public void testInvalidEmptyLabel() throws Exception { - try { - Query query = QueryBuilder.getInstance().parseQuery("select c1 label c1 "); - fail("Should have thrown an exception."); - } catch (InvalidQueryException e) { - // Expected behavior. - } - } - - public void testDuplicateLabelColumn() throws Exception { - try { - Query query = QueryBuilder.getInstance().parseQuery("select c1 label c1 'gaga', c1 'gugu' "); - fail("Should have thrown an exception."); - } catch (InvalidQueryException e) { - // Expected behavior. - } - } - - public void testInvalidTwoLabelsNoComma() throws Exception { - try { - Query query = QueryBuilder.getInstance().parseQuery( - "select c1, c2 label c1,c2 'label 1' c2 'label 2' "); - fail("Should have thrown an exception."); - } catch (InvalidQueryException e) { - // Expected behavior. - } - } - - // FORMAT clause tests - - public void testOneValidFormatWithDoubleQuotes() throws Exception { - Query query = QueryBuilder.getInstance().parseQuery("select c1 Format c1 \"Format 1\" "); - QueryFormat formats = query.getUserFormatOptions(); - assertEquals("Format 1", formats.getPattern(new SimpleColumn("c1"))); - } - - public void testOneValidFormatWithSingleQuote() throws Exception { - Query query = QueryBuilder.getInstance().parseQuery("select c1 Format c1 'Format 1' "); - QueryFormat formats = query.getUserFormatOptions(); - assertEquals("Format 1", formats.getPattern(new SimpleColumn("c1"))); - } - - public void testTwoValidFormats() throws Exception { - Query query = QueryBuilder.getInstance().parseQuery( - "select c1,c2 Format c1 'Format 1', c2 'Format 2' "); - QueryFormat formats = query.getUserFormatOptions(); - assertEquals("Format 1", formats.getPattern(new SimpleColumn("c1"))); - assertEquals("Format 2", formats.getPattern(new SimpleColumn("c2"))); - } - - public void testInvalidFormat() throws Exception { - try { - Query query = QueryBuilder.getInstance().parseQuery("select c1 Format c1 gaga "); - fail("Should have thrown an exception."); - } catch (InvalidQueryException e) { - // Expected behavior. - } - } - - public void testInvalidEmptyFormat() throws Exception { - try { - Query query = QueryBuilder.getInstance().parseQuery("select c1 Format c1 "); - fail("Should have thrown an exception."); - } catch (InvalidQueryException e) { - // Expected behavior. - } - } - - public void testInvalidTwoFormatsNoComma() throws Exception { - try { - Query query = QueryBuilder.getInstance().parseQuery( - "select c1,c2 Format c1 'Format 1' c2 'Format 2' "); - fail("Should have thrown an exception."); - } catch (InvalidQueryException e) { - // Expected behavior. - } - } - - public void testDuplicateFormatColumn() throws Exception { - try { - Query query = QueryBuilder.getInstance().parseQuery("select c1 format c1 'gaga', c1 'gugu' "); - fail("Should have thrown an exception."); - } catch (InvalidQueryException e) { - // Expected behavior. - } - } - - // WHERE clause tests: - - public void testColumnColumnFilter() throws Exception { - Query query = QueryBuilder.getInstance().parseQuery(" WHERE C1 > `c 2`"); - QueryFilter filter = query.getFilter(); - assertTrue(filter instanceof ColumnColumnFilter); - ColumnColumnFilter f = (ColumnColumnFilter) filter; - assertEquals("C1", f.getFirstColumn().getId()); - assertEquals("c 2", f.getSecondColumn().getId()); - assertEquals(ComparisonFilter.Operator.GT, f.getOperator()); - } - - public void testColumnValueFilterWithNumber() throws Exception { - Query query = QueryBuilder.getInstance().parseQuery(" WHERE c1 <= 7.55"); - QueryFilter filter = query.getFilter(); - assertTrue(filter instanceof ColumnValueFilter); - ColumnValueFilter f = (ColumnValueFilter) filter; - assertEquals("c1", f.getColumn().getId()); - Value val = f.getValue(); - assertTrue(val instanceof NumberValue); - NumberValue v = (NumberValue) val; - assertEquals(7.55, v.getValue()); - assertEquals(ComparisonFilter.Operator.LE, f.getOperator()); - } - - public void testColumnValueFilterWithText1() throws Exception { - Query query = QueryBuilder.getInstance().parseQuery(" WHERE `selEct` = 'baba'"); - QueryFilter filter = query.getFilter(); - assertTrue(filter instanceof ColumnValueFilter); - ColumnValueFilter f = (ColumnValueFilter) filter; - assertEquals("selEct", f.getColumn().getId()); - Value val = f.getValue(); - assertTrue(val instanceof TextValue); - TextValue v = (TextValue) val; - assertEquals("baba", v.toString()); - assertEquals(ComparisonFilter.Operator.EQ, f.getOperator()); - } - - public void testColumnValueFilterWithText2() throws Exception { - Query query = QueryBuilder.getInstance().parseQuery(" WHERE MiN <> \"baba\""); - QueryFilter filter = query.getFilter(); - assertTrue(filter instanceof ColumnValueFilter); - ColumnValueFilter f = (ColumnValueFilter) filter; - assertEquals("MiN", f.getColumn().getId()); - Value val = f.getValue(); - assertTrue(val instanceof TextValue); - TextValue v = (TextValue) val; - assertEquals("baba", v.toString()); - assertEquals(ComparisonFilter.Operator.NE, f.getOperator()); - } - - public void testColumnValueFilterWithBoolean1() throws Exception { - Query query = QueryBuilder.getInstance().parseQuery(" WHERE c1 != trUe"); - QueryFilter filter = query.getFilter(); - assertTrue(filter instanceof ColumnValueFilter); - ColumnValueFilter f = (ColumnValueFilter) filter; - assertEquals("c1", f.getColumn().getId()); - Value val = f.getValue(); - assertTrue(val instanceof BooleanValue); - BooleanValue v = (BooleanValue) val; - assertEquals(true, v.getValue()); - assertEquals(ComparisonFilter.Operator.NE, f.getOperator()); - } - - public void testColumnValueFilterWithBoolean2() throws Exception { - Query query = QueryBuilder.getInstance().parseQuery(" WHERE `min` >= FalSe"); - QueryFilter filter = query.getFilter(); - assertTrue(filter instanceof ColumnValueFilter); - ColumnValueFilter f = (ColumnValueFilter) filter; - assertEquals("min", f.getColumn().getId()); - Value val = f.getValue(); - assertTrue(val instanceof BooleanValue); - BooleanValue v = (BooleanValue) val; - assertEquals(false, v.getValue()); - assertEquals(ComparisonFilter.Operator.GE, f.getOperator()); - assertEquals(false, f.isComparisonOrderReversed()); - } - - public void testReverseColumnValueFilter1() throws Exception { - Query query = QueryBuilder.getInstance().parseQuery(" WHERE -.3 < `ba ba`"); - QueryFilter filter = query.getFilter(); - assertTrue(filter instanceof ColumnValueFilter); - ColumnValueFilter f = (ColumnValueFilter) filter; - assertEquals("ba ba", f.getColumn().getId()); - Value val = f.getValue(); - assertTrue(val instanceof NumberValue); - NumberValue v = (NumberValue) val; - assertEquals(-0.3, v.getValue()); - assertEquals(ComparisonFilter.Operator.LT, f.getOperator()); - assertEquals(true, f.isComparisonOrderReversed()); - } - - public void testReverseColumnValueFilter2() throws Exception { - Query query = QueryBuilder.getInstance().parseQuery(" WHERE 'select' > count "); - QueryFilter filter = query.getFilter(); - assertTrue(filter instanceof ColumnValueFilter); - ColumnValueFilter f = (ColumnValueFilter) filter; - assertEquals("count", f.getColumn().getId()); - Value val = f.getValue(); - assertTrue(val instanceof TextValue); - TextValue v = (TextValue) val; - assertEquals("select", v.toString()); - assertEquals(ComparisonFilter.Operator.GT, f.getOperator()); - assertEquals(true, f.isComparisonOrderReversed()); - } - - public void testReverseColumnValueFilter3() throws Exception { - Query query = QueryBuilder.getInstance().parseQuery(" WHERE false <> `false` "); - QueryFilter filter = query.getFilter(); - assertTrue(filter instanceof ColumnValueFilter); - ColumnValueFilter f = (ColumnValueFilter) filter; - assertEquals("false", f.getColumn().getId()); - Value val = f.getValue(); - assertTrue(val instanceof BooleanValue); - BooleanValue v = (BooleanValue) val; - assertEquals(false, v.getValue()); - assertEquals(ComparisonFilter.Operator.NE, f.getOperator()); - assertEquals(true, f.isComparisonOrderReversed()); - } - - public void testNegationFilter() throws Exception { - Query query = QueryBuilder.getInstance().parseQuery(" WHERE not (c1 < c2) "); - QueryFilter filter = query.getFilter(); - assertTrue(filter instanceof NegationFilter); - NegationFilter f = (NegationFilter) filter; - QueryFilter subFilter = f.getSubFilter(); - assertTrue(subFilter instanceof ColumnColumnFilter); - ColumnColumnFilter ccf = (ColumnColumnFilter) subFilter; - assertEquals("c1", ccf.getFirstColumn().getId()); - assertEquals("c2", ccf.getSecondColumn().getId()); - assertEquals(ComparisonFilter.Operator.LT, ccf.getOperator()); - } - - public void testAndFilter() throws Exception { - Query query = QueryBuilder.getInstance().parseQuery( - " WHERE c1 < c2 AND 4 >= `WHERE` aNd (`c1` < `c 3`)"); - QueryFilter filter = query.getFilter(); - assertTrue(filter instanceof CompoundFilter); - CompoundFilter f = (CompoundFilter) filter; - assertEquals(CompoundFilter.LogicalOperator.AND, f.getOperator()); - List subFilters = f.getSubFilters(); - assertEquals(3, subFilters.size()); - QueryFilter f1 = subFilters.get(0); - QueryFilter f2 = subFilters.get(1); - QueryFilter f3 = subFilters.get(2); - assertTrue(f1 instanceof ColumnColumnFilter); - assertTrue(f2 instanceof ColumnValueFilter); - assertTrue(f3 instanceof ColumnColumnFilter); - Set allColumnIds = f.getAllColumnIds(); - assertEquals(Sets.newHashSet("c1", "c2", "c 3", "WHERE"), allColumnIds); - } - - public void testMultipleAndAssociativity() throws Exception { - Query query = QueryBuilder.getInstance().parseQuery( - " WHERE `Date` > '2008-06-01' and `RoleId` != 47 and " - + "`RoleId` != 6 and `RoleId` != 8 and `RoleId` != 2"); - QueryFilter filter = query.getFilter(); - assertTrue(filter instanceof CompoundFilter); - CompoundFilter f = (CompoundFilter) filter; - assertEquals(CompoundFilter.LogicalOperator.AND, f.getOperator()); - List subFilters = f.getSubFilters(); - ColumnValueFilter[] filters = new ColumnValueFilter[5]; - assertEquals(5, subFilters.size()); - for (int i = 0; i < 5; i++) { - filters[i] = (ColumnValueFilter) subFilters.get(i); - } - assertEquals("Date", filters[0].getColumn().getId()); - assertEquals("RoleId", filters[1].getColumn().getId()); - assertEquals("RoleId", filters[2].getColumn().getId()); - assertEquals("RoleId", filters[3].getColumn().getId()); - assertEquals("RoleId", filters[4].getColumn().getId()); - - assertEquals(ComparisonFilter.Operator.GT, filters[0].getOperator()); - assertEquals(ComparisonFilter.Operator.NE, filters[1].getOperator()); - assertEquals(ComparisonFilter.Operator.NE, filters[2].getOperator()); - assertEquals(ComparisonFilter.Operator.NE, filters[3].getOperator()); - assertEquals(ComparisonFilter.Operator.NE, filters[4].getOperator()); - - assertEquals(new TextValue("2008-06-01"), filters[0].getValue()); - assertEquals(new NumberValue(47), filters[1].getValue()); - assertEquals(new NumberValue(6), filters[2].getValue()); - assertEquals(new NumberValue(8), filters[3].getValue()); - assertEquals(new NumberValue(2), filters[4].getValue()); - - } - - public void testOrFilterWithExtraneousParantheses() throws Exception { - Query query = QueryBuilder.getInstance().parseQuery( - " WHERE (((c1 < c2)) OR 4 >= `WHERE` OR (`c1` < `c 3`))"); - QueryFilter filter = query.getFilter(); - assertTrue(filter instanceof CompoundFilter); - CompoundFilter f = (CompoundFilter) filter; - assertEquals(CompoundFilter.LogicalOperator.OR, f.getOperator()); - List subFilters = f.getSubFilters(); - assertEquals(3, subFilters.size()); - QueryFilter f1 = subFilters.get(0); - QueryFilter f2 = subFilters.get(1); - QueryFilter f3 = subFilters.get(2); - assertTrue(f1 instanceof ColumnColumnFilter); - assertTrue(f2 instanceof ColumnValueFilter); - assertTrue(f3 instanceof ColumnColumnFilter); - Set allColumnIds = f.getAllColumnIds(); - assertEquals(Sets.newHashSet("c1", "c2", "c 3", "WHERE"), allColumnIds); - } - - public void testReallyComplexFilter() throws Exception { - Query query = QueryBuilder.getInstance().parseQuery( - "SELECT c1,c2 WHERE (NOT ((c1 < c2) OR (NOT (c3 < " + - "c4))) AND (NOT ((NOT (NOT (c5 < c6))) OR (c7 < c8))) AND " + - "((c9 < c10) AND ((c11 < c12) OR ((c13 < c14) AND (c15 < c16)))))"); - QueryFilter filter = query.getFilter(); - assertTrue(filter instanceof CompoundFilter); - CompoundFilter f = (CompoundFilter) filter; - assertEquals(CompoundFilter.LogicalOperator.AND, f.getOperator()); - List subFilters = f.getSubFilters(); - assertEquals(3, subFilters.size()); - QueryFilter f1 = subFilters.get(0); - QueryFilter f2 = subFilters.get(1); - QueryFilter f3 = subFilters.get(2); - - // f1: (!((c1 < c2) || (!(c3 < c4))) - assertTrue(f1 instanceof NegationFilter); - NegationFilter nf = (NegationFilter) f1; - QueryFilter subFilter = nf.getSubFilter(); - assertTrue(subFilter instanceof CompoundFilter); - CompoundFilter cf = (CompoundFilter) subFilter; - assertEquals(CompoundFilter.LogicalOperator.OR, cf.getOperator()); - subFilters = cf.getSubFilters(); - assertEquals(2, subFilters.size()); - assertTrue(subFilters.get(0) instanceof ColumnColumnFilter); - assertEquals(Sets.newHashSet("c1", "c2"), - subFilters.get(0).getAllColumnIds()); - assertTrue(subFilters.get(1) instanceof NegationFilter); - nf = (NegationFilter) subFilters.get(1); - assertTrue(nf.getSubFilter() instanceof ColumnColumnFilter); - assertEquals(Sets.newHashSet("c3", "c4"), - nf.getSubFilter().getAllColumnIds()); - - //f2: (!((!(!(c5 < c6))) || (c7 < c8))) - assertTrue(f2 instanceof NegationFilter); - nf = (NegationFilter) f2; - assertTrue(nf.getSubFilter() instanceof CompoundFilter); - cf = (CompoundFilter) nf.getSubFilter(); - assertEquals(CompoundFilter.LogicalOperator.OR, cf.getOperator()); - subFilters = cf.getSubFilters(); - assertEquals(2, subFilters.size()); - assertTrue(subFilters.get(0) instanceof NegationFilter); - assertTrue(subFilters.get(1) instanceof ColumnColumnFilter); - assertEquals(Sets.newHashSet("c7", "c8"), - subFilters.get(1).getAllColumnIds()); - nf = (NegationFilter) subFilters.get(0); - assertTrue(nf.getSubFilter() instanceof NegationFilter); - nf = (NegationFilter) nf.getSubFilter(); - assertTrue(nf.getSubFilter() instanceof ColumnColumnFilter); - assertEquals(Sets.newHashSet("c5", "c6"), - nf.getSubFilter().getAllColumnIds()); - - //f3: ((c9 < c10) && ((c11 < c12)||((c13 < c14)&&(c15 < c16)))) - assertTrue(f3 instanceof CompoundFilter); - cf = (CompoundFilter) f3; - assertEquals(CompoundFilter.LogicalOperator.AND, cf.getOperator()); - subFilters = cf.getSubFilters(); - assertEquals(2, subFilters.size()); - assertTrue(subFilters.get(0) instanceof ColumnColumnFilter); - assertEquals(Sets.newHashSet("c9", "c10"), - subFilters.get(0).getAllColumnIds()); - assertTrue(subFilters.get(1) instanceof CompoundFilter); - cf = (CompoundFilter) subFilters.get(1); - assertEquals(CompoundFilter.LogicalOperator.OR, cf.getOperator()); - subFilters = cf.getSubFilters(); - assertEquals(2, subFilters.size()); - assertTrue(subFilters.get(0) instanceof ColumnColumnFilter); - assertEquals(Sets.newHashSet("c11", "c12"), - subFilters.get(0).getAllColumnIds()); - assertTrue(subFilters.get(1) instanceof CompoundFilter); - cf = (CompoundFilter) subFilters.get(1); - subFilters = cf.getSubFilters(); - assertEquals(2, subFilters.size()); - assertTrue(subFilters.get(0) instanceof ColumnColumnFilter); - assertTrue(subFilters.get(1) instanceof ColumnColumnFilter); - assertEquals(Sets.newHashSet("c13", "c14"), - subFilters.get(0).getAllColumnIds()); - assertEquals(Sets.newHashSet("c15", "c16"), - subFilters.get(1).getAllColumnIds()); - - } - - public void testPrecedence() throws Exception { - Query query = QueryBuilder.getInstance().parseQuery( - "SELECT c1,c2 WHERE NOT c1 < c2 OR NOT c3 < " + - "c4 AND NOT c5 < c6 OR c7 < c8 AND " + - "c9 < c10 AND c11 < c12 OR c13 < c14 AND c15 < c16"); - // interpretation: (!(c1 < c2)) or - // ((not (c3 < c4)) and (not (c5 < c6))) or - // ((c7 < c8) and (c9 < c10) and (c11 < c12)) or - // ((c13 < c14) and (c15 < c16)) - QueryFilter filter = query.getFilter(); - assertTrue(filter instanceof CompoundFilter); - CompoundFilter f = (CompoundFilter) filter; - assertEquals(CompoundFilter.LogicalOperator.OR, f.getOperator()); - List subFilters = f.getSubFilters(); - assertEquals(4, subFilters.size()); - QueryFilter f1 = subFilters.get(0); - QueryFilter f2 = subFilters.get(1); - QueryFilter f3 = subFilters.get(2); - QueryFilter f4 = subFilters.get(3); - - // f1: (!(c1 < c2)) - assertTrue(f1 instanceof NegationFilter); - NegationFilter nf = (NegationFilter) f1; - QueryFilter subFilter = nf.getSubFilter(); - assertTrue(subFilter instanceof ColumnColumnFilter); - assertEquals(Sets.newHashSet("c1", "c2"), subFilter.getAllColumnIds()); - - // f2: ((!(c3newArrayList( - new AggregationColumn(new SimpleColumn("salary"), AggregationType.MIN), - new AggregationColumn(new SimpleColumn("height"), AggregationType.AVG)), - query.getSelection().getColumns()); - assertEquals(Lists.newArrayList("dept", "subdept"), - query.getGroup().getColumnIds()); - assertEquals(Lists.newArrayList("year", "month"), - query.getPivot().getColumnIds()); - } - - public void testDateLiterals() throws Exception { - Query query = QueryBuilder.getInstance().parseQuery("WHERE c1 > DATE '2006-08-23'"); - assertEquals(new DateValue(2006, 7, 23), - ((ColumnValueFilter) query.getFilter()).getValue()); - query = QueryBuilder.getInstance().parseQuery( - "WHERE c1 = DaTeTiMe '2007-01-30 15:33:22.432'"); - assertEquals(new DateTimeValue(2007, 0, 30, 15, 33, 22, 432), - ((ColumnValueFilter) query.getFilter()).getValue()); - query = QueryBuilder.getInstance().parseQuery( - "WHERE c1 = timesTaMP '2007-01-30 15:33:22.432'"); - assertEquals(new DateTimeValue(2007, 0, 30, 15, 33, 22, 432), - ((ColumnValueFilter) query.getFilter()).getValue()); - query = QueryBuilder.getInstance().parseQuery("WHERE c1 != TimeOfDay '15:33:22'"); - assertEquals(new TimeOfDayValue(15, 33, 22), - ((ColumnValueFilter) query.getFilter()).getValue()); - } - - public void testBadDateLiteral() throws Exception { - try { - QueryBuilder.getInstance().parseQuery("WHERE c1 > DATE '12:32:43'"); - fail("Should have thrown an exception."); - } catch (InvalidQueryException e) { - // Supposed to throw an exception. - } - try { - // 2005 was not a leap year. - QueryBuilder.getInstance().parseQuery("WHERE c1 > DATE '2005-02-29'"); - fail("Should have thrown an exception."); - } catch (InvalidQueryException e) { - // Supposed to throw an exception. - } - } - - public void testAdvancedStringOperators() throws Exception { - Query query = QueryBuilder.getInstance().parseQuery("WHERE c1 MATCHES " - + "'.*a[^b]*b' AND 'abc' MATCHES c2 AND 'foo' CONTAINS c3" - + " AND c4 CONTAINS 'bar' AND c5 STARTS WITH 'baz' AND c6" - + " ENDS WITH 'chiko' AND 'baba' STARTS WITH c7 AND 'gaga'" - + " ENDS WITH c8"); - CompoundFilter filter = (CompoundFilter) query.getFilter(); - List subFilters = filter.getSubFilters(); - assertEquals(ComparisonFilter.Operator.MATCHES, - ((ComparisonFilter) subFilters.get(0)).getOperator()); - assertEquals(ComparisonFilter.Operator.CONTAINS, - ((ComparisonFilter) subFilters.get(3)).getOperator()); - assertEquals(ComparisonFilter.Operator.STARTS_WITH, - ((ComparisonFilter) subFilters.get(4)).getOperator()); - assertEquals(ComparisonFilter.Operator.ENDS_WITH, - ((ComparisonFilter) subFilters.get(5)).getOperator()); - } - - public void testSelectionOfArithmeticExpressions() throws Exception { - Query query = QueryBuilder.getInstance().parseQuery("SELECT ((c1+c2)/c3*c4)-(c5/c6+year(c7))"); - ScalarFunctionColumn col1 = new ScalarFunctionColumn( - Lists.newArrayList(new SimpleColumn("c1"), - new SimpleColumn("c2")), Sum.getInstance()); - ScalarFunctionColumn col2 = new ScalarFunctionColumn( - Lists.newArrayList(col1, new SimpleColumn("c3")), - Quotient.getInstance()); - ScalarFunctionColumn col3 = new ScalarFunctionColumn( - Lists.newArrayList(col2, new SimpleColumn("c4")), - Product.getInstance()); - ScalarFunctionColumn col4 = new ScalarFunctionColumn( - Lists.newArrayList(new SimpleColumn("c5"), - new SimpleColumn("c6")), Quotient.getInstance()); - ScalarFunctionColumn col5 = new ScalarFunctionColumn( - Lists.newArrayList(col4, - new ScalarFunctionColumn(Lists.newArrayList( - new SimpleColumn("c7")), TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.YEAR))), - Sum.getInstance()); - ScalarFunctionColumn col6 = new ScalarFunctionColumn( - Lists.newArrayList(col3, col5), - Difference.getInstance()); - QuerySelection selection = query.getSelection(); - assertEquals(1, selection.getColumns().size()); - assertEquals(col6, selection.getColumns().get(0)); - } - - public void testFilterOfArithmeticExpression() throws Exception { - Query query = QueryBuilder.getInstance().parseQuery("Where ((c1+c2)/c3*c4)" - + " > (c5/c6+year(c7)) and (c8+c9=0 or c10<>c11) "); - QueryFilter filter = query.getFilter(); - assertTrue(filter instanceof CompoundFilter); - CompoundFilter f = (CompoundFilter) filter; - assertEquals(CompoundFilter.LogicalOperator.AND, f.getOperator()); - List subFilters = f.getSubFilters(); - assertEquals(2, subFilters.size()); - QueryFilter f1 = subFilters.get(0); - QueryFilter f2 = subFilters.get(1); - - // f1: ((c1+c2)/c3*c4) > (c5/c6+year(c7)) - ScalarFunctionColumn col1 = new ScalarFunctionColumn( - Lists.newArrayList(new SimpleColumn("c1"), - new SimpleColumn("c2")), Sum.getInstance()); - ScalarFunctionColumn col2 = new ScalarFunctionColumn( - Lists.newArrayList(col1, new SimpleColumn("c3")), - Quotient.getInstance()); - ScalarFunctionColumn col3 = new ScalarFunctionColumn( - Lists.newArrayList(col2, new SimpleColumn("c4")), - Product.getInstance()); - ScalarFunctionColumn col4 = new ScalarFunctionColumn( - Lists.newArrayList(new SimpleColumn("c5"), - new SimpleColumn("c6")), Quotient.getInstance()); - ScalarFunctionColumn col5 = new ScalarFunctionColumn( - Lists.newArrayList(col4, - new ScalarFunctionColumn(Lists.newArrayList( - new SimpleColumn("c7")), TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.YEAR))), - Sum.getInstance()); - assertTrue(f1 instanceof ColumnColumnFilter); - ColumnColumnFilter ccf = (ColumnColumnFilter) f1; - assertEquals(col3, ccf.getFirstColumn()); - assertEquals(col5, ccf.getSecondColumn()); - - // f2: (c8+c9=0 or c10<>c11) - assertTrue(f2 instanceof CompoundFilter); - CompoundFilter cf = (CompoundFilter) f2; - assertEquals(CompoundFilter.LogicalOperator.OR, cf.getOperator()); - subFilters = cf.getSubFilters(); - assertEquals(2, subFilters.size()); - assertTrue(subFilters.get(0) instanceof ColumnValueFilter); - assertTrue(subFilters.get(1) instanceof ColumnColumnFilter); - assertEquals(new ScalarFunctionColumn( - Lists.newArrayList(new SimpleColumn("c8"), - new SimpleColumn("c9")), Sum.getInstance()), - ((ColumnValueFilter) subFilters.get(0)).getColumn()); - assertEquals(new NumberValue(0), - ((ColumnValueFilter) subFilters.get(0)).getValue()); - assertEquals(Sets.newHashSet("c10", "c11"), - subFilters.get(1).getAllColumnIds()); - assertEquals(ComparisonFilter.Operator.EQ, - ((ComparisonFilter) subFilters.get(0)).getOperator()); - assertEquals(ComparisonFilter.Operator.NE, - ((ComparisonFilter) subFilters.get(1)).getOperator()); - } - - public void testBadFilterOfArithmeticExpression() throws Exception { - try { - QueryBuilder.getInstance().parseQuery("Where ((c1+c2/c3*c4)" - + " > (c5/c6+year(c7)) and (c8+c9=0 or c10<>c11) "); - fail("Should have thrown an exception, missing ')': Where ((c1+c2/c3*c4)" - + "> (c5/c6+year(c7)) and (c8+c9=0 or c10<>c11)"); - } catch (InvalidQueryException e) { - // Expected behavior. - } - try { - QueryBuilder.getInstance().parseQuery("Where ((c1+)/c3*c4)" - + " > (c5/c6+year(c7)) and (c8+c9=0 or c10<>c11) "); - fail("Should have thrown an exception: 'Where ((c1+)/c3*c4)" - + "> (c5/c6+year(c7)) and (c8+c9=0 or c10<>c11)'"); - } catch (InvalidQueryException e) { - // Expected behavior. - } - try { - QueryBuilder.getInstance().parseQuery("Where ((c1+c2)/c3*c4)" - + " > (c5/c6+year(c7)) and (c8+c9=0 or c10*c11) "); - fail("Should have thrown an exception: 'Where ((c1+c2)/c3*c4)" - + "> (c5/c6+year(c7)) and (c8+c9=0 or c10*c11)'"); - } catch (InvalidQueryException e) { - // Expected behavior. - } - } - - public void testOrderByOfArithmeticExpression() throws Exception { - Query query = QueryBuilder.getInstance().parseQuery("order by ((c1+c2)/c3/c4)"); - QuerySort sort = query.getSort(); - List columnSorts = sort.getSortColumns(); - assertEquals(1, columnSorts.size()); - ScalarFunctionColumn col1 = new ScalarFunctionColumn( - Lists.newArrayList(new SimpleColumn("c1"), - new SimpleColumn("c2")), Sum.getInstance()); - ScalarFunctionColumn col2 = new ScalarFunctionColumn( - Lists.newArrayList(col1, new SimpleColumn("c3")), - Quotient.getInstance()); - ScalarFunctionColumn col3 = new ScalarFunctionColumn( - Lists.newArrayList(col2, new SimpleColumn("c4")), - Quotient.getInstance()); - assertEquals(col3, columnSorts.get(0).getColumn()); - assertEquals(SortOrder.ASCENDING, columnSorts.get(0).getOrder()); - } - - public void testPivotAndGroupByArithmeticExpression() throws Exception { - Query query = QueryBuilder.getInstance().parseQuery("select sum(c7) group " - + "by ((c1+c2)*c3/c4) pivot `c5` - `c6`"); - QueryGroup group = query.getGroup(); - QueryPivot pivot = query.getPivot(); - List groupColumns = group.getColumns(); - assertEquals(1, groupColumns.size()); - List pivotColumns = pivot.getColumns(); - assertEquals(1, pivotColumns.size()); - - ScalarFunctionColumn col1 = new ScalarFunctionColumn( - Lists.newArrayList(new SimpleColumn("c1"), - new SimpleColumn("c2")), Sum.getInstance()); - ScalarFunctionColumn col2 = new ScalarFunctionColumn( - Lists.newArrayList(col1, new SimpleColumn("c3")), - Product.getInstance()); - ScalarFunctionColumn col3 = new ScalarFunctionColumn( - Lists.newArrayList(col2, new SimpleColumn("c4")), - Quotient.getInstance()); - assertEquals(col3, groupColumns.get(0)); - - ScalarFunctionColumn col4 = new ScalarFunctionColumn( - Lists.newArrayList(new SimpleColumn("c5"), - new SimpleColumn("c6")), Difference.getInstance()); - assertEquals(col4, pivotColumns.get(0)); - } - - public void testVeryLongFilterQuery() throws Exception { - QueryBuilder.getInstance().parseQuery("WHERE ((((((((a+b)*c" - + "*d+e+f/(g+h*(d+b)))*3.3+d)/b+(d*3+year(c1)/month(c2)))-9+a)+b*c*d*e" - + ")-year(d))< (((((((a+b)*c*d+e+f/(g+h*(d+b)))*3.3+100*`r`)/b+(d*3+" - + "year(c1)/month(c2)))-9+a)+b*c*d*e)-year(d))) AND ((((((((a+`b d`)*" - + "c*d+e+f/(g+h*(d+b)))*3.3+d)/b+(d*3+year(c1)/month(c2)))-9+a)+b*c*d" - + "*e)-year(d))< (((((((a+bilo)*c*d+e+f/(g+h*(d+b)))*3.3+100*`r`)/b+(" - + "d*3+year(c1)/month(c2)))-9+a)+b*c*d*e)-year(d))) AND ((((((((a+`b d" - + "`)*c*gfdd+e+f/(g+h*(d+b)))*3.3+d)/b+(d*3+year(c1)/month(c2)))-9+a)" - + "+b*c*d*e)-year(d))< (((((((a+bsdilo)*c*d+e+f/(g+h*(d+b)))*3.3+100" - + "*`r`)/b+(d*3+year(c1)/month(c2)))-9+a)+b*c*d*e)-year(d))) OR ((((((" - + "((a+`b d`)*c*d+e+f/(g+hhh*(ffd+b)))*3.3+d)/b+(d*3+year(c1)/month(c2)" - + "))-9+a)+b*c*d*e)-year(d))< (((((((a+bilo)*c*d+e+f/(g+h*(d+bss)))*" - + "3.3+100*`r`)/b+(d*3+year(c1)/month(c2)))-9+a)+b*c*d*e)-year(d))) OR" - + " NOT (a + b < 3)"); - } - - public void testScalarFunctions() throws Exception { - // Test lower function. - Query query = QueryBuilder.getInstance().parseQuery("Select lower(c1)"); - QuerySelection selection = query.getSelection(); - assertEquals(selection.getColumns().size(), 1); - assertEquals( - ((ScalarFunctionColumn) selection.getColumns().get(0)).getFunction(), - Lower.getInstance()); - - // Test upper function. - query = QueryBuilder.getInstance().parseQuery("Select upper(c1)"); - selection = query.getSelection(); - assertEquals(selection.getColumns().size(), 1); - assertEquals( - ((ScalarFunctionColumn) selection.getColumns().get(0)).getFunction(), - Upper.getInstance()); - } - - public void testLikeOperator() throws Exception { - Query query = QueryBuilder.getInstance().parseQuery("where A like 'foo%bar'"); - ColumnValueFilter filter = (ColumnValueFilter) query.getFilter(); - assertEquals(ComparisonFilter.Operator.LIKE, filter.getOperator()); - assertEquals("A", ((SimpleColumn) filter.getColumn()).getId()); - assertEquals("foo%bar", ((TextValue) filter.getValue()).toString()); - } -} diff --git a/src/test/java/com/google/visualization/datasource/query/scalarfunction/DateDiffTest.java b/src/test/java/com/google/visualization/datasource/query/scalarfunction/DateDiffTest.java deleted file mode 100644 index ac09353..0000000 --- a/src/test/java/com/google/visualization/datasource/query/scalarfunction/DateDiffTest.java +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query.scalarfunction; - -import com.google.common.collect.Lists; -import com.google.visualization.datasource.base.InvalidQueryException; -import com.google.visualization.datasource.datatable.value.DateTimeValue; -import com.google.visualization.datasource.datatable.value.DateValue; -import com.google.visualization.datasource.datatable.value.NumberValue; -import com.google.visualization.datasource.datatable.value.Value; -import com.google.visualization.datasource.datatable.value.ValueType; - -import junit.framework.TestCase; - -import java.util.List; - -/** - * Tests for the DateDiff scalar function. - * - * @author Liron L. - */ -public class DateDiffTest extends TestCase { - public void testValidateParameters() throws InvalidQueryException { - List types = Lists.newArrayList(ValueType.DATE, - ValueType.DATETIME); - DateDiff dateDiff = DateDiff.getInstance(); - - // Validate date paremeter. - dateDiff.validateParameters(types); - - // Should throw an exception. - try { - dateDiff.validateParameters(Lists.newArrayList(ValueType.DATE, - ValueType.NUMBER)); - fail("Should have thrown a ScalarFunctionException: The dateDiff " - + "function was given a number parameter to validate."); - } catch (InvalidQueryException e) { - // do nothing - } - - // Validate datetime paremeter. - types = Lists.newArrayList(ValueType.DATETIME, ValueType.DATETIME); - dateDiff.validateParameters(types); - - // Should throw an exception. - try { - dateDiff.validateParameters(Lists.newArrayList(ValueType.DATE)); - fail("Should have thrown a ScalarFunctionException: The dateDiff " - + "function was given only 1 parameter."); - } catch (InvalidQueryException e) { - // Expected behavior. - } - } - - public void testEvaluate() { - DateDiff dateDiff = DateDiff.getInstance(); - List valuesList1 = - Lists.newArrayList(new DateValue(2008, 1, 13), - new DateValue(2008, 2, 13)); - List valuesList2 = Lists.newArrayList(new DateValue(2008, 1, 13), - new DateTimeValue(2008, 1, 13, 9, 12, 22, 333)); - List valuesList3 = - Lists.newArrayList(new DateTimeValue(2008, 6, 1, 9, 12, 22, 333), - new DateTimeValue(2008, 10, 1, 9, 12, 22, 333)); - List valuesList4 = Lists.newArrayList(new DateTimeValue( - 2008, 10, 1, 9, 12, 22, 333), - new DateTimeValue(2008, 6, 1, 9, 12, 20, 333)); - - assertEquals(new NumberValue(-29), dateDiff.evaluate(valuesList1)); - assertEquals(new NumberValue(0), dateDiff.evaluate(valuesList2)); - assertEquals(new NumberValue(-123), dateDiff.evaluate(valuesList3)); - assertEquals(new NumberValue(123), dateDiff.evaluate(valuesList4)); - } -} diff --git a/src/test/java/com/google/visualization/datasource/query/scalarfunction/LowerTest.java b/src/test/java/com/google/visualization/datasource/query/scalarfunction/LowerTest.java deleted file mode 100644 index 1255312..0000000 --- a/src/test/java/com/google/visualization/datasource/query/scalarfunction/LowerTest.java +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query.scalarfunction; - -import com.google.common.collect.Lists; -import com.google.visualization.datasource.base.InvalidQueryException; -import com.google.visualization.datasource.datatable.value.TextValue; -import com.google.visualization.datasource.datatable.value.Value; -import com.google.visualization.datasource.datatable.value.ValueType; - -import junit.framework.TestCase; - - -/** - * Tests for the DateDiff scalar function. - * - * @author Yaniv S. - */ -public class LowerTest extends TestCase { - public void testValidateParameters() { - Lower lower = Lower.getInstance(); - - // Verify that Lower does not accept 0 parameters. - try { - lower.validateParameters(Lists.newArrayList()); - fail(); - } catch (InvalidQueryException e) { - // Do nothing - this is the expected behavior. - } - - // Verify that Lower does not accept more than 1 parameter. - try { - lower.validateParameters(Lists.newArrayList(ValueType.TEXT, - ValueType.TEXT)); - fail(); - } catch (InvalidQueryException e) { - // Do nothing - this is the expected behavior. - } - - // Verify that Lower does not accept a non-Text parameter. - try { - lower.validateParameters(Lists.newArrayList(ValueType.DATE)); - fail(); - } catch (InvalidQueryException e) { - // Do nothing - this is the expected behavior. - } - - // Verify that Lower accepts 1 TEXT parameter. - try { - lower.validateParameters(Lists.newArrayList(ValueType.TEXT)); - } catch (InvalidQueryException e) { - fail(); - } - } - - public void testEvaluate() { - Lower lower = Lower.getInstance(); - - // Test empty string. - TextValue textValue = (TextValue) lower.evaluate( - Lists.newArrayList(new TextValue(""))); - assertEquals(textValue.getValue(), ""); - - // Basic test. - textValue = (TextValue) lower.evaluate( - Lists.newArrayList(new TextValue("AbC"))); - assertEquals(textValue.getValue(), "abc"); - } -} diff --git a/src/test/java/com/google/visualization/datasource/query/scalarfunction/TimeComponentExtractorTest.java b/src/test/java/com/google/visualization/datasource/query/scalarfunction/TimeComponentExtractorTest.java deleted file mode 100644 index 170b693..0000000 --- a/src/test/java/com/google/visualization/datasource/query/scalarfunction/TimeComponentExtractorTest.java +++ /dev/null @@ -1,272 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query.scalarfunction; - -import com.google.common.collect.Lists; -import com.google.visualization.datasource.base.InvalidQueryException; -import com.google.visualization.datasource.datatable.value.DateTimeValue; -import com.google.visualization.datasource.datatable.value.DateValue; -import com.google.visualization.datasource.datatable.value.NumberValue; -import com.google.visualization.datasource.datatable.value.TimeOfDayValue; -import com.google.visualization.datasource.datatable.value.Value; -import com.google.visualization.datasource.datatable.value.ValueType; - -import junit.framework.TestCase; - -import java.util.List; - -/** - * Tests for the TimeComponentExtractor - * - * @author Liron L. - */ -public class TimeComponentExtractorTest extends TestCase { - private TimeComponentExtractor year = - TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.YEAR); - - private TimeComponentExtractor month = - TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.MONTH); - - private TimeComponentExtractor day = - TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.DAY); - - private TimeComponentExtractor hour = - TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.HOUR); - - private TimeComponentExtractor minute = - TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.MINUTE); - - private TimeComponentExtractor second = - TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.SECOND); - - private TimeComponentExtractor millisecond = - TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.MILLISECOND); - - private TimeComponentExtractor quarter = - TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.QUARTER); - - private TimeComponentExtractor dayofweek = - TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.DAY_OF_WEEK); - - public void testValidateParameters() throws InvalidQueryException { - List types = Lists.newArrayList(ValueType.DATE); - - // Validate date paremeter. - year.validateParameters(types); - month.validateParameters(types); - day.validateParameters(types); - - // Should throw an exception. - try { - second.validateParameters(types); - fail("Should have thrown a ScalarFunctionException: The second function " - + "was given a date parameter to validate."); - } catch (InvalidQueryException e) { - // Expected behavior. - } - // Validate datetime paremeter. - types = Lists.newArrayList(ValueType.DATETIME); - year.validateParameters(types); - month.validateParameters(types); - day.validateParameters(types); - hour.validateParameters(types); - minute.validateParameters(types); - second.validateParameters(types); - millisecond.validateParameters(types); - - // Should throw an exception. - try { - hour.validateParameters(Lists.newArrayList(ValueType.NUMBER)); - fail("Should have thrown a ScalarFunctionException: The hour function " - + "was given a number parameter to validate."); - } catch (InvalidQueryException e) { - // Expected behavior. - } - - // Validate timeofday paremeter. - types = Lists.newArrayList(ValueType.TIMEOFDAY); - hour.validateParameters(types); - minute.validateParameters(types); - second.validateParameters(types); - millisecond.validateParameters(types); - - // Should throw an exception. - try { - year.validateParameters(types); - fail("Should have thrown a ScalarFunctionException: The year function " - + "was given a timeofday parameter to validate."); - } catch (InvalidQueryException e) { - // Expected behavior. - } - - // Should throw an exception. - try { - quarter.validateParameters(Lists.newArrayList(ValueType.NUMBER)); - fail("Should have thrown a ScalarFunctionException: The quarter " - + "function was given a number parameter to validate."); - } catch (InvalidQueryException e) { - // Expected behavior. - } - - // Should throw an exception. - try { - dayofweek.validateParameters(Lists.newArrayList(ValueType.NUMBER)); - fail("Should have thrown a ScalarFunctionException: The dayofweek " - + "function was given a number parameter to validate."); - } catch (InvalidQueryException e) { - // Expected behavior. - } - - // Validate datetime paremeter. - types = Lists.newArrayList(ValueType.DATETIME); - quarter.validateParameters(types); - dayofweek.validateParameters(types); - - // Should throw an exception. - try { - types.add(ValueType.DATETIME); - quarter.validateParameters(types); - fail("Should have thrown a ScalarFunctionException: The quarter " - + "function was given 2 parameters."); - } catch (InvalidQueryException e) { - // Expected behavior. - } - } - - public void testEvaluate() { - List dateValues = - Lists.newArrayList((Value) new DateValue(2008, 7, 13)); - assertEquals(new NumberValue(2008), year.evaluate(dateValues)); - assertEquals(new NumberValue(7), month.evaluate(dateValues)); - assertEquals(new NumberValue(13), day.evaluate(dateValues)); - - List dateTimeValues = - Lists.newArrayList((Value) new DateTimeValue( - 2001, 2, 3, 9, 12, 22, 333)); - assertEquals(new NumberValue(2001), year.evaluate(dateTimeValues)); - assertEquals(new NumberValue(2), month.evaluate(dateTimeValues)); - assertEquals(new NumberValue(3), day.evaluate(dateTimeValues)); - assertEquals(new NumberValue(9), hour.evaluate(dateTimeValues)); - assertEquals(new NumberValue(12), minute.evaluate(dateTimeValues)); - assertEquals(new NumberValue(22), second.evaluate(dateTimeValues)); - assertEquals(new NumberValue(333), millisecond.evaluate(dateTimeValues)); - - List timeOfDayValues = - Lists.newArrayList((Value) new TimeOfDayValue(23, 22, 21, 20)); - assertEquals(new NumberValue(23), hour.evaluate(timeOfDayValues)); - assertEquals(new NumberValue(22), minute.evaluate(timeOfDayValues)); - assertEquals(new NumberValue(21), second.evaluate(timeOfDayValues)); - assertEquals(new NumberValue(20), millisecond.evaluate(timeOfDayValues)); - timeOfDayValues = Lists.newArrayList((Value) new TimeOfDayValue(9, 12, 22)); - // Tests that milliseconds return 0 when the the TimeOfDayValue is - // initialized without the milliseconds. - assertEquals(new NumberValue(0), millisecond.evaluate(timeOfDayValues)); - - List dateValues1 = - Lists.newArrayList((Value) new DateValue(2008, 1, 13)); - List dateValues2 = - Lists.newArrayList((Value) new DateValue(2008, 4, 13)); - List dateValues3 = - Lists.newArrayList((Value) new DateValue(2008, 8, 13)); - List dateValues4 = - Lists.newArrayList((Value) new DateValue(2008, 11, 13)); - List dateValues5 = - Lists.newArrayList((Value) new DateValue(2008, 5, 13)); - - assertEquals(new NumberValue(1), quarter.evaluate(dateValues1)); - assertEquals(new NumberValue(2), quarter.evaluate(dateValues2)); - assertEquals(new NumberValue(3), quarter.evaluate(dateValues3)); - assertEquals(new NumberValue(4), quarter.evaluate(dateValues4)); - assertEquals(new NumberValue(2), quarter.evaluate(dateValues5)); - - assertEquals(new NumberValue(4), dayofweek.evaluate(dateValues1)); - assertEquals(new NumberValue(3), dayofweek.evaluate(dateValues2)); - assertEquals(new NumberValue(7), dayofweek.evaluate(dateValues3)); - assertEquals(new NumberValue(7), dayofweek.evaluate(dateValues4)); - assertEquals(new NumberValue(6), dayofweek.evaluate(dateValues5)); - - List dateTimeValues1 = - Lists.newArrayList((Value) new DateTimeValue( - 2001, 0, 3, 9, 12, 22, 333)); - List dateTimeValues2 = - Lists.newArrayList((Value) new DateTimeValue( - 2001, 3, 3, 9, 12, 22, 333)); - List dateTimeValues3 = - Lists.newArrayList((Value) new DateTimeValue( - 2001, 8, 3, 9, 12, 22, 333)); - List dateTimeValues4 = - Lists.newArrayList((Value) new DateTimeValue( - 2001, 10, 3, 9, 12, 22, 333)); - List dateTimeValues5 = - Lists.newArrayList((Value) new DateTimeValue( - 2001, 7, 3, 9, 12, 22, 333)); - - assertEquals(new NumberValue(1), quarter.evaluate(dateTimeValues1)); - assertEquals(new NumberValue(2), quarter.evaluate(dateTimeValues2)); - assertEquals(new NumberValue(3), quarter.evaluate(dateTimeValues3)); - assertEquals(new NumberValue(4), quarter.evaluate(dateTimeValues4)); - assertEquals(new NumberValue(3), quarter.evaluate(dateTimeValues5)); - - assertEquals(new NumberValue(4), dayofweek.evaluate(dateTimeValues1)); - assertEquals(new NumberValue(3), dayofweek.evaluate(dateTimeValues2)); - assertEquals(new NumberValue(2), dayofweek.evaluate(dateTimeValues3)); - assertEquals(new NumberValue(7), dayofweek.evaluate(dateTimeValues4)); - assertEquals(new NumberValue(6), dayofweek.evaluate(dateTimeValues5)); - } - - // Tests that 2 instances of the same kind of TimeComponentExtractor are equal - // (i.e., they're the same instance). - public void testSingelton() { - TimeComponentExtractor anotherYear = TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.YEAR); - TimeComponentExtractor anotherMonth = TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.MONTH); - TimeComponentExtractor anotherDay = TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.DAY); - TimeComponentExtractor anotherHour = TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.HOUR); - TimeComponentExtractor anotherMinute = TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.MINUTE); - TimeComponentExtractor anotherSecond = TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.SECOND); - TimeComponentExtractor anotherMillisecond = - TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.MILLISECOND); - TimeComponentExtractor anotherQuarter = - TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.QUARTER); - TimeComponentExtractor anotherDayOfWeek = - TimeComponentExtractor.getInstance( - TimeComponentExtractor.TimeComponent.DAY_OF_WEEK); - assertTrue(year == anotherYear); - assertTrue(month == anotherMonth); - assertTrue(day == anotherDay); - assertTrue(hour == anotherHour); - assertTrue(minute == anotherMinute); - assertTrue(second == anotherSecond); - assertTrue(millisecond == anotherMillisecond); - assertTrue(quarter == anotherQuarter); - assertTrue(dayofweek == anotherDayOfWeek); - } -} diff --git a/src/test/java/com/google/visualization/datasource/query/scalarfunction/ToDateTest.java b/src/test/java/com/google/visualization/datasource/query/scalarfunction/ToDateTest.java deleted file mode 100644 index fdd0a9a..0000000 --- a/src/test/java/com/google/visualization/datasource/query/scalarfunction/ToDateTest.java +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query.scalarfunction; - -import com.google.common.collect.Lists; -import com.google.visualization.datasource.base.InvalidQueryException; -import com.google.visualization.datasource.datatable.value.DateTimeValue; -import com.google.visualization.datasource.datatable.value.DateValue; -import com.google.visualization.datasource.datatable.value.NumberValue; -import com.google.visualization.datasource.datatable.value.Value; -import com.google.visualization.datasource.datatable.value.ValueType; - -import junit.framework.TestCase; - -import java.util.List; - -/** - * Tests for the ToDate scalar function. - * - * @author Liron L. - */ -public class ToDateTest extends TestCase { - public void testValidateParameters() throws InvalidQueryException { - ToDate toDate = ToDate.getInstance(); - - // Validate datetime, date, number and string paremeters. - toDate.validateParameters(Lists.newArrayList(ValueType.DATETIME)); - toDate.validateParameters(Lists.newArrayList(ValueType.DATE)); - toDate.validateParameters(Lists.newArrayList(ValueType.NUMBER)); - - // Should throw an exception. - try { - toDate.validateParameters(Lists.newArrayList(ValueType.TIMEOFDAY)); - fail("Should have thrown a ScalarFunctionException: The toDiff " - + "function was given a timeofday parameter to validate."); - } catch (InvalidQueryException e) { - // Expected behavior. - } - - // Should throw an exception. - try { - toDate.validateParameters(Lists.newArrayList(ValueType.DATE, - ValueType.NUMBER)); - fail("Should have thrown a ScalarFunctionException: The toDAte " - + "function was given 2 parameters."); - } catch (InvalidQueryException e) { - // Expected behavior. - } - } - - public void testEvaluate() { - ToDate toDate = ToDate.getInstance(); - List valuesList1 = - Lists.newArrayList(new DateValue(2008, 1, 13)); - List valuesList2 = - Lists.newArrayList( - new DateTimeValue(2008, 2, 23, 9, 12, 22, 333)); - List valuesList3 = - Lists.newArrayList(new NumberValue(1234567890000.53421423424)); -List valuesList4 = - Lists.newArrayList(new NumberValue(-1234567890000.0)); - assertEquals(new DateValue(2008, 1, 13), toDate.evaluate(valuesList1)); - assertEquals(new DateValue(2008, 2, 23), toDate.evaluate(valuesList2)); - assertEquals(new DateValue(2009, 1, 13), toDate.evaluate(valuesList3)); - assertEquals(new DateValue(1930, 10, 18), toDate.evaluate(valuesList4)); - - } -} diff --git a/src/test/java/com/google/visualization/datasource/query/scalarfunction/UpperTest.java b/src/test/java/com/google/visualization/datasource/query/scalarfunction/UpperTest.java deleted file mode 100644 index 2e0893a..0000000 --- a/src/test/java/com/google/visualization/datasource/query/scalarfunction/UpperTest.java +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.query.scalarfunction; - -import com.google.common.collect.Lists; -import com.google.visualization.datasource.base.InvalidQueryException; -import com.google.visualization.datasource.datatable.value.TextValue; -import com.google.visualization.datasource.datatable.value.Value; -import com.google.visualization.datasource.datatable.value.ValueType; - -import junit.framework.TestCase; - - -/** - * Tests for the Upper scalar function. - * - * @author Yaniv S. - */ -public class UpperTest extends TestCase { - public void testValidateParameters() { - Upper upper = Upper.getInstance(); - - // Verify that Upper does not accept 0 parameters. - try { - upper.validateParameters(Lists.newArrayList()); - fail(); - } catch (InvalidQueryException e) { - // Do nothing - this is the expected behavior. - } - - // Verify that Upper does not accept more than 1 parameter. - try { - upper.validateParameters(Lists.newArrayList(ValueType.TEXT, - ValueType.TEXT)); - fail(); - } catch (InvalidQueryException e) { - // Do nothing - this is the expected behavior. - } - - // Verify that Upper does not accept a non-Text parameter. - try { - upper.validateParameters(Lists.newArrayList(ValueType.DATE)); - fail(); - } catch (InvalidQueryException e) { - // Do nothing - this is the expected behavior. - } - - // Verify that Upper accepts 1 TEXT parameter. - try { - upper.validateParameters(Lists.newArrayList(ValueType.TEXT)); - } catch (InvalidQueryException e) { - fail(); - } - } - - public void testEvaluate() { - Upper upper = Upper.getInstance(); - - // Test empty string. - TextValue textValue = (TextValue) upper.evaluate( - Lists.newArrayList(new TextValue(""))); - assertEquals(textValue.getValue(), ""); - - // Basic test. - textValue = (TextValue) upper.evaluate( - Lists.newArrayList(new TextValue("aBc"))); - assertEquals(textValue.getValue(), "ABC"); - } -} diff --git a/src/test/java/com/google/visualization/datasource/render/CsvRendererTest.java b/src/test/java/com/google/visualization/datasource/render/CsvRendererTest.java deleted file mode 100644 index bbf429b..0000000 --- a/src/test/java/com/google/visualization/datasource/render/CsvRendererTest.java +++ /dev/null @@ -1,312 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.render; - -import com.google.common.collect.Lists; -import com.google.visualization.datasource.base.DataSourceException; -import com.google.visualization.datasource.base.ReasonType; -import com.google.visualization.datasource.base.ResponseStatus; -import com.google.visualization.datasource.base.StatusType; -import com.google.visualization.datasource.datatable.ColumnDescription; -import com.google.visualization.datasource.datatable.DataTable; -import com.google.visualization.datasource.datatable.TableCell; -import com.google.visualization.datasource.datatable.TableRow; -import com.google.visualization.datasource.datatable.value.BooleanValue; -import com.google.visualization.datasource.datatable.value.DateTimeValue; -import com.google.visualization.datasource.datatable.value.DateValue; -import com.google.visualization.datasource.datatable.value.NumberValue; -import com.google.visualization.datasource.datatable.value.TextValue; -import com.google.visualization.datasource.datatable.value.TimeOfDayValue; -import com.google.visualization.datasource.datatable.value.ValueType; - -import junit.framework.TestCase; - -import java.util.List; - -/** - * Tests for CsvRenderer. - * - * @author Nimrod T. - */ -public class CsvRendererTest extends TestCase { - - DataTable testData; - - List rows; - - List colIds; - - @Override - public void setUp() throws Exception { - super.setUp(); - - colIds = Lists.newArrayList(); - - testData = new DataTable(); - ColumnDescription c0 = new ColumnDescription("col0", ValueType.TEXT, "label0"); - ColumnDescription c1 = new ColumnDescription("col1", ValueType.NUMBER, "label1"); - ColumnDescription c2 = new ColumnDescription("col2", ValueType.BOOLEAN, "label2"); - ColumnDescription c3 = new ColumnDescription("col3", ValueType.DATE, "label3"); - ColumnDescription c4 = new ColumnDescription("col4", ValueType.TIMEOFDAY, "label4"); - ColumnDescription c5 = new ColumnDescription("col5", ValueType.DATETIME, "label5"); - - testData.addColumn(c0); - testData.addColumn(c1); - testData.addColumn(c2); - testData.addColumn(c3); - testData.addColumn(c4); - testData.addColumn(c5); - - colIds.add("col0"); - colIds.add("col1"); - colIds.add("col2"); - colIds.add("col3"); - colIds.add("col4"); - colIds.add("col5"); - - rows = Lists.newArrayList(); - - TableRow row = new TableRow(); - row.addCell(new TableCell("aaa")); - row.addCell(new TableCell(222)); - row.addCell(new TableCell(false)); - row.addCell(new TableCell(new DateValue(2001, 10, 14))); - row.addCell(new TableCell(new TimeOfDayValue(12, 11, 13, 14))); - row.addCell(new TableCell(new DateTimeValue(2000, 10, 1, 1, 10, 23, 432))); - rows.add(row); - - row = new TableRow(); - row.addCell(new TableCell("ccc")); - row.addCell(new TableCell(111)); - row.addCell(new TableCell(true)); - row.addCell(new TableCell(new DateValue(2001, 1, 14))); - row.addCell(new TableCell(new TimeOfDayValue(12, 30, 13, 14))); - row.addCell(new TableCell(new DateTimeValue(1000, 11, 1, 1, 10, 23, 432))); - rows.add(row); - - row = new TableRow(); - row.addCell(new TableCell("bbb")); - row.addCell(new TableCell(3)); - row.addCell(new TableCell(true)); - row.addCell(new TableCell(new DateValue(2012, 2, 14))); - row.addCell(new TableCell(new TimeOfDayValue(12, 11, 3, 14))); - row.addCell(new TableCell(new DateTimeValue(2000, 1, 1, 1, 10, 31, 4))); - rows.add(row); - - row = new TableRow(); - row.addCell("ddd"); - row.addCell(222); - row.addCell(false); - row.addCell(new DateValue(1997, 5, 5)); - row.addCell(new TimeOfDayValue(12, 15, 15, 14)); - row.addCell(new DateTimeValue(3100, 1, 2, 15, 15, 1, 0)); - rows.add(row); - - testData.addRows(rows); - } - - @Override - public void tearDown() throws Exception { - super.tearDown(); - testData = null; - rows = null; - } - - public void testEmptyDataTableToCsv() { - DataTable dataTable = new DataTable(); - assertEquals("", CsvRenderer.renderDataTable(dataTable, null, null)); - assertEquals("", CsvRenderer.renderDataTable(dataTable, null, ",")); - assertEquals("", CsvRenderer.renderDataTable(dataTable, null, "\t")); - } - - public void testSimpleDataTableToCsv() throws DataSourceException { - colIds = Lists.newArrayList(); - - testData = new DataTable(); - ColumnDescription c0 = new ColumnDescription("A", ValueType.TEXT, "col0"); - ColumnDescription c1 = new ColumnDescription("B", ValueType.NUMBER, "col1"); - ColumnDescription c2 = new ColumnDescription("C", ValueType.BOOLEAN, "col2"); - - testData.addColumn(c0); - testData.addColumn(c1); - testData.addColumn(c2); - - rows = Lists.newArrayList(); - - TableRow row = new TableRow(); - row.addCell(new TableCell("aaa")); - row.addCell(new TableCell(new NumberValue(222), "222")); - row.addCell(new TableCell(false)); - rows.add(row); - - row = new TableRow(); - row.addCell(new TableCell("")); - row.addCell(new TableCell(NumberValue.getNullValue())); - row.addCell(new TableCell(true)); - rows.add(row); - - row = new TableRow(); - row.addCell(new TableCell(new TextValue("bbb"), "bb@@b")); - row.addCell(new TableCell(333)); - row.addCell(new TableCell(true)); - rows.add(row); - - row = new TableRow(); - row.addCell(new TableCell("ddd")); - row.addCell(new TableCell(222)); - row.addCell(new TableCell(false)); - rows.add(row); - - testData.addRows(rows); - - assertEquals( - "\"col0\",\"col1\",\"col2\"\n" + - "\"aaa\",222,false\n" + - "\"\",null,true\n" + - "\"bb@@b\",333,true\n" + - "\"ddd\",222,false\n", - CsvRenderer.renderDataTable(testData, null, null).toString()); - assertEquals( - "\"col0\",\"col1\",\"col2\"\n" + - "\"aaa\",222,false\n" + - "\"\",null,true\n" + - "\"bb@@b\",333,true\n" + - "\"ddd\",222,false\n", - CsvRenderer.renderDataTable(testData, null, ",").toString()); - assertEquals( - "\"col0\"\t\"col1\"\t\"col2\"\n" + - "\"aaa\"\t222\tfalse\n" + - "\"\"\tnull\ttrue\n" + - "\"bb@@b\"\t333\ttrue\n" + - "\"ddd\"\t222\tfalse\n", - CsvRenderer.renderDataTable(testData, null, "\t").toString()); - } - - public void testCustomPropertiesToCsv() throws DataSourceException { - colIds = Lists.newArrayList(); - - testData = new DataTable(); - ColumnDescription c0 = new ColumnDescription("A", ValueType.TEXT, "col0"); - ColumnDescription c1 = new ColumnDescription("B", ValueType.NUMBER, "col1"); - c1.setCustomProperty("arak", "elit"); - - testData.addColumn(c0); - testData.addColumn(c1); - - rows = Lists.newArrayList(); - - TableRow row = new TableRow(); - row.addCell(new TableCell("aaa")); - row.addCell(new TableCell(new NumberValue(222), "2a2b2")); - rows.add(row); - - row = new TableRow(); - row.addCell(new TableCell("")); - row.addCell(new TableCell(NumberValue.getNullValue())); - rows.add(row); - row.setCustomProperty("sensi", "puff"); - - testData.addRows(rows); - - testData.getRow(0).getCell(0).setCustomProperty("a", "b"); - - assertEquals( - "\"col0\",\"col1\"\n\"aaa\",2a2b2\n\"\",null\n", - CsvRenderer.renderDataTable(testData, null, null).toString()); - assertEquals( - "\"col0\",\"col1\"\n\"aaa\",2a2b2\n\"\",null\n", - CsvRenderer.renderDataTable(testData, null, ",").toString()); - assertEquals( - "\"col0\"\t\"col1\"\n\"aaa\"\t2a2b2\n\"\"\tnull\n", - CsvRenderer.renderDataTable(testData, null, "\t").toString()); - - testData.setCustomProperty("brandy", "cognac"); - assertEquals( - "\"col0\",\"col1\"\n\"aaa\",2a2b2\n\"\",null\n", - CsvRenderer.renderDataTable(testData, null, null).toString()); - assertEquals( - "\"col0\",\"col1\"\n\"aaa\",2a2b2\n\"\",null\n", - CsvRenderer.renderDataTable(testData, null, ",").toString()); - assertEquals( - "\"col0\"\t\"col1\"\n\"aaa\"\t2a2b2\n\"\"\tnull\n", - CsvRenderer.renderDataTable(testData, null, "\t").toString()); - } - - public void testRenderError() { - ResponseStatus responseStatus = new ResponseStatus( - StatusType.ERROR, ReasonType.INVALID_REQUEST, "but why? why?"); - assertEquals( - "\"Error: Invalid request. but why? why?\"", - CsvRenderer.renderCsvError(responseStatus)); - - responseStatus = new ResponseStatus( - StatusType.ERROR, ReasonType.NOT_SUPPORTED, "Cannot do dat!"); - assertEquals( - "\"Error: Operation not supported. Cannot do dat!\"", - CsvRenderer.renderCsvError(responseStatus)); - - responseStatus = new ResponseStatus( - StatusType.ERROR, ReasonType.NOT_SUPPORTED, "Cannot \"do\" that, too late!"); - assertEquals( - "\"Error: Operation not supported. Cannot \"\"do\"\" that, too late!\"", - CsvRenderer.renderCsvError(responseStatus)); - } - - public void testRenderDataTableWithCommas() throws DataSourceException { - testData = new DataTable(); - ColumnDescription c0 = new ColumnDescription("A", ValueType.TEXT, "col0"); - ColumnDescription c1 = new ColumnDescription("B", ValueType.NUMBER, "col1"); - ColumnDescription c2 = new ColumnDescription("C", ValueType.BOOLEAN, "col2"); - ColumnDescription c3 = new ColumnDescription("D", ValueType.DATE, "col3"); - ColumnDescription c4 = new ColumnDescription("E", ValueType.DATETIME, "col4"); - ColumnDescription c5 = new ColumnDescription("F", ValueType.TIMEOFDAY, "col5"); - - testData.addColumn(c0); - testData.addColumn(c1); - testData.addColumn(c2); - testData.addColumn(c3); - testData.addColumn(c4); - testData.addColumn(c5); - - rows = Lists.newArrayList(); - - TableRow row = new TableRow(); - row.addCell(new TableCell(new TextValue("aaa"), "aaa")); - row.addCell(new TableCell(new NumberValue(222), "222")); - row.addCell(new TableCell(BooleanValue.TRUE, "true")); - row.addCell(new TableCell(new DateValue(2009, 1, 1), "2009-02-01")); - row.addCell(new TableCell(new DateTimeValue(2009, 1, 1, 12, 14, 1, 0), "2009-02-01 12:14:01")); - row.addCell(new TableCell(new TimeOfDayValue(12, 14, 1), "12:14:01")); - rows.add(row); - - row = new TableRow(); - row.addCell(new TableCell(new TextValue("aaa"), "a,aa")); - row.addCell(new TableCell(new NumberValue(222), "2,22")); - row.addCell(new TableCell(BooleanValue.TRUE, "true,")); - row.addCell(new TableCell(new DateValue(2009, 1, 1), "2009-02-01")); - row.addCell(new TableCell(new DateTimeValue(2009, 1, 1, 12, 14, 1, 0), "2009-02-01 12,14,01")); - row.addCell(new TableCell(new TimeOfDayValue(12, 14, 1), "12:14:01")); - rows.add(row); - - testData.addRows(rows); - - String expected = "\"col0\",\"col1\",\"col2\",\"col3\",\"col4\",\"col5\"\n"; - expected += "\"aaa\",222,true,2009-02-01,2009-02-01 12:14:01,12:14:01\n"; - expected += "\"a,aa\",\"2,22\",\"true,\",2009-02-01,\"2009-02-01 12,14,01\",12:14:01\n"; - assertEquals(expected, CsvRenderer.renderDataTable(testData, null, null)); - - } -} - diff --git a/src/test/java/com/google/visualization/datasource/render/EscapeUtilTest.java b/src/test/java/com/google/visualization/datasource/render/EscapeUtilTest.java deleted file mode 100644 index 412ccb9..0000000 --- a/src/test/java/com/google/visualization/datasource/render/EscapeUtilTest.java +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.render; - - -import junit.framework.TestCase; - -/** - * Tests for Escape Util. - * - * @author Hillel M. - */ -public class EscapeUtilTest extends TestCase{ - - public static void testJsonEscape() { - // Check ' " < > \ - assertEquals("\\u0027ABC", EscapeUtil.jsonEscape("'ABC")); - assertEquals("\\u0022ABC", EscapeUtil.jsonEscape("\"ABC")); - assertEquals("\\\\", EscapeUtil.jsonEscape("\\")); - assertEquals("\\u003cABC\\u003e", EscapeUtil.jsonEscape("")); - assertEquals("\\u003c/ABC\\u003e", EscapeUtil.jsonEscape("")); - - // Normal string (all keyboard letters but ', ", \, <, >) - String normalString = "`1234567890-=qwertyuiop[];lkjhgfdsazxcvbnm,.//*-+.0~!@#$%^&*()_+" - + "QWERTYUIOP{}|:LKJHGFDSAZXCVBNM?;"; - assertEquals(normalString, EscapeUtil.jsonEscape(normalString)); - - // Weird characters (non readable) - String weirdString = "\n\t\r\\ \u0081\u0010\u2010\u2099\b\f"; - String escapedweirdString = "\\n\\t\\r\\\\ \\u0081\\u0010\\u2010\\u2099\\b\\f"; - assertEquals(escapedweirdString, EscapeUtil.jsonEscape(weirdString)); - - // Normal string in Unicode (pqr) - String normalStringInUnicode = "\u0070\u0071\u0072"; - assertEquals("pqr", EscapeUtil.jsonEscape(normalStringInUnicode)); - - // Non English normal characters (Hebrew - me) - String nonEnglishString = "\u05d0\u05e0\u05d9"; - assertEquals(nonEnglishString, EscapeUtil.jsonEscape(nonEnglishString)); - } -} \ No newline at end of file diff --git a/src/test/java/com/google/visualization/datasource/render/HtmlRendererTest.java b/src/test/java/com/google/visualization/datasource/render/HtmlRendererTest.java deleted file mode 100644 index ec996d0..0000000 --- a/src/test/java/com/google/visualization/datasource/render/HtmlRendererTest.java +++ /dev/null @@ -1,371 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.render; - -import com.google.common.collect.Lists; -import com.google.visualization.datasource.base.DataSourceException; -import com.google.visualization.datasource.base.ReasonType; -import com.google.visualization.datasource.base.ResponseStatus; -import com.google.visualization.datasource.base.StatusType; -import com.google.visualization.datasource.base.Warning; -import com.google.visualization.datasource.datatable.ColumnDescription; -import com.google.visualization.datasource.datatable.DataTable; -import com.google.visualization.datasource.datatable.TableCell; -import com.google.visualization.datasource.datatable.TableRow; -import com.google.visualization.datasource.datatable.value.DateTimeValue; -import com.google.visualization.datasource.datatable.value.DateValue; -import com.google.visualization.datasource.datatable.value.NumberValue; -import com.google.visualization.datasource.datatable.value.TextValue; -import com.google.visualization.datasource.datatable.value.TimeOfDayValue; -import com.google.visualization.datasource.datatable.value.ValueType; - -import com.ibm.icu.util.ULocale; - -import junit.framework.TestCase; - -import java.util.List; - -/** - * Tests for HtmlRenderer. - * - * @author Nimrod T. - */ -public class HtmlRendererTest extends TestCase { - - DataTable testData; - - List rows; - - List colIds; - - // Use platform dependent new-line to validate the results. - String nl = System.getProperty("line.separator"); - - @Override - public void setUp() throws Exception { - super.setUp(); - - colIds = Lists.newArrayList(); - - testData = new DataTable(); - ColumnDescription c0 = new ColumnDescription("col0", ValueType.TEXT, "label0"); - ColumnDescription c1 = new ColumnDescription("col1", ValueType.NUMBER, "label1"); - ColumnDescription c2 = new ColumnDescription("col2", ValueType.BOOLEAN, "label2"); - ColumnDescription c3 = new ColumnDescription("col3", ValueType.DATE, "label3"); - ColumnDescription c4 = new ColumnDescription("col4", ValueType.TIMEOFDAY, "label4"); - ColumnDescription c5 = new ColumnDescription("col5", ValueType.DATETIME, "label5"); - - testData.addColumn(c0); - testData.addColumn(c1); - testData.addColumn(c2); - testData.addColumn(c3); - testData.addColumn(c4); - testData.addColumn(c5); - - colIds.add("col0"); - colIds.add("col1"); - colIds.add("col2"); - colIds.add("col3"); - colIds.add("col4"); - colIds.add("col5"); - - rows = Lists.newArrayList(); - - TableRow row = new TableRow(); - row.addCell(new TableCell("aaa")); - row.addCell(new TableCell(222)); - row.addCell(new TableCell(false)); - row.addCell(new TableCell(new DateValue(2001, 10, 14))); - row.addCell(new TableCell(new TimeOfDayValue(12, 11, 13, 14))); - row.addCell(new TableCell(new DateTimeValue(2000, 10, 1, 1, 10, 23, 432))); - rows.add(row); - - row = new TableRow(); - row.addCell(new TableCell("ccc")); - row.addCell(new TableCell(111)); - row.addCell(new TableCell(true)); - row.addCell(new TableCell(new DateValue(2001, 1, 14))); - row.addCell(new TableCell(new TimeOfDayValue(12, 30, 13, 14))); - row.addCell(new TableCell(new DateTimeValue(1000, 11, 1, 1, 10, 23, 432))); - rows.add(row); - - row = new TableRow(); - row.addCell(new TableCell("bbb")); - row.addCell(new TableCell(3)); - row.addCell(new TableCell(true)); - row.addCell(new TableCell(new DateValue(2012, 2, 14))); - row.addCell(new TableCell(new TimeOfDayValue(12, 11, 3, 14))); - row.addCell(new TableCell(new DateTimeValue(2000, 1, 1, 1, 10, 31, 4))); - rows.add(row); - - row = new TableRow(); - row.addCell("ddd"); - row.addCell(222); - row.addCell(false); - row.addCell(new DateValue(1997, 5, 5)); - row.addCell(new TimeOfDayValue(12, 15, 15, 14)); - row.addCell(new DateTimeValue(3100, 1, 2, 15, 15, 1, 0)); - rows.add(row); - - testData.addRows(rows); - } - - @Override - public void tearDown() throws Exception { - super.tearDown(); - testData = null; - rows = null; - } - - public void testEmptyDataTableToHtml() { - DataTable dataTable = new DataTable(); - String expected = - "" + nl - + "" + nl - + "" + nl - + "" + nl - + "Google Visualization" + nl - + "" + nl - + "" + nl - + "" + nl - + "" + nl - + "
" + nl - + "" + nl - + "" + nl; - - String actual = HtmlRenderer.renderDataTable(dataTable, ULocale.US).toString(); - assertEquals(expected, actual); - } - - public void testSimpleDataTableToHtml() throws DataSourceException { - colIds = Lists.newArrayList(); - - testData = new DataTable(); - ColumnDescription c0 = new ColumnDescription("A", ValueType.TEXT, "col0"); - ColumnDescription c1 = new ColumnDescription("B", ValueType.NUMBER, "col1"); - ColumnDescription c2 = new ColumnDescription("C", ValueType.BOOLEAN, "col2"); - - testData.addColumn(c0); - testData.addColumn(c1); - testData.addColumn(c2); - - rows = Lists.newArrayList(); - - TableRow row = new TableRow(); - row.addCell(new TableCell("aaa")); - row.addCell(new TableCell(new NumberValue(222), "222")); - row.addCell(new TableCell(false)); - rows.add(row); - - row = new TableRow(); - row.addCell(new TableCell("")); - row.addCell(NumberValue.getNullValue()); - row.addCell(new TableCell(true)); - rows.add(row); - - row = new TableRow(); - row.addCell(new TableCell(new TextValue("bbb"), "bb@@b")); - row.addCell(new TableCell(333)); - row.addCell(new TableCell(true)); - rows.add(row); - - row = new TableRow(); - row.addCell(new TableCell("ddd")); - row.addCell(new TableCell(222)); - row.addCell(new TableCell(false)); - rows.add(row); - - testData.addRows(rows); - - String expected = - "" + nl - + "" + nl - + "" + nl - + "" + nl - + "Google Visualization" + nl - + "" + nl - + "" + nl - + "" + nl - + "" + nl - + "" - + "" - + "" + nl - + "" + nl - + "" + nl - + "" - + "" - + "" + nl - + "" + nl - + "" + nl - + "" - + "" - + "" + nl - + "" + nl - + "" + nl - + "" - + "" - + "" + nl - + "" + nl - + "" + nl - + "" - + "" - + "" + nl - + "" + nl - + "
col0col1col2
aaa222\u2717
  \u2714
bb@@b333\u2714
ddd222\u2717
" + nl - + "" + nl - + "" + nl; - - String actual = HtmlRenderer.renderDataTable(testData, ULocale.US).toString(); - - assertEquals(expected, actual); - } - - public void testWarnings() throws DataSourceException { - testData = new DataTable(); - ColumnDescription c0 = new ColumnDescription("A", ValueType.TEXT, "col0"); - ColumnDescription c1 = new ColumnDescription("B", ValueType.NUMBER, "col1"); - - testData.addColumn(c0); - testData.addColumn(c1); - - rows = Lists.newArrayList(); - - TableRow row = new TableRow(); - row.addCell(new TableCell("aaa")); - row.addCell(new TableCell(new NumberValue(222), "$222")); - rows.add(row); - - row = new TableRow(); - row.addCell(new TableCell("bbb")); - row.addCell(new TableCell(333)); - rows.add(row); - - testData.addRows(rows); - - testData.addWarning(new Warning(ReasonType.DATA_TRUNCATED, "Sorry, data truncated")); - testData.addWarning(new Warning(ReasonType.NOT_SUPPORTED, "foobar")); - - String expected = - "" + nl - + "" + nl - + "" + nl - + "" + nl - + "Google Visualization" + nl - + "" + nl - + "" + nl - + "" + nl - + "" + nl - + "" - + "" + nl - + "" + nl - + "" + nl - + "" - + "" + nl - + "" + nl - + "" + nl - + "" - + "" + nl - + "" + nl - + "
col0col1
aaa$222
bbb333
" + nl - + "
" + nl - + "
" + nl - + "

Retrieved data was truncated. Sorry, data truncated
" + nl - + "
" + nl - + "
" + nl - + "
Operation not supported. foobar
" + nl - + "" + nl - + "" + nl; - - String actual = HtmlRenderer.renderDataTable(testData, ULocale.US).toString(); - - assertEquals(expected, actual); - } - - public void testEscaping() { - ResponseStatus responseStatus = new ResponseStatus( - StatusType.ERROR, ReasonType.INVALID_REQUEST, "but why? why? why?"); - assertEquals( - "" + nl - + "" + nl - + "" + nl - + "" + nl - + "Google Visualization" + nl - + "" + nl - + "" + nl - + "

Oops, an error occured.

" + nl - + "
Status: error
" + nl - + "
Reason: Invalid request
" + nl - + "
Description: but why? why? why?
" + nl - + "" + nl - + "" + nl, - HtmlRenderer.renderHtmlError(responseStatus).toString()); - - responseStatus = new ResponseStatus( - StatusType.ERROR, ReasonType.NOT_SUPPORTED, "Cannot do dat!"); - assertEquals( - "" + nl - + "" + nl - + "" + nl - + "" + nl - + "Google Visualization" + nl - + "" + nl - + "" + nl - + "

Oops, an error occured.

" + nl - + "
Status: error
" + nl - + "
Reason: Operation not supported
" + nl - + "
Description: Cannot do dat!
" + nl - + "" + nl - + "" + nl, - HtmlRenderer.renderHtmlError(responseStatus).toString()); - } - - public void testRenderError() { - ResponseStatus responseStatus = new ResponseStatus( - StatusType.ERROR, ReasonType.INVALID_REQUEST, "but why? why?"); - assertEquals( - "" + nl - + "" + nl - + "" + nl - + "" + nl - + "Google Visualization" + nl - + "" + nl - + "" + nl - + "

Oops, an error occured.

" + nl - + "
Status: error
" + nl - + "
Reason: Invalid request
" + nl - + "
Description: but why? why?
" + nl - + "" + nl - + "" + nl, - HtmlRenderer.renderHtmlError(responseStatus).toString()); - - responseStatus = new ResponseStatus( - StatusType.ERROR, ReasonType.NOT_SUPPORTED, "Cannot do dat!"); - assertEquals( - "" + nl - + "" + nl - + "" + nl - + "" + nl - + "Google Visualization" + nl - + "" + nl - + "" + nl - + "

Oops, an error occured.

" + nl - + "
Status: error
" + nl - + "
Reason: Operation not supported
" + nl - + "
Description: Cannot do dat!
" + nl - + "" + nl - + "" + nl, - HtmlRenderer.renderHtmlError(responseStatus).toString()); - } -} diff --git a/src/test/java/com/google/visualization/datasource/render/JsonRendererTest.java b/src/test/java/com/google/visualization/datasource/render/JsonRendererTest.java deleted file mode 100644 index 2b0561b..0000000 --- a/src/test/java/com/google/visualization/datasource/render/JsonRendererTest.java +++ /dev/null @@ -1,436 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.visualization.datasource.render; - -import com.google.common.collect.Lists; -import com.google.visualization.datasource.base.DataSourceException; -import com.google.visualization.datasource.base.DataSourceParameters; -import com.google.visualization.datasource.base.ReasonType; -import com.google.visualization.datasource.base.ResponseStatus; -import com.google.visualization.datasource.base.StatusType; -import com.google.visualization.datasource.base.Warning; -import com.google.visualization.datasource.datatable.ColumnDescription; -import com.google.visualization.datasource.datatable.DataTable; -import com.google.visualization.datasource.datatable.TableCell; -import com.google.visualization.datasource.datatable.TableRow; -import com.google.visualization.datasource.datatable.value.DateTimeValue; -import com.google.visualization.datasource.datatable.value.DateValue; -import com.google.visualization.datasource.datatable.value.NumberValue; -import com.google.visualization.datasource.datatable.value.TextValue; -import com.google.visualization.datasource.datatable.value.TimeOfDayValue; -import com.google.visualization.datasource.datatable.value.Value; -import com.google.visualization.datasource.datatable.value.ValueType; - -import junit.framework.TestCase; - -import java.util.List; - -/** - * Tests for JsonRenderer. - * - * @author Nimrod T. - */ -public class JsonRendererTest extends TestCase { - - DataTable testData; - - List rows; - - List colIds; - - @Override - public void setUp() throws Exception { - super.setUp(); - - colIds = Lists.newArrayList(); - - testData = new DataTable(); - ColumnDescription c0 = new ColumnDescription("col0", ValueType.TEXT, "label0"); - ColumnDescription c1 = new ColumnDescription("col1", ValueType.NUMBER, "label1"); - ColumnDescription c2 = new ColumnDescription("col2", ValueType.BOOLEAN, "label2"); - ColumnDescription c3 = new ColumnDescription("col3", ValueType.DATE, "label3"); - ColumnDescription c4 = new ColumnDescription("col4", ValueType.TIMEOFDAY, "label4"); - ColumnDescription c5 = new ColumnDescription("col5", ValueType.DATETIME, "label5"); - - testData.addColumn(c0); - testData.addColumn(c1); - testData.addColumn(c2); - testData.addColumn(c3); - testData.addColumn(c4); - testData.addColumn(c5); - - colIds.add("col0"); - colIds.add("col1"); - colIds.add("col2"); - colIds.add("col3"); - colIds.add("col4"); - colIds.add("col5"); - - rows = Lists.newArrayList(); - - TableRow row = new TableRow(); - row.addCell(new TableCell("aaa")); - row.addCell(new TableCell(222)); - row.addCell(new TableCell(false)); - row.addCell(new TableCell(new DateValue(2001, 10, 14))); - row.addCell(new TableCell(new TimeOfDayValue(12, 11, 13, 14))); - row.addCell(new TableCell(new DateTimeValue(2000, 10, 1, 1, 10, 23, 432))); - rows.add(row); - - row = new TableRow(); - row.addCell(new TableCell("ccc")); - row.addCell(new TableCell(111)); - row.addCell(new TableCell(true)); - row.addCell(new TableCell(new DateValue(2001, 1, 14))); - row.addCell(new TableCell(new TimeOfDayValue(12, 30, 13, 14))); - row.addCell(new TableCell(new DateTimeValue(1000, 11, 1, 1, 10, 23, 432))); - rows.add(row); - - row = new TableRow(); - row.addCell(new TableCell("bbb")); - row.addCell(new TableCell(3)); - row.addCell(new TableCell(true)); - row.addCell(new TableCell(new DateValue(2012, 2, 14))); - row.addCell(new TableCell(new TimeOfDayValue(12, 11, 3, 14))); - row.addCell(new TableCell(new DateTimeValue(2000, 1, 1, 1, 10, 31, 4))); - rows.add(row); - - row = new TableRow(); - row.addCell("ddd"); - row.addCell(222); - row.addCell(false); - row.addCell(new DateValue(1997, 5, 5)); - row.addCell(new TimeOfDayValue(12, 15, 15, 14)); - row.addCell(new DateTimeValue(3100, 1, 2, 15, 15, 1, 0)); - rows.add(row); - - testData.addRows(rows); - } - - @Override - public void tearDown() throws Exception { - super.tearDown(); - testData = null; - rows = null; - } - - public void testEmptyDataTableToJson() { - DataTable dataTable = new DataTable(); - assertEquals("", JsonRenderer.renderDataTable(dataTable, false, false, true)); - assertEquals("", JsonRenderer.renderDataTable(dataTable, false, true, true)); - assertEquals("", JsonRenderer.renderDataTable(dataTable, true, false, true)); - assertEquals("", JsonRenderer.renderDataTable(dataTable, true, true, true)); - } - - public void testAppendCellJson() { - TableCell dateCell = new TableCell(new DateValue(2009, 1, 12)); - TableCell timeofdayCell = new TableCell(new TimeOfDayValue(12, 13, 14, 15)); - TableCell datetimeCell = new TableCell(new DateTimeValue(2009, 1, 12, 12, 13, 14, 15)); - TableCell booleanCell = new TableCell(true); - TableCell numberCell = new TableCell(12.3); - TableCell textCell = new TableCell("aba"); - - - assertEquals("{\"v\":new Date(2009,1,12)}", - JsonRenderer.appendCellJson(dateCell, new StringBuilder(), - true, false, true).toString()); - assertEquals("{\"v\":\"Date(2009,1,12)\"}", - JsonRenderer.appendCellJson(dateCell, new StringBuilder(), - true, false, false).toString()); - assertEquals("{\"v\":[12,13,14,15]}", - JsonRenderer.appendCellJson(timeofdayCell, new StringBuilder(), - true, false, true).toString()); - assertEquals("{\"v\":new Date(2009,1,12,12,13,14)}", //no milliseconds passed - JsonRenderer.appendCellJson(datetimeCell, new StringBuilder(), - true, false, true).toString()); - assertEquals("{\"v\":\"Date(2009,1,12,12,13,14)\"}", //no milliseconds passed - JsonRenderer.appendCellJson(datetimeCell, new StringBuilder(), - true, false, false).toString()); - assertEquals("{\"v\":true}", - JsonRenderer.appendCellJson(booleanCell, new StringBuilder(), - true, false, true).toString()); - assertEquals("{\"v\":12.3}", - JsonRenderer.appendCellJson(numberCell, new StringBuilder(), - true, false, true).toString()); - assertEquals("{\"v\":\"aba\"}", - JsonRenderer.appendCellJson(textCell, new StringBuilder(), - true, false, true).toString()); - - // No formatting still stays the same when there is no formatted value - assertEquals("{\"v\":12.3}", - JsonRenderer.appendCellJson(numberCell, new StringBuilder(), - false, false, true).toString()); - - - dateCell = new TableCell(new DateValue(2009, 1, 12), "2009-2-12"); - - // With formatting - assertEquals("{\"v\":new Date(2009,1,12),\"f\":\"2009-2-12\"}", - JsonRenderer.appendCellJson(dateCell, new StringBuilder(), - true, false, true).toString()); - - // Without formatting - assertEquals("{\"v\":new Date(2009,1,12)}", - JsonRenderer.appendCellJson(dateCell, new StringBuilder(), - false, false, true).toString()); - - TableCell nullCell = new TableCell(Value.getNullValueFromValueType(ValueType.NUMBER)); - - // Null value - assertEquals("", - JsonRenderer.appendCellJson(nullCell, new StringBuilder(), - true, false, true).toString()); - // isLast = true - assertEquals("{\"v\":null}", - JsonRenderer.appendCellJson(nullCell, new StringBuilder(), - true, true, true).toString()); - } - - public void testAppendColumnDescriptionJson() { - ColumnDescription columnDescription = new ColumnDescription("ID", ValueType.BOOLEAN, "LABEL"); - assertEquals("{\"id\":\"ID\",\"label\":\"LABEL\",\"type\":\"boolean\",\"pattern\":\"\"}", - JsonRenderer.appendColumnDescriptionJson( - columnDescription, new StringBuilder()).toString()); - - columnDescription.setPattern("%%%.@@"); - - assertEquals("{\"id\":\"ID\",\"label\":\"LABEL\",\"type\":\"boolean\",\"pattern\":\"%%%.@@\"}", - JsonRenderer.appendColumnDescriptionJson( - columnDescription, new StringBuilder()).toString()); - } - - - public void testSimpleDataTableToJson() throws DataSourceException { - testData = new DataTable(); - ColumnDescription c0 = new ColumnDescription("A", ValueType.TEXT, "col0"); - ColumnDescription c1 = new ColumnDescription("B", ValueType.NUMBER, "col1"); - ColumnDescription c2 = new ColumnDescription("C", ValueType.BOOLEAN, "col2"); - - testData.addColumn(c0); - testData.addColumn(c1); - testData.addColumn(c2); - - rows = Lists.newArrayList(); - - TableRow row = new TableRow(); - row.addCell(new TableCell("aaa")); - row.addCell(new TableCell(new NumberValue(222), "222")); - row.addCell(new TableCell(false)); - rows.add(row); - - row = new TableRow(); - row.addCell(new TableCell("")); - row.addCell(new TableCell(NumberValue.getNullValue())); - row.addCell(new TableCell(true)); - rows.add(row); - - row = new TableRow(); - row.addCell(new TableCell(new TextValue("bbb"), "bbb")); - row.addCell(new TableCell(333)); - row.addCell(new TableCell(true)); - rows.add(row); - - row = new TableRow(); - row.addCell(new TableCell("d'dd")); - row.addCell(new TableCell(222)); - row.addCell(new TableCell(false)); - rows.add(row); - - testData.addRows(rows); - assertEquals( - "{\"cols\":[{\"id\":\"A\",\"label\":\"col0\",\"type\":\"string\",\"pattern\":\"\"}," - + "{\"id\":\"B\",\"label\":\"col1\",\"type\":\"number\",\"pattern\":\"\"}," - + "{\"id\":\"C\",\"label\":\"col2\",\"type\":\"boolean\",\"pattern\":\"\"}]," - + "\"rows\":[{\"c\":[{\"v\":\"aaa\"},{\"v\":222.0,\"f\":\"222\"},{\"v\":false}]}," - + "{\"c\":[{\"v\":\"\"},,{\"v\":true}]}," - + "{\"c\":[{\"v\":\"bbb\"},{\"v\":333.0},{\"v\":true}]}," - + "{\"c\":[{\"v\":\"d\\u0027dd\"},{\"v\":222.0},{\"v\":false}]}]}", - JsonRenderer.renderDataTable(testData, true, true, true).toString()); - - // With non default pattern (the ' will be escaped) - testData.getColumnDescription(1).setPattern("00'\"