├── lib ├── javacc.jar ├── guava-r07.jar ├── junit-4.6.jar ├── easymock-2.5.jar ├── icu4j-4_0_1.jar ├── opencsv-1.8.jar ├── commons-lang-2.4.jar └── commons-logging-1.1.1.jar ├── examples └── src │ ├── html │ ├── csv_example.csv │ ├── getting_started.html │ └── all_examples.html │ └── java │ ├── SimpleExampleServlet.java │ ├── SqlDataSourceServlet.java │ └── CsvDataSourceServlet.java ├── src ├── main │ └── java │ │ └── com │ │ └── google │ │ └── visualization │ │ └── datasource │ │ ├── query │ │ ├── SortOrder.java │ │ ├── ColumnLookup.java │ │ ├── DataTableColumnLookup.java │ │ ├── engine │ │ │ ├── RowTitle.java │ │ │ ├── AggregationPath.java │ │ │ ├── ColumnIndices.java │ │ │ ├── MetaTable.java │ │ │ └── TableRowComparator.java │ │ ├── parser │ │ │ ├── QueryOptionEnum.java │ │ │ ├── GenericsHelper.java │ │ │ └── QueryBuilder.java │ │ ├── ColumnSort.java │ │ ├── AggregationType.java │ │ ├── GenericColumnLookup.java │ │ ├── QueryFilter.java │ │ ├── scalarfunction │ │ │ ├── Upper.java │ │ │ ├── Lower.java │ │ │ ├── ScalarFunction.java │ │ │ ├── CurrentDateTime.java │ │ │ ├── Constant.java │ │ │ ├── Sum.java │ │ │ ├── Product.java │ │ │ ├── Difference.java │ │ │ ├── Modulo.java │ │ │ └── Quotient.java │ │ ├── QueryOptions.java │ │ ├── ColumnIsNullFilter.java │ │ ├── NegationFilter.java │ │ ├── SimpleColumn.java │ │ ├── QueryPivot.java │ │ └── QueryGroup.java │ │ ├── datatable │ │ └── value │ │ │ ├── NullValueException.java │ │ │ ├── NumberValue.java │ │ │ ├── TextValue.java │ │ │ ├── BooleanValue.java │ │ │ └── ValueType.java │ │ ├── base │ │ ├── TypeMismatchException.java │ │ ├── InvalidQueryException.java │ │ ├── StatusType.java │ │ ├── Warning.java │ │ ├── DataSourceException.java │ │ ├── TextFormat.java │ │ ├── OutputType.java │ │ ├── ErrorMessages.java │ │ └── ResponseStatus.java │ │ ├── util │ │ ├── CsvDataSourceException.java │ │ └── SqlDatabaseDescription.java │ │ ├── QueryPair.java │ │ ├── DataSourceServlet.java │ │ ├── DataTableGenerator.java │ │ └── Capabilities.java └── test │ └── java │ └── com │ └── google │ └── visualization │ └── datasource │ ├── base │ ├── StatusTypeTest.java │ ├── ReasonTypeTest.java │ ├── LocaleUtilTest.java │ └── ResponseStatusTest.java │ ├── query │ ├── engine │ │ ├── AggregationPathTest.java │ │ └── ColumnValueAggregatorTest.java │ ├── scalarfunction │ │ ├── LowerTest.java │ │ ├── UpperTest.java │ │ ├── ToDateTest.java │ │ └── DateDiffTest.java │ ├── ColumnColumnFilterTest.java │ └── ColumnValueFilterTest.java │ ├── datatable │ ├── ColumnDescriptionTest.java │ ├── value │ │ └── ValueTest.java │ └── TableRowTest.java │ └── render │ └── EscapeUtilTest.java ├── ReleaseNotes.txt └── pom.xml /lib/javacc.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/google-visualization-java/HEAD/lib/javacc.jar -------------------------------------------------------------------------------- /lib/guava-r07.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/google-visualization-java/HEAD/lib/guava-r07.jar -------------------------------------------------------------------------------- /lib/junit-4.6.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/google-visualization-java/HEAD/lib/junit-4.6.jar -------------------------------------------------------------------------------- /lib/easymock-2.5.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/google-visualization-java/HEAD/lib/easymock-2.5.jar -------------------------------------------------------------------------------- /lib/icu4j-4_0_1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/google-visualization-java/HEAD/lib/icu4j-4_0_1.jar -------------------------------------------------------------------------------- /lib/opencsv-1.8.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/google-visualization-java/HEAD/lib/opencsv-1.8.jar -------------------------------------------------------------------------------- /lib/commons-lang-2.4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/google-visualization-java/HEAD/lib/commons-lang-2.4.jar -------------------------------------------------------------------------------- /examples/src/html/csv_example.csv: -------------------------------------------------------------------------------- 1 | Employee,Manager 2 | Roger,John 3 | Robert,John 4 | Jane,Roger 5 | Jack,Jane 6 | Bob,Jane 7 | -------------------------------------------------------------------------------- /lib/commons-logging-1.1.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/google-visualization-java/HEAD/lib/commons-logging-1.1.1.jar -------------------------------------------------------------------------------- /src/main/java/com/google/visualization/datasource/query/SortOrder.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.query; 16 | 17 | /** 18 | * Sort order. 19 | * 20 | * @author Yoah B.D. 21 | */ 22 | public enum SortOrder { 23 | ASCENDING, 24 | DESCENDING 25 | } 26 | -------------------------------------------------------------------------------- /src/test/java/com/google/visualization/datasource/base/StatusTypeTest.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.base; 16 | 17 | import junit.framework.TestCase; 18 | 19 | /** 20 | * Unit test for StatusType. 21 | * 22 | * @author Nimrod T. 23 | */ 24 | public class StatusTypeTest extends TestCase { 25 | public void testBasic() { 26 | StatusType statusType = StatusType.OK; 27 | assertEquals("ok", statusType.lowerCaseString()); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/google/visualization/datasource/datatable/value/NullValueException.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.datatable.value; 16 | 17 | /** 18 | * Exception that is thrown when there is an attempt to request the value of 19 | * a cell with a null value. 20 | * 21 | * @author Itai R. 22 | */ 23 | public class NullValueException extends RuntimeException { 24 | 25 | /** 26 | * Constructor. 27 | * 28 | * @param message The detailed message of this exception. 29 | */ 30 | public NullValueException(String message) { 31 | super(message); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/test/java/com/google/visualization/datasource/base/ReasonTypeTest.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.base; 16 | 17 | import junit.framework.TestCase; 18 | 19 | 20 | /** 21 | * Unit test for Helper. 22 | * 23 | * @author Yaniv S. 24 | */ 25 | public class ReasonTypeTest extends TestCase { 26 | 27 | public void testBasic() { 28 | // Test getMessageForReasonType with default locale. 29 | assertEquals(ReasonType.INVALID_QUERY.getMessageForReasonType(), "Invalid query"); 30 | } 31 | 32 | public void testLowerString() { 33 | ReasonType reasonType = ReasonType.ACCESS_DENIED; 34 | assertEquals("access_denied", reasonType.lowerCaseString()); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/google/visualization/datasource/base/TypeMismatchException.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.base; 16 | 17 | /** 18 | * This exception is thrown when there is a mismatch between a value type and a column type, 19 | * for example when trying to assign a boolean value to a column of type number. 20 | * 21 | * @author Yaniv S. 22 | */ 23 | public class TypeMismatchException extends DataSourceException { 24 | 25 | /** 26 | * Constructs a new exception with OTHER reason type and a message for the user. 27 | * 28 | * @param message The message for the user. 29 | */ 30 | public TypeMismatchException(String message) { 31 | super(ReasonType.OTHER, message); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/google/visualization/datasource/base/InvalidQueryException.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.base; 16 | 17 | /** 18 | * An exception that is thrown when trying to serve an invalid query. 19 | * A query can fail at parsing time, or at later validations. 20 | * 21 | * @author Yonatan B.Y. 22 | * @author Hillel M. 23 | */ 24 | public class InvalidQueryException extends DataSourceException { 25 | 26 | /** 27 | * Construct a data source exception with an InvalidQuery reason type 28 | * and a message to the user. 29 | * 30 | * @param messageToUser The message for the user. 31 | */ 32 | public InvalidQueryException(String messageToUser) { 33 | super(ReasonType.INVALID_QUERY, messageToUser); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/google/visualization/datasource/util/CsvDataSourceException.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.util; 16 | 17 | import com.google.visualization.datasource.base.DataSourceException; 18 | import com.google.visualization.datasource.base.ReasonType; 19 | 20 | /** 21 | * An exception concerning the csv data source. 22 | * 23 | * @author Nimrod T. 24 | */ 25 | public class CsvDataSourceException extends DataSourceException { 26 | 27 | /** 28 | * Constructor. 29 | * @param reasonType The reason type. 30 | * @param messageToUser A message that will be displayed to the end user. 31 | */ 32 | public CsvDataSourceException(ReasonType reasonType, String messageToUser) { 33 | super(reasonType, messageToUser); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/google/visualization/datasource/query/ColumnLookup.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.query; 16 | 17 | /** 18 | * A column lookup. 19 | * Maps columns to their index in a column container (e.g., DateTable). 20 | * 21 | * @author Liron L. 22 | */ 23 | public interface ColumnLookup { 24 | 25 | /** 26 | * Returns the index of the given column. 27 | * 28 | * @param column The given AbstractColumn. 29 | * 30 | * @return The index of the given column. 31 | */ 32 | public int getColumnIndex(AbstractColumn column); 33 | 34 | /** 35 | * Returns whether or not this ColumnLookup contains the given column. 36 | * 37 | * @param column The column to check. 38 | * 39 | * @return True if column exists, false otherwise. 40 | */ 41 | public boolean containsColumn(AbstractColumn column); 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/google/visualization/datasource/base/StatusType.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.base; 16 | 17 | /** 18 | * An enum value to represent the status of a response. 19 | * 20 | * @author Hillel M. 21 | */ 22 | public enum StatusType { 23 | 24 | /** 25 | * The query completed successfully and the data can be returned. 26 | */ 27 | OK, 28 | 29 | /** 30 | * The query failed to complete. In this case, no data table is passed in the response. 31 | */ 32 | ERROR, 33 | 34 | /** 35 | * The query completed with a warning. In some cases, part of the data is returned. 36 | */ 37 | WARNING; 38 | 39 | /** 40 | * Returns a lower case string of this enum. 41 | * 42 | * @return a lower case string of this enum. 43 | */ 44 | public String lowerCaseString() { 45 | return this.toString().toLowerCase(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /examples/src/html/getting_started.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Getting Started Example 5 | 6 | 7 | 38 | 39 | 40 |

Hello! Data Source!

41 | A table chart that shows data taken from the simple data source. 42 | 43 |
44 | 45 | 46 | -------------------------------------------------------------------------------- /src/test/java/com/google/visualization/datasource/base/LocaleUtilTest.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.base; 16 | 17 | import junit.framework.TestCase; 18 | 19 | import java.util.Locale; 20 | 21 | /** 22 | * Unit test for LocaleUtil. 23 | * 24 | * @author Hillel M. 25 | */ 26 | public class LocaleUtilTest extends TestCase { 27 | 28 | 29 | public void testGetLocalizedMessageFromBundle() { 30 | assertEquals("Sign in", LocaleUtil.getLocalizedMessageFromBundle( 31 | "com.google.visualization.datasource.base.ErrorMessages", "SIGN_IN", null)); 32 | 33 | assertEquals("Sign in", LocaleUtil.getLocalizedMessageFromBundle( 34 | "com.google.visualization.datasource.base.ErrorMessages", "SIGN_IN", Locale.CANADA_FRENCH)); 35 | 36 | assertEquals("Access denied", LocaleUtil.getLocalizedMessageFromBundle( 37 | "com.google.visualization.datasource.base.ErrorMessages", "ACCESS_DENIED", Locale.GERMAN)); 38 | } 39 | 40 | } -------------------------------------------------------------------------------- /src/main/java/com/google/visualization/datasource/query/DataTableColumnLookup.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.query; 16 | 17 | import com.google.visualization.datasource.datatable.DataTable; 18 | 19 | /** 20 | * An adapter between a data table and a column lookup. 21 | * The table does not have to contain rows; only the columns data is used. 22 | * 23 | * @author Liron L. 24 | */ 25 | public class DataTableColumnLookup implements ColumnLookup { 26 | 27 | /** 28 | * The table. 29 | */ 30 | private DataTable table; 31 | 32 | /** 33 | * Creates a new DataTableColumnLookup with the given data table. 34 | * 35 | * @param table The given TableDescription. 36 | */ 37 | public DataTableColumnLookup(DataTable table) { 38 | this.table = table; 39 | } 40 | 41 | @Override 42 | public int getColumnIndex(AbstractColumn column) { 43 | return table.getColumnIndex(column.getId()); 44 | } 45 | 46 | @Override 47 | public boolean containsColumn(AbstractColumn column) { 48 | return table.containsColumn(column.getId()); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/com/google/visualization/datasource/base/Warning.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.base; 16 | 17 | /** 18 | * A warning generated while processing a request. 19 | * 20 | * @author Yonatan B.Y. 21 | */ 22 | public class Warning { 23 | 24 | /** 25 | * The reason for this warning. 26 | */ 27 | private ReasonType reasonType; 28 | 29 | /** 30 | * The warning message to return to the user. 31 | */ 32 | private String messageToUser; 33 | 34 | /** 35 | * Constructs a new exception with a reason type and a message for the user. 36 | * 37 | * @param reasonType The reason type of the exception. 38 | * @param messageToUser The message to the user. 39 | */ 40 | public Warning(ReasonType reasonType, String messageToUser) { 41 | this.messageToUser = messageToUser; 42 | this.reasonType = reasonType; 43 | } 44 | 45 | /** 46 | * Returns the reason. 47 | * 48 | * @return The reason. 49 | */ 50 | public ReasonType getReasonType() { 51 | return reasonType; 52 | } 53 | 54 | /** 55 | * Returns the message. 56 | * 57 | * @return The message. 58 | */ 59 | public String getMessage() { 60 | return messageToUser; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/com/google/visualization/datasource/query/engine/RowTitle.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.query.engine; 16 | 17 | import com.google.visualization.datasource.datatable.value.Value; 18 | 19 | import java.util.List; 20 | 21 | /** 22 | * A "title" (identification) of a row in a pivoted and/or grouped table. 23 | * What identifies a row is the list of values, one value from each of the group-by columns. 24 | * 25 | * @author Yonatan B.Y. 26 | */ 27 | /* package */ class RowTitle { 28 | 29 | /** 30 | * The values of the group-by columns that identify the row. 31 | */ 32 | public List values; 33 | 34 | /** 35 | * Creates a new instance with the given list of group-by column values. 36 | * 37 | * @param values The list of group-by column values. 38 | */ 39 | public RowTitle(List values) { 40 | this.values = values; 41 | } 42 | 43 | @Override 44 | public boolean equals(Object o) { 45 | if (this == o) { 46 | return true; 47 | } 48 | if (!(o instanceof RowTitle)) { 49 | return false; 50 | } 51 | RowTitle other = (RowTitle) o; 52 | return values.equals(other.values); 53 | } 54 | 55 | 56 | @Override 57 | public int hashCode() { 58 | return values.hashCode(); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /ReleaseNotes.txt: -------------------------------------------------------------------------------- 1 | Version 1.1.2 2 | ----------------------------------------- 3 | - Fix security threat of swf injection in jsonp. 4 | 5 | Version 1.1.1 6 | ----------------------------------------- 7 | - Move from google-collect-1.0 to guava-r07. 8 | - Changed Json output to be valid Json format: Added quotation marks around 9 | all keys and string values. Date values are formated as"Date(2011,1,1)". 10 | Note: for jsonp dates remain as they were before and the Date object is 11 | returned in the json string, e.g., new Date(2011,1,1). 12 | - Added setCell method to DataTable class. 13 | - Added support for SKIPPING clause in the query language. 14 | - Added support for MODULO operator in the query language. 15 | - Fixed bug: Response content type for JSON/P is not valid. 16 | - Fixed bug: java.util.TreeMap initialization in QueryEngine causes 17 | compilation error. 18 | - Fixed bug: Where clause with column names that contain spaces does not work 19 | for SQL datasources (Issue 16). 20 | - Fixed bug: SQL data source dates are shifted (Issue 11). 21 | - Changed initialization of Timestamp in SQLDataSourceHelperTest. 22 | - Add a message to the IllegalArgumentException thrown when a 23 | DateValue/DateTimeValue/TimeOfDayValue is created with a GregorianCalendar 24 | that is not GMT. 25 | - Externalized error messages. 26 | - Removed unnecessary servlet from web.xml. 27 | 28 | Version 1.0.2 29 | ----------------------------------------- 30 | - Added maven build (pom.xml). 31 | - Starting with this version this library is available in a maven web repository. 32 | - Added tests. 33 | - Added support for LIKE operator in the query language. 34 | - Fixed bug: Export to HTML double escapes   (Issue 2). 35 | - Fixed bug: Format and label clauses do not work for queries that contain 36 | scalar functions (Issue 3). 37 | - Fixed bug: "is null" in the where clause of a query does not work for SQL 38 | datasources (Issue 4). 39 | - Fixed bug: CSV output does not escape non text values with commas (Issue 5). 40 | -------------------------------------------------------------------------------- /src/main/java/com/google/visualization/datasource/query/parser/QueryOptionEnum.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.query.parser; 16 | 17 | import com.google.visualization.datasource.query.QueryOptions; 18 | 19 | /** 20 | * Helper enum for the auto-generated parser. Holds a single query option (a single element of the 21 | * OPTIONS clause). This is used by the parser, i.e., referenced from the QueryParser.jj file. 22 | * It is needed because queryOptions uses boolean setX() functions, and does not have a datatype 23 | * to hold a single value, and such a datatype is needed for convenience of parsing purposes in 24 | * the .jj parser. You can use the setInQueryOptions() method of this enum, to set the option to 25 | * true in a QueryOptions instance. 26 | * 27 | * @author Yonatan B.Y. 28 | */ 29 | /* package */ enum QueryOptionEnum { 30 | NO_VALUES, 31 | NO_FORMAT; 32 | 33 | /** 34 | * Sets this option to true in the given QueryOptions, leaving its other 35 | * options intact. 36 | * 37 | * @param queryOptions The QueryOptions in which to set the option to true. 38 | */ 39 | public void setInQueryOptions(QueryOptions queryOptions) { 40 | switch (this) { 41 | case NO_VALUES: 42 | queryOptions.setNoValues(true); 43 | break; 44 | case NO_FORMAT: 45 | queryOptions.setNoFormat(true); 46 | break; 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/test/java/com/google/visualization/datasource/query/engine/AggregationPathTest.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.query.engine; 16 | 17 | import com.google.visualization.datasource.datatable.value.NumberValue; 18 | import com.google.visualization.datasource.datatable.value.Value; 19 | 20 | import junit.framework.TestCase; 21 | 22 | import java.util.List; 23 | 24 | /** 25 | * Tests for the AggregationPath class 26 | * 27 | * @author Yoav G. 28 | */ 29 | 30 | public class AggregationPathTest extends TestCase { 31 | 32 | public void simpleTest() { 33 | AggregationPath path = new AggregationPath(); 34 | path.add(new NumberValue(3)); 35 | path.add(new NumberValue(4)); 36 | List values = path.getValues(); 37 | assertEquals(3.0, ((NumberValue) values.get(0)).getValue()); 38 | assertEquals(4.0, ((NumberValue) values.get(1)).getValue()); 39 | } 40 | 41 | public void testReverse() { 42 | AggregationPath path = new AggregationPath(); 43 | path.add(new NumberValue(3)); 44 | path.add(new NumberValue(4)); 45 | path.reverse(); 46 | List values = path.getValues(); 47 | assertEquals(4.0, ((NumberValue) values.get(0)).getValue()); 48 | assertEquals(3.0, ((NumberValue) values.get(1)).getValue()); 49 | } 50 | 51 | public void testEmptyPath() { 52 | AggregationPath path = new AggregationPath(); 53 | path.reverse(); 54 | List values = path.getValues(); 55 | assertEquals(0, values.size()); 56 | } 57 | 58 | } -------------------------------------------------------------------------------- /src/main/java/com/google/visualization/datasource/query/ColumnSort.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.query; 16 | 17 | /** 18 | * A sort definition for a single column. 19 | * This class is immutable. 20 | * 21 | * @author Yoah B.D. 22 | */ 23 | public class ColumnSort { 24 | 25 | /** 26 | * The column by which to sort. 27 | */ 28 | private AbstractColumn column; 29 | 30 | /** 31 | * The requested ordering. 32 | */ 33 | private SortOrder order; 34 | 35 | /** 36 | * Construct and new column sort condition. 37 | * @param column The column by which to sort. 38 | * @param order The requested ordering. 39 | */ 40 | public ColumnSort(AbstractColumn column, SortOrder order) { 41 | this.column = column; 42 | this.order = order; 43 | } 44 | 45 | /** 46 | * Returns the column by which to sort. 47 | * @return The column by which to sort. 48 | */ 49 | public AbstractColumn getColumn() { 50 | return column; 51 | } 52 | 53 | /** 54 | * Returns the requested ordering. 55 | * @return The requested ordering. 56 | */ 57 | public SortOrder getOrder() { 58 | return order; 59 | } 60 | 61 | /** 62 | * Creates a string that when fed to the query parser should return a ColumnSort equal to this 63 | * one. Used mainly for debugging purposes. 64 | * @return A query string. 65 | */ 66 | public String toQueryString() { 67 | return column.toQueryString() + (order == SortOrder.DESCENDING ? " DESC" : ""); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/com/google/visualization/datasource/query/engine/AggregationPath.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.query.engine; 16 | 17 | import com.google.common.collect.ImmutableList; 18 | import com.google.common.collect.Lists; 19 | import com.google.visualization.datasource.datatable.value.Value; 20 | 21 | import java.util.Collections; 22 | import java.util.List; 23 | 24 | /** 25 | * An ordered list of values representing a path in an aggregation tree, from the root to a node. 26 | * Only the values are stored, not the nodes themselves. 27 | * 28 | * @author Yoav G. 29 | */ 30 | 31 | public class AggregationPath { 32 | 33 | /** 34 | * The list of values forming the path. Each value, in turn, is used to 35 | * navigate down from the current node to one of its children. 36 | */ 37 | private List values; 38 | 39 | /** 40 | * Construct an empty path. 41 | */ 42 | public AggregationPath() { 43 | values = Lists.newArrayList(); 44 | } 45 | 46 | /** 47 | * Adds a value to this path. 48 | * 49 | * @param value The value to add. 50 | */ 51 | public void add(Value value) { 52 | values.add(value); 53 | } 54 | 55 | /** 56 | * Returns the list of values. This list is immutable. 57 | * 58 | * @return The list of values. This list is immutable. 59 | */ 60 | 61 | public List getValues() { 62 | return ImmutableList.copyOf(values); 63 | } 64 | 65 | /** 66 | * Reverses this path. 67 | */ 68 | public void reverse() { 69 | Collections.reverse(values); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/com/google/visualization/datasource/QueryPair.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource; 16 | 17 | import com.google.visualization.datasource.query.Query; 18 | 19 | /** 20 | * A product of splitQuery() method, composed of a data source query to be executed first by 21 | * the data source and a second completion query to be executed on the results of the 22 | * first one by the query engine. 23 | * The application of the first query and the second query is equivalent to the application of the 24 | * original query. 25 | * 26 | * @author Yonatan B.Y. 27 | */ 28 | public class QueryPair { 29 | 30 | /** 31 | * The data source query. 32 | */ 33 | private Query dataSourceQuery; 34 | 35 | /** 36 | * The completion query. 37 | */ 38 | private Query completionQuery; 39 | 40 | /** 41 | * Construct a new query pair. 42 | * 43 | * @param dataSourceQuery The data source query. 44 | * @param completionQuery The completion query. 45 | */ 46 | public QueryPair(Query dataSourceQuery, Query completionQuery) { 47 | this.dataSourceQuery = dataSourceQuery; 48 | this.completionQuery = completionQuery; 49 | } 50 | 51 | /** 52 | * Returns the data source query. 53 | * 54 | * @return The data source query. 55 | */ 56 | public Query getDataSourceQuery() { 57 | return dataSourceQuery; 58 | } 59 | 60 | /** 61 | * Returns the completion query. 62 | * 63 | * @return The completion query. 64 | */ 65 | public Query getCompletionQuery() { 66 | return completionQuery; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/com/google/visualization/datasource/DataSourceServlet.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource; 16 | 17 | import java.io.IOException; 18 | 19 | import javax.servlet.http.HttpServlet; 20 | import javax.servlet.http.HttpServletRequest; 21 | import javax.servlet.http.HttpServletResponse; 22 | 23 | /** 24 | * An abstract class for data source servlet implementations. 25 | * 26 | * @author Yaniv S. 27 | */ 28 | public abstract class DataSourceServlet extends HttpServlet implements DataTableGenerator { 29 | 30 | @Override 31 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { 32 | DataSourceHelper.executeDataSourceServletFlow(req, resp, this, isRestrictedAccessMode()); 33 | } 34 | 35 | /** 36 | * Returns a flag that indicates whether the servlet is in restricted-access mode. 37 | * In restricted-access mode the server serves only requests coming from the same domain as the 38 | * server domain (i.e., same origin policy). 39 | * This protects the server from XSRF attacks while limiting the requests to which the server 40 | * can respond. 41 | * 42 | * @return True if this servlet operates in restricted-access mode, false otherwise. 43 | */ 44 | protected boolean isRestrictedAccessMode() { 45 | return true; 46 | } 47 | 48 | @Override 49 | protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException { 50 | doGet(req, resp); 51 | } 52 | 53 | @Override 54 | public Capabilities getCapabilities() { 55 | return Capabilities.NONE; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/com/google/visualization/datasource/DataTableGenerator.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource; 16 | 17 | import com.google.visualization.datasource.base.DataSourceException; 18 | import com.google.visualization.datasource.datatable.DataTable; 19 | import com.google.visualization.datasource.query.Query; 20 | 21 | import javax.servlet.http.HttpServletRequest; 22 | 23 | /** 24 | * An interface for a class that can generate a DataTable. 25 | * 26 | * @author Yaniv S. 27 | */ 28 | public interface DataTableGenerator { 29 | 30 | /** 31 | * Generates the data table. 32 | * 33 | * @param query The query to execute on the underlying data. Ignore this parameter for 34 | * a data source that does not support any capabilities. 35 | * @param request The http request. May contain information that is relevant to generating 36 | * the data table. 37 | * 38 | * @return The generated data table. 39 | * 40 | * @throws DataSourceException If the data could not be generated for any reason. 41 | */ 42 | public DataTable generateDataTable(Query query, HttpServletRequest request) 43 | throws DataSourceException; 44 | 45 | /** 46 | * Returns the capabilities supported by this data table generator. 47 | * 48 | * The query that generateDataTable accepts will only contain clauses 49 | * corresponding to these capabilities. 50 | * (see {@link com.google.visualization.datasource.Capabilities}). 51 | * 52 | * @return The capabilities supported by this datasource. 53 | */ 54 | public Capabilities getCapabilities(); 55 | } 56 | -------------------------------------------------------------------------------- /src/test/java/com/google/visualization/datasource/datatable/ColumnDescriptionTest.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.datatable; 16 | 17 | import com.google.visualization.datasource.datatable.value.ValueType; 18 | 19 | import junit.framework.TestCase; 20 | 21 | /** 22 | * ColumnDescription Tester. 23 | * 24 | * @author Hillel M. 25 | */ 26 | public class ColumnDescriptionTest extends TestCase { 27 | 28 | private ColumnDescription columnDescription; 29 | 30 | public void testConstructor() { 31 | columnDescription = new ColumnDescription("col123", ValueType.TIMEOFDAY, "123"); 32 | assertNotNull(columnDescription); 33 | } 34 | 35 | public void testGetId() { 36 | columnDescription = new ColumnDescription("col123", ValueType.TIMEOFDAY, "123"); 37 | assertEquals("col123", columnDescription.getId()); 38 | } 39 | 40 | public void testGetType() { 41 | columnDescription = new ColumnDescription("col123", ValueType.TIMEOFDAY, "123"); 42 | assertEquals(ValueType.TIMEOFDAY, columnDescription.getType()); 43 | } 44 | 45 | 46 | public void testGetLabel() { 47 | columnDescription = new ColumnDescription("col123", ValueType.TIMEOFDAY, "123"); 48 | assertEquals("123", columnDescription.getLabel()); 49 | } 50 | 51 | public void testColumnProperties() { 52 | columnDescription = new ColumnDescription("col123", ValueType.BOOLEAN, "123"); 53 | assertNull(columnDescription.getCustomProperty("brandy")); 54 | 55 | columnDescription.setCustomProperty("brandy", "cognac"); 56 | assertEquals("cognac", columnDescription.getCustomProperty("brandy")); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/test/java/com/google/visualization/datasource/render/EscapeUtilTest.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.render; 16 | 17 | 18 | import junit.framework.TestCase; 19 | 20 | /** 21 | * Tests for Escape Util. 22 | * 23 | * @author Hillel M. 24 | */ 25 | public class EscapeUtilTest extends TestCase{ 26 | 27 | public static void testJsonEscape() { 28 | // Check ' " < > \ 29 | assertEquals("\\u0027ABC", EscapeUtil.jsonEscape("'ABC")); 30 | assertEquals("\\u0022ABC", EscapeUtil.jsonEscape("\"ABC")); 31 | assertEquals("\\\\", EscapeUtil.jsonEscape("\\")); 32 | assertEquals("\\u003cABC\\u003e", EscapeUtil.jsonEscape("")); 33 | assertEquals("\\u003c/ABC\\u003e", EscapeUtil.jsonEscape("")); 34 | 35 | // Normal string (all keyboard letters but ', ", \, <, >) 36 | String normalString = "`1234567890-=qwertyuiop[];lkjhgfdsazxcvbnm,.//*-+.0~!@#$%^&*()_+" 37 | + "QWERTYUIOP{}|:LKJHGFDSAZXCVBNM?;"; 38 | assertEquals(normalString, EscapeUtil.jsonEscape(normalString)); 39 | 40 | // Weird characters (non readable) 41 | String weirdString = "\n\t\r\\ \u0081\u0010\u2010\u2099\b\f"; 42 | String escapedweirdString = "\\n\\t\\r\\\\ \\u0081\\u0010\\u2010\\u2099\\b\\f"; 43 | assertEquals(escapedweirdString, EscapeUtil.jsonEscape(weirdString)); 44 | 45 | // Normal string in Unicode (pqr) 46 | String normalStringInUnicode = "\u0070\u0071\u0072"; 47 | assertEquals("pqr", EscapeUtil.jsonEscape(normalStringInUnicode)); 48 | 49 | // Non English normal characters (Hebrew - me) 50 | String nonEnglishString = "\u05d0\u05e0\u05d9"; 51 | assertEquals(nonEnglishString, EscapeUtil.jsonEscape(nonEnglishString)); 52 | } 53 | } -------------------------------------------------------------------------------- /src/main/java/com/google/visualization/datasource/query/AggregationType.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.query; 16 | 17 | import com.google.common.collect.Maps; 18 | 19 | import java.util.Map; 20 | 21 | /** 22 | * Enumeration of all possible aggregation types. 23 | * 24 | * @author Yoav G. 25 | * @author Yonatan B.Y. 26 | */ 27 | public enum AggregationType { 28 | SUM("sum"), 29 | COUNT("count"), 30 | MIN("min"), 31 | MAX("max"), 32 | AVG("avg"); 33 | 34 | /** 35 | * The code for this AggregationType. 36 | */ 37 | private String code; 38 | 39 | /** 40 | * Constructor 41 | * 42 | * @param code The code for this AggregationType. 43 | */ 44 | private AggregationType(String code) { 45 | this.code = code; 46 | } 47 | 48 | /** 49 | * Get this AggregationType code. 50 | * 51 | * @return The AggregationType code. 52 | */ 53 | public String getCode() { 54 | return code; 55 | } 56 | 57 | /** 58 | * Returns the correct AggregationType for a given code. 59 | * 60 | * @param code The code for a type. 61 | * 62 | * @return The correct AggregationType for the given code. 63 | */ 64 | public static AggregationType getByCode(String code) { 65 | return codeToAggregationType.get(code); 66 | } 67 | 68 | /** 69 | * Holds the mapping of type code to instances of this class. 70 | */ 71 | private static Map codeToAggregationType; 72 | 73 | /** 74 | * Initializes the static maps. 75 | */ 76 | static { 77 | codeToAggregationType = Maps.newHashMap(); 78 | for (AggregationType type : AggregationType.values()) { 79 | codeToAggregationType.put(type.code, type); 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/main/java/com/google/visualization/datasource/query/parser/GenericsHelper.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.query.parser; 16 | 17 | import com.google.common.collect.Lists; 18 | 19 | import java.util.ArrayList; 20 | import java.util.Arrays; 21 | import java.util.List; 22 | 23 | 24 | /** 25 | * Helper functions to assist the generated parser to deal with generic types. Unfortunately, 26 | * javacc is not good at handling generic types, such as List, inside 27 | * the .jj file. One solution is to use ArrayLists in the .jj file and then convert them 28 | * using this class. This class uses unsafe operations, which is unavoidable. 29 | * 30 | * @author Yonatan B.Y. 31 | */ 32 | /* package */ class GenericsHelper { 33 | private GenericsHelper() 34 | {} 35 | 36 | /** 37 | * Transforms, in an unsafe way, a typed List from a raw ArrayList. 38 | * 39 | * @param list The ArrayList to transform. 40 | * 41 | * @return The new List containing all the elements in list. 42 | */ 43 | /* package */ static List makeTypedList(ArrayList list) { 44 | List result = Lists.newArrayListWithExpectedSize(list.size()); 45 | for (T obj : list) { 46 | result.add(obj); 47 | } 48 | return result; 49 | } 50 | 51 | /** 52 | * Transforms a typed List from a raw array. 53 | * 54 | * @param array The array to transform. 55 | * 56 | * @return The new List containing all the elements in array. 57 | */ 58 | /* package */ static List makeAbstractColumnList(T[] array) { 59 | List result = Lists.newArrayListWithExpectedSize(array.length); 60 | result.addAll(Arrays.asList(array)); 61 | return result; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/com/google/visualization/datasource/query/GenericColumnLookup.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.query; 16 | 17 | import com.google.common.collect.Maps; 18 | 19 | import java.util.Map; 20 | 21 | /** 22 | * This class represents a generic column lookup. It maps an abstract 23 | * column to its index in a table description. 24 | * 25 | * @author Liron L. 26 | */ 27 | public class GenericColumnLookup implements ColumnLookup { 28 | 29 | /** 30 | * A map from the column to its index in the table description. 31 | */ 32 | private Map columnIndexByColumn; 33 | 34 | /** 35 | * Create a GenericColumnLookup (with an empty map). 36 | */ 37 | public GenericColumnLookup() { 38 | columnIndexByColumn = Maps.newHashMap(); 39 | } 40 | 41 | /** 42 | * Clear all data of this GenericColumnLookup. 43 | */ 44 | public void clear() { 45 | columnIndexByColumn.clear(); 46 | } 47 | 48 | /** 49 | * Sets the index of the given column to the given number. 50 | * 51 | * @param col The column to set the index of. 52 | * @param index The index to set for the column. 53 | */ 54 | public void put(AbstractColumn col, int index) { 55 | columnIndexByColumn.put(col, index); 56 | } 57 | 58 | /** 59 | * Returns the column index in the columns of a row (first is zero). 60 | * 61 | * @param column The column. 62 | * 63 | * @return The column index in the columns of a row (first is zero). 64 | */ 65 | public int getColumnIndex(AbstractColumn column) { 66 | return columnIndexByColumn.get(column); 67 | } 68 | 69 | @Override 70 | public boolean containsColumn(AbstractColumn column) { 71 | return columnIndexByColumn.containsKey(column); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/com/google/visualization/datasource/Capabilities.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource; 16 | 17 | /** 18 | * An enumeration of the capabilities provided by a data source. A data source declares the 19 | * capabilities it supports and this information determines how a query is split. 20 | * For example if a data source declares Capibilities.SELECT then the following 21 | * query select A,B sort A limit 20 22 | * will be split as follows: 23 | * query for data source - 'select A,B' 24 | * completion query - 'sort A limit 20' 25 | * 26 | * @author Yonatan B.Y. 27 | */ 28 | public enum Capabilities { 29 | 30 | /** 31 | * Supports: filter, sort, group, limit, and offset. 32 | * Does not support: pivot, options, labels, format or scalar functions. 33 | */ 34 | SQL, 35 | 36 | /** 37 | * Supports: sort, limit, and offset over simple columns. 38 | * Simple columns are those that are not aggregation columns (such as max(a), 39 | * count(b), avg(c)) or scalar function columns (like a+b, c*2, year(d)). 40 | * If calculated columns are created, through scalar functions or aggregation for example, 41 | * the completion query handles the SORT_AND_PAGINATION over the newly created columns. 42 | */ 43 | SORT_AND_PAGINATION, 44 | 45 | /** 46 | * Supports: select over simple columns. 47 | * 48 | * If calculated columns are created, through scalar functions or aggregation for example, 49 | * the completion query handles the SELECT over the newly created columns. 50 | */ 51 | SELECT, 52 | 53 | /** 54 | * Supports all the above capabilities: SQL. SORT_AND_PAGINATION, and SELECT. 55 | */ 56 | ALL, 57 | 58 | /** 59 | * Supports no capabilities. 60 | */ 61 | NONE 62 | } 63 | -------------------------------------------------------------------------------- /src/test/java/com/google/visualization/datasource/datatable/value/ValueTest.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.datatable.value; 16 | 17 | import junit.framework.TestCase; 18 | 19 | /** 20 | * Value Tester. 21 | * 22 | * @author Hillel M. 23 | */ 24 | public class ValueTest extends TestCase { 25 | 26 | public void testCompareTo() { 27 | Value val1 = new DateValue(2007, 1, 23); 28 | Value val2 = new DateValue(2007, 1, 23); 29 | Value val4 = new DateValue(2007, 1, 20); 30 | 31 | Value valTime1 = new TimeOfDayValue(10, 11, 21, 222); 32 | 33 | // Equal objects. 34 | assertTrue(0 == val1.compareTo(val1)); 35 | assertTrue(0 == val1.compareTo(val2)); 36 | assertTrue(0 == val2.compareTo(val1)); 37 | 38 | // Same class x > y. 39 | assertTrue(0 < val2.compareTo(val4)); 40 | assertTrue(0 > val4.compareTo(val2)); 41 | 42 | // Different class x > y. 43 | try { 44 | val2.compareTo(valTime1); 45 | fail(); 46 | } catch (ClassCastException e) { 47 | // Expected behavior. 48 | } 49 | } 50 | 51 | public void testEquals() { 52 | Number number = new Double(-12.3); 53 | Value numberValue1 = new NumberValue(-12.3); 54 | Value numberValue2 = new NumberValue(-12.3); 55 | Value numberValue3 = new NumberValue(12.3343); 56 | Value timeValue = new TimeOfDayValue(12, 1, 2, 3); 57 | 58 | // null == other. 59 | assertFalse(numberValue1.equals(null)); 60 | 61 | // other.Class != this.Class. 62 | assertFalse(numberValue1.equals(timeValue)); 63 | assertFalse(timeValue.equals(numberValue1)); 64 | assertFalse(numberValue1.equals(number)); 65 | 66 | // this == other. 67 | assertTrue(numberValue2.equals(numberValue2)); 68 | 69 | // equal objects. 70 | assertTrue(numberValue1.equals(numberValue2)); 71 | 72 | // not equal Values. 73 | assertFalse(numberValue1.equals(numberValue3)); 74 | assertFalse(numberValue1.equals(timeValue)); 75 | } 76 | } -------------------------------------------------------------------------------- /src/main/java/com/google/visualization/datasource/base/DataSourceException.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.base; 16 | 17 | /** 18 | * An exception to be used by callers and callees of the library. 19 | * Each exception has a type taken from ReasonType, and a 20 | * message that can be used to output an appropriate message to the user. 21 | * 22 | * Example: 23 | * new DataSourceException(ReasonType.InvalidQuery, "The query cannot be empty") 24 | * 25 | * @author Hillel M. 26 | */ 27 | 28 | public class DataSourceException extends Exception { 29 | 30 | /** 31 | * The reason for this exception. Used to set the reason type of this 32 | * execution response by the thrower of this exception. 33 | */ 34 | private ReasonType reasonType; 35 | 36 | /** 37 | * The error message to return to the user. 38 | */ 39 | private String messageToUser = null; 40 | 41 | /** 42 | * A private constructor to prevent using this exception with no message. 43 | */ 44 | private DataSourceException() {} 45 | 46 | /** 47 | * Constructs a new exception with a single message for the user. 48 | * 49 | * @param reasonType The reason type of the exception. 50 | * @param messageToUser The message for the user. 51 | */ 52 | public DataSourceException(ReasonType reasonType, String messageToUser) { 53 | super(messageToUser); 54 | this.messageToUser = messageToUser; 55 | this.reasonType = reasonType; 56 | } 57 | 58 | /** 59 | * Returns the message for the user. 60 | * 61 | * @return The message for the user. 62 | */ 63 | public String getMessageToUser() { 64 | return messageToUser; 65 | } 66 | 67 | /** 68 | * Returns the reason type of this exception. 69 | * 70 | * @return The reason type of this exception. 71 | */ 72 | public ReasonType getReasonType() { 73 | return reasonType; 74 | } 75 | 76 | @Override @Deprecated 77 | public String getMessage() { 78 | return super.getMessage(); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/com/google/visualization/datasource/query/QueryFilter.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.query; 16 | 17 | import com.google.visualization.datasource.datatable.DataTable; 18 | import com.google.visualization.datasource.datatable.TableRow; 19 | 20 | import java.util.List; 21 | import java.util.Set; 22 | 23 | /** 24 | * A query filter. 25 | * Any class that implements this interface can act as a filter, i.e., be the 26 | * part of a query that decides for a given TableRow if that row is part of the 27 | * result set. 28 | * 29 | * @author Yonatan B.Y. 30 | */ 31 | public abstract class QueryFilter { 32 | 33 | /** 34 | * Checks if this row should be part of the result set. 35 | * 36 | * @param table The table containing this row. 37 | * @param row The row to check. 38 | * 39 | * @return true if this row should be part of the result set, false otherwise. 40 | */ 41 | public abstract boolean isMatch(DataTable table, TableRow row); 42 | 43 | /** 44 | * Returns all the columnIds this filter uses. 45 | * 46 | * @return All the columnIds this filter uses. 47 | */ 48 | public abstract Set getAllColumnIds(); 49 | 50 | /** 51 | * Returns a list of all scalarFunctionColumns this filter uses. 52 | * 53 | * @return A list of all scalarFunctionColumns this filter uses. 54 | */ 55 | public abstract List getScalarFunctionColumns(); 56 | 57 | /** 58 | * Returns a list of all aggregation columns this filter uses. This is kept for future use, as 59 | * currently filters are not allowed to have aggregation columns. This is still used currently 60 | * for validation purposes. 61 | * 62 | * @return A list of all aggregation columns this filter uses. 63 | */ 64 | protected abstract List getAggregationColumns(); 65 | 66 | /** 67 | * Returns a string that, when parsed by the query parser, should return an 68 | * identical filter. The string returned does not contain the WHERE keyword. 69 | * 70 | * @return A string form of this filter. 71 | */ 72 | public abstract String toQueryString(); 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/com/google/visualization/datasource/base/TextFormat.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.base; 16 | 17 | import com.ibm.icu.text.UFormat; 18 | 19 | import java.text.FieldPosition; 20 | import java.text.ParsePosition; 21 | 22 | /** 23 | * A UFormat that performs (dummy) formatting and parsing of text (string) values. 24 | * 25 | * This class is required only to be consistent with the UFormat API, its methods do nothing. 26 | * 27 | * @author Hillel M. 28 | */ 29 | public class TextFormat extends UFormat { 30 | 31 | /** 32 | * Formats a TextValue and appends the result to a StringBuffer. 33 | * 34 | * @param obj The object to format. 35 | * @param appendTo The StringBuffer to which the formatted string is appended. 36 | * @param pos A FieldPosition parameter not used in this case. 37 | * 38 | * @return A StringBuffer with the formatted string for this object. 39 | */ 40 | @Override 41 | public StringBuffer format(Object obj, StringBuffer appendTo, FieldPosition pos) { 42 | if ((null == obj) || !(obj instanceof String)) { 43 | throw new IllegalArgumentException(); 44 | } 45 | String text = (String) obj; 46 | appendTo.append(text); 47 | pos.setBeginIndex(0); 48 | if (0 == text.length()) { 49 | pos.setEndIndex(0); 50 | } else { 51 | pos.setEndIndex(text.length() - 1); 52 | } 53 | return appendTo; 54 | } 55 | 56 | /** 57 | * Parse a string into a TextValue. 58 | * 59 | * If this method is used to parse an empty string and it is called via 60 | * Format.parseObject(Object) a ParseException is thrown. 61 | * 62 | * @param source The string to parse from. 63 | * @param pos Marks the end of the parsing or 0 if the parsing failed. 64 | * 65 | * @return A BooleanValue for the parsed string. 66 | * 67 | * @throws NullPointerException if pos is null or source is null. 68 | */ 69 | @Override 70 | public Object parseObject(String source, ParsePosition pos) { 71 | if ((null == pos) || (null == source)) { 72 | throw new NullPointerException(); 73 | } 74 | pos.setIndex(source.length()); 75 | return source; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/test/java/com/google/visualization/datasource/query/scalarfunction/LowerTest.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.query.scalarfunction; 16 | 17 | import com.google.common.collect.Lists; 18 | import com.google.visualization.datasource.base.InvalidQueryException; 19 | import com.google.visualization.datasource.datatable.value.TextValue; 20 | import com.google.visualization.datasource.datatable.value.Value; 21 | import com.google.visualization.datasource.datatable.value.ValueType; 22 | 23 | import junit.framework.TestCase; 24 | 25 | 26 | /** 27 | * Tests for the DateDiff scalar function. 28 | * 29 | * @author Yaniv S. 30 | */ 31 | public class LowerTest extends TestCase { 32 | public void testValidateParameters() { 33 | Lower lower = Lower.getInstance(); 34 | 35 | // Verify that Lower does not accept 0 parameters. 36 | try { 37 | lower.validateParameters(Lists.newArrayList()); 38 | fail(); 39 | } catch (InvalidQueryException e) { 40 | // Do nothing - this is the expected behavior. 41 | } 42 | 43 | // Verify that Lower does not accept more than 1 parameter. 44 | try { 45 | lower.validateParameters(Lists.newArrayList(ValueType.TEXT, 46 | ValueType.TEXT)); 47 | fail(); 48 | } catch (InvalidQueryException e) { 49 | // Do nothing - this is the expected behavior. 50 | } 51 | 52 | // Verify that Lower does not accept a non-Text parameter. 53 | try { 54 | lower.validateParameters(Lists.newArrayList(ValueType.DATE)); 55 | fail(); 56 | } catch (InvalidQueryException e) { 57 | // Do nothing - this is the expected behavior. 58 | } 59 | 60 | // Verify that Lower accepts 1 TEXT parameter. 61 | try { 62 | lower.validateParameters(Lists.newArrayList(ValueType.TEXT)); 63 | } catch (InvalidQueryException e) { 64 | fail(); 65 | } 66 | } 67 | 68 | public void testEvaluate() { 69 | Lower lower = Lower.getInstance(); 70 | 71 | // Test empty string. 72 | TextValue textValue = (TextValue) lower.evaluate( 73 | Lists.newArrayList(new TextValue(""))); 74 | assertEquals(textValue.getValue(), ""); 75 | 76 | // Basic test. 77 | textValue = (TextValue) lower.evaluate( 78 | Lists.newArrayList(new TextValue("AbC"))); 79 | assertEquals(textValue.getValue(), "abc"); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/test/java/com/google/visualization/datasource/query/scalarfunction/UpperTest.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.query.scalarfunction; 16 | 17 | import com.google.common.collect.Lists; 18 | import com.google.visualization.datasource.base.InvalidQueryException; 19 | import com.google.visualization.datasource.datatable.value.TextValue; 20 | import com.google.visualization.datasource.datatable.value.Value; 21 | import com.google.visualization.datasource.datatable.value.ValueType; 22 | 23 | import junit.framework.TestCase; 24 | 25 | 26 | /** 27 | * Tests for the Upper scalar function. 28 | * 29 | * @author Yaniv S. 30 | */ 31 | public class UpperTest extends TestCase { 32 | public void testValidateParameters() { 33 | Upper upper = Upper.getInstance(); 34 | 35 | // Verify that Upper does not accept 0 parameters. 36 | try { 37 | upper.validateParameters(Lists.newArrayList()); 38 | fail(); 39 | } catch (InvalidQueryException e) { 40 | // Do nothing - this is the expected behavior. 41 | } 42 | 43 | // Verify that Upper does not accept more than 1 parameter. 44 | try { 45 | upper.validateParameters(Lists.newArrayList(ValueType.TEXT, 46 | ValueType.TEXT)); 47 | fail(); 48 | } catch (InvalidQueryException e) { 49 | // Do nothing - this is the expected behavior. 50 | } 51 | 52 | // Verify that Upper does not accept a non-Text parameter. 53 | try { 54 | upper.validateParameters(Lists.newArrayList(ValueType.DATE)); 55 | fail(); 56 | } catch (InvalidQueryException e) { 57 | // Do nothing - this is the expected behavior. 58 | } 59 | 60 | // Verify that Upper accepts 1 TEXT parameter. 61 | try { 62 | upper.validateParameters(Lists.newArrayList(ValueType.TEXT)); 63 | } catch (InvalidQueryException e) { 64 | fail(); 65 | } 66 | } 67 | 68 | public void testEvaluate() { 69 | Upper upper = Upper.getInstance(); 70 | 71 | // Test empty string. 72 | TextValue textValue = (TextValue) upper.evaluate( 73 | Lists.newArrayList(new TextValue(""))); 74 | assertEquals(textValue.getValue(), ""); 75 | 76 | // Basic test. 77 | textValue = (TextValue) upper.evaluate( 78 | Lists.newArrayList(new TextValue("aBc"))); 79 | assertEquals(textValue.getValue(), "ABC"); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/com/google/visualization/datasource/query/engine/ColumnIndices.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.query.engine; 16 | 17 | import com.google.common.collect.ArrayListMultimap; 18 | import com.google.common.collect.ImmutableList; 19 | import com.google.visualization.datasource.query.AbstractColumn; 20 | 21 | import java.util.List; 22 | 23 | /** 24 | * Holds a mapping between {@link AbstractColumn}s and lists of indices, i.e., holds a list of 25 | * indices for each column. The indices for a column are the indices in the new datatable, generated 26 | * by a grouping/pivoting operation. There may be many indices for one column because a pivoting 27 | * operation creates a few columns for a single original column. 28 | * 29 | * @author Yonatan B.Y. 30 | */ 31 | /* package */ class ColumnIndices { 32 | 33 | /** 34 | * The indices of the columns. 35 | */ 36 | private ArrayListMultimap columnToIndices; 37 | /** 38 | * Creates an empty instance of this class. 39 | */ 40 | public ColumnIndices() { 41 | columnToIndices = ArrayListMultimap.create(); 42 | } 43 | 44 | /** 45 | * Sets the index of the given column to the given number. 46 | * 47 | * @param col The column to set the index of. 48 | * @param index The index to set for the column. 49 | */ 50 | public void put(AbstractColumn col, int index) { 51 | columnToIndices.put(col, index); 52 | } 53 | 54 | /** 55 | * Returns the index of the given column. If there is more than one index for 56 | * the column, a runtime exception is thrown. 57 | * 58 | * @param col The column to look for. 59 | * 60 | * @return The index of the column. 61 | */ 62 | public int getColumnIndex(AbstractColumn col) { 63 | List indices = columnToIndices.get(col); 64 | if (indices.size() != 1) { 65 | throw new RuntimeException("Invalid use of ColumnIndices."); 66 | } 67 | return indices.get(0); 68 | } 69 | 70 | /** 71 | * Returns the indices of the given column. 72 | * 73 | * @param col The column to look for. 74 | * 75 | * @return The indeices of the column. 76 | */ 77 | public List getColumnIndices(AbstractColumn col) { 78 | return ImmutableList.copyOf(columnToIndices.get(col)); 79 | } 80 | 81 | /** 82 | * Clears the entire map. 83 | */ 84 | public void clear() { 85 | columnToIndices.clear(); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/test/java/com/google/visualization/datasource/datatable/TableRowTest.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.datatable; 16 | 17 | import com.google.visualization.datasource.datatable.value.BooleanValue; 18 | import com.google.visualization.datasource.datatable.value.DateValue; 19 | import com.google.visualization.datasource.datatable.value.NumberValue; 20 | import com.google.visualization.datasource.datatable.value.TextValue; 21 | 22 | import junit.framework.TestCase; 23 | 24 | /** 25 | * Tests for TableRow 26 | * 27 | * @author Yonatan B.Y. 28 | */ 29 | public class TableRowTest extends TestCase { 30 | 31 | @Override 32 | public void setUp() throws Exception { 33 | super.setUp(); 34 | } 35 | 36 | @Override 37 | public void tearDown() throws Exception { 38 | super.tearDown(); 39 | } 40 | 41 | public void testClone() throws Exception { 42 | TableRow row = new TableRow(); 43 | row.addCell(true); 44 | row.addCell(BooleanValue.getNullValue()); 45 | row.addCell(-2.3); 46 | row.addCell("foo"); 47 | row.addCell(new DateValue(2008, 2, 3)); 48 | row.getCell(2).setFormattedValue("bar-2.3"); 49 | row.getCell(4).setCustomProperty("foo", "bar"); 50 | 51 | TableRow clonedRow = row.clone(); 52 | 53 | assertEquals(true, ((BooleanValue) clonedRow.getCell(0).getValue()).getValue()); 54 | assertTrue(clonedRow.getCell(1).isNull()); 55 | assertEquals(-2.3, ((NumberValue) clonedRow.getCell(2).getValue()).getValue()); 56 | assertEquals("foo", ((TextValue) clonedRow.getCell(3).getValue()).getValue()); 57 | assertEquals(3, ((DateValue) clonedRow.getCell(4).getValue()).getDayOfMonth()); 58 | assertEquals("bar-2.3", clonedRow.getCell(2).getFormattedValue()); 59 | assertEquals("bar", clonedRow.getCell(4).getCustomProperty("foo")); 60 | assertEquals(1, clonedRow.getCell(4).getCustomProperties().size()); 61 | 62 | assertTrue(clonedRow != row); 63 | assertTrue(clonedRow.getCell(0) != row.getCell(0)); 64 | assertTrue(clonedRow.getCell(1) != row.getCell(1)); 65 | assertTrue(clonedRow.getCell(4).getCustomProperties() != row.getCell(4).getCustomProperties()); 66 | 67 | row.getCell(0).setCustomProperty("foo2", "bar2"); 68 | assertTrue(clonedRow.getCell(0).getCustomProperties().isEmpty()); 69 | 70 | clonedRow.getCell(3).setCustomProperty("foo3", "bar3"); 71 | assertTrue(row.getCell(3).getCustomProperties().isEmpty()); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/com/google/visualization/datasource/query/scalarfunction/Upper.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.query.scalarfunction; 16 | 17 | import com.google.visualization.datasource.base.InvalidQueryException; 18 | import com.google.visualization.datasource.datatable.value.TextValue; 19 | import com.google.visualization.datasource.datatable.value.Value; 20 | import com.google.visualization.datasource.datatable.value.ValueType; 21 | 22 | import java.util.List; 23 | 24 | /** 25 | * A unary scalar function that changes text to upper case. 26 | * 27 | * @author Yaniv S. 28 | */ 29 | public class Upper implements ScalarFunction { 30 | 31 | /** 32 | * The name of this function. 33 | */ 34 | private static final String FUNCTION_NAME = "upper"; 35 | 36 | /** 37 | * A singleton instance of this class. 38 | */ 39 | private static final Upper INSTANCE = new Upper(); 40 | 41 | /** 42 | * A private constructor, to prevent instantiation other than by the singleton. 43 | */ 44 | private Upper() {} 45 | 46 | /** 47 | * @return The singleton instance of this class. 48 | */ 49 | public static Upper getInstance() { 50 | return INSTANCE; 51 | } 52 | 53 | /** 54 | * {@inheritDoc} 55 | */ 56 | public String getFunctionName() { 57 | return FUNCTION_NAME; 58 | } 59 | 60 | /** 61 | * @param values A list that contains one text value. 62 | * 63 | * @return An uppercase version of the input text value. 64 | */ 65 | public Value evaluate(List values) { 66 | return new TextValue(((TextValue) values.get(0)).getValue().toUpperCase()); 67 | } 68 | 69 | /** 70 | * @return The return type of this function - TEXT. 71 | */ 72 | public ValueType getReturnType(List types) { 73 | return ValueType.TEXT; 74 | } 75 | 76 | /** 77 | * {@inheritDoc} 78 | */ 79 | public void validateParameters(List types) throws InvalidQueryException { 80 | if (types.size() != 1) { 81 | throw new InvalidQueryException(FUNCTION_NAME + 82 | " requires 1 parmaeter"); 83 | } 84 | if (types.get(0) != ValueType.TEXT) { 85 | throw new InvalidQueryException(FUNCTION_NAME + 86 | " takes a text parameter"); 87 | } 88 | } 89 | 90 | /** 91 | * {@inheritDoc} 92 | */ 93 | public String toQueryString(List argumentsQueryStrings) { 94 | return FUNCTION_NAME + "(" + argumentsQueryStrings.get(0) + ")"; 95 | } 96 | } -------------------------------------------------------------------------------- /src/main/java/com/google/visualization/datasource/query/scalarfunction/Lower.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.query.scalarfunction; 16 | 17 | import com.google.visualization.datasource.base.InvalidQueryException; 18 | import com.google.visualization.datasource.datatable.value.TextValue; 19 | import com.google.visualization.datasource.datatable.value.Value; 20 | import com.google.visualization.datasource.datatable.value.ValueType; 21 | 22 | import java.util.List; 23 | 24 | /** 25 | * A unary scalar function that changes text to lower case. 26 | * 27 | * @author Yaniv S. 28 | */ 29 | public class Lower implements ScalarFunction { 30 | 31 | /** 32 | * The name of this function. 33 | */ 34 | private static final String FUNCTION_NAME = "lower"; 35 | 36 | /** 37 | * A singleton instance of this class. 38 | */ 39 | private static final Lower INSTANCE = new Lower(); 40 | 41 | /** 42 | * A private constructor, to prevent instantiation other than by the singleton. 43 | */ 44 | private Lower() {} 45 | 46 | /** 47 | * @return The singleton instance of this class. 48 | */ 49 | public static Lower getInstance() { 50 | return INSTANCE; 51 | } 52 | 53 | /** 54 | * {@inheritDoc} 55 | */ 56 | public String getFunctionName() { 57 | return FUNCTION_NAME; 58 | } 59 | 60 | /** 61 | * @param values A list that contains one text value. 62 | * 63 | * @return A lower-case version of the input text value. 64 | */ 65 | public Value evaluate(List values) { 66 | return new TextValue(((TextValue) values.get(0)).getValue().toLowerCase()); 67 | } 68 | 69 | /** 70 | * @return The return type of this function - TEXT. 71 | */ 72 | public ValueType getReturnType(List types) { 73 | return ValueType.TEXT; 74 | } 75 | 76 | /** 77 | * {@inheritDoc} 78 | */ 79 | public void validateParameters(List types) throws InvalidQueryException { 80 | if (types.size() != 1) { 81 | throw new InvalidQueryException(FUNCTION_NAME + 82 | " requires 1 parmaeter"); 83 | } 84 | if (types.get(0) != ValueType.TEXT) { 85 | throw new InvalidQueryException(FUNCTION_NAME + 86 | " takes a text parameter"); 87 | } 88 | } 89 | 90 | /** 91 | * {@inheritDoc} 92 | */ 93 | public String toQueryString(List argumentsQueryStrings) { 94 | return FUNCTION_NAME + "(" + argumentsQueryStrings.get(0) + ")"; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/main/java/com/google/visualization/datasource/util/SqlDatabaseDescription.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.util; 16 | 17 | /** 18 | * This class contains all information required to connect to the sql database. 19 | * 20 | * @author Liron L. 21 | */ 22 | public class SqlDatabaseDescription { 23 | 24 | /** 25 | * The url of the sql database. 26 | */ 27 | private String url; 28 | 29 | /** 30 | * The user name used to access the sql database. 31 | */ 32 | private String user; 33 | 34 | /** 35 | * The password used to access the sql database. 36 | */ 37 | private String password; 38 | 39 | /** 40 | * The database table name. Has a {@code null} value in case table name is not provided. 41 | */ 42 | private String tableName; 43 | 44 | /** 45 | * Constructs a sql database description. 46 | * 47 | * @param url The url of the sql databasae. 48 | * @param user The user name to access the sql database. 49 | * @param password The password to access the sql database. 50 | * @param tableName The database table name. 51 | */ 52 | public SqlDatabaseDescription(String url, String user, String password, String tableName) { 53 | this.url = url; 54 | this.user = user; 55 | this.password = password; 56 | this.tableName = tableName; 57 | } 58 | 59 | /** 60 | * Returns the url of the sql databasae. 61 | * 62 | * @return The url of the sql databasae. 63 | */ 64 | public String getUrl() { 65 | return url; 66 | } 67 | 68 | /** 69 | * Returns the user name used to access the sql database. 70 | * 71 | * @return The user name used to access the sql database. 72 | * 73 | */ 74 | public String getUser() { 75 | return user; 76 | } 77 | 78 | /** 79 | * Returns the password used to access the sql database. 80 | * 81 | * @return The password used to access the sql database. 82 | */ 83 | public String getPassword() { 84 | return password; 85 | } 86 | 87 | /** 88 | * Sets the password. 89 | * 90 | * @param password The new password to set. 91 | */ 92 | public void setPassword(String password) { 93 | this.password = password; 94 | } 95 | 96 | /** 97 | * Returns the database table name. 98 | * 99 | * @return The database table name. 100 | */ 101 | public String getTableName() { 102 | return tableName; 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/main/java/com/google/visualization/datasource/base/OutputType.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.base; 16 | 17 | /** 18 | * Enumeration of the supported output formats for the data source. 19 | * This enumeration almost exactly correlates to the "out" parameter of the wire protocol, except 20 | * JSONP which is never explicitly specified in the "out" parameter. 21 | * 22 | * @author Nimrod T. 23 | */ 24 | public enum OutputType { 25 | HTML("html"), 26 | JSON("json"), 27 | JSONP("jsonp"), 28 | CSV("csv"), 29 | 30 | /** 31 | * Output type value for tab-separated values encoded using UTF-16 32 | * little-endian with byte-order mark supported by Microsoft Excel. 33 | * 34 | * UTF-8 encoding used by {@link #CSV} output type is not supported by Excel. 35 | * The Unicode encoding understood by Excel is UTF-16 little-endian with 36 | * byte-order mark. Excel also does not support comma delimiter in UTF-16 37 | * encoded files, however, it supports tab delimiter. 38 | * 39 | * The default output filename for Excel should have a {@code .csv} extension in 40 | * spite of containing tab-separated values because Excel does not 41 | * automatically associate with files having {@code .tsv} extension. 42 | */ 43 | TSV_EXCEL("tsv-excel"); 44 | 45 | /** 46 | * The code used to encode the output type in the tqx parameter. 47 | */ 48 | private String code; 49 | 50 | /** 51 | * Constructs a new instance of this class with the given code. 52 | * 53 | * @param code Used to encode the output type in the tqx parameter. 54 | */ 55 | OutputType(String code) { 56 | this.code = code; 57 | } 58 | 59 | /** 60 | * Returns the code for this OutputType. 61 | * 62 | * @return The code for this OutputType. 63 | */ 64 | public String getCode() { 65 | return code; 66 | } 67 | 68 | /** 69 | * Finds the OutputType that matches the given code. 70 | * 71 | * @param code The code to search for. 72 | * 73 | * @return The OutputType that matches the given code or null if none are found. 74 | */ 75 | public static OutputType findByCode(String code) { 76 | for (OutputType t : values()) { 77 | if (t.code.equals(code)) { 78 | return t; 79 | } 80 | } 81 | return null; 82 | } 83 | 84 | /** 85 | * Returns the default OutputType. 86 | * 87 | * @return The default OutputType. 88 | */ 89 | public static OutputType defaultValue() { 90 | return JSON; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /examples/src/java/SimpleExampleServlet.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import com.google.visualization.datasource.DataSourceServlet; 16 | import com.google.visualization.datasource.base.TypeMismatchException; 17 | import com.google.visualization.datasource.datatable.ColumnDescription; 18 | import com.google.visualization.datasource.datatable.DataTable; 19 | import com.google.visualization.datasource.datatable.value.ValueType; 20 | import com.google.visualization.datasource.query.Query; 21 | 22 | import java.util.ArrayList; 23 | 24 | import javax.servlet.http.HttpServletRequest; 25 | 26 | /** 27 | * A demo servlet for serving a simple, constant data table. 28 | * This servlet extends DataSourceServlet. 29 | * 30 | * @author Nimrod T. 31 | */ 32 | public class SimpleExampleServlet extends DataSourceServlet { 33 | 34 | @Override 35 | public DataTable generateDataTable(Query query, HttpServletRequest request) { 36 | // Create a data table. 37 | DataTable data = new DataTable(); 38 | ArrayList cd = new ArrayList(); 39 | cd.add(new ColumnDescription("name", ValueType.TEXT, "Animal name")); 40 | cd.add(new ColumnDescription("link", ValueType.TEXT, "Link to wikipedia")); 41 | cd.add(new ColumnDescription("population", ValueType.NUMBER, "Population size")); 42 | cd.add(new ColumnDescription("vegeterian", ValueType.BOOLEAN, "Vegetarian?")); 43 | 44 | data.addColumns(cd); 45 | 46 | // Fill the data table. 47 | try { 48 | data.addRowFromValues("Aye-aye", "http://en.wikipedia.org/wiki/Aye-aye", 100, true); 49 | data.addRowFromValues("Sloth", "http://en.wikipedia.org/wiki/Sloth", 300, true); 50 | data.addRowFromValues("Leopard", "http://en.wikipedia.org/wiki/Leopard", 50, false); 51 | data.addRowFromValues("Tiger", "http://en.wikipedia.org/wiki/Tiger", 80, false); 52 | } catch (TypeMismatchException e) { 53 | System.out.println("Invalid type!"); 54 | } 55 | return data; 56 | } 57 | 58 | /** 59 | * NOTE: By default, this function returns true, which means that cross 60 | * domain requests are rejected. 61 | * This check is disabled here so examples can be used directly from the 62 | * address bar of the browser. Bear in mind that this exposes your 63 | * data source to xsrf attacks. 64 | * If the only use of the data source url is from your application, 65 | * that runs on the same domain, it is better to remain in restricted mode. 66 | */ 67 | @Override 68 | protected boolean isRestrictedAccessMode() { 69 | return false; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/com/google/visualization/datasource/query/engine/MetaTable.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.query.engine; 16 | 17 | import com.google.common.collect.Maps; 18 | import com.google.visualization.datasource.datatable.TableCell; 19 | 20 | import java.util.Map; 21 | 22 | /** 23 | * Holds the data of a table after pivoting and grouping, indexed by {@link RowTitle} and 24 | * {@link ColumnTitle}. 25 | * 26 | * @author Yonatan B.Y. 27 | */ 28 | /* package */ class MetaTable { 29 | 30 | /** 31 | * The data. A map that gives, for each row and column, a map of the cell 32 | * associated with that row and that column. 33 | */ 34 | private Map> data; 35 | 36 | /** 37 | * Creates an empty instance. 38 | */ 39 | public MetaTable() { 40 | data = Maps.newHashMap(); 41 | } 42 | 43 | /** 44 | * Puts a new value in the MetaTable. 45 | * 46 | * @param rowTitle The row into which the cell should be inserted. 47 | * @param columnTitle The column into which the cell should be inserted. 48 | * @param cell The cell to insert. 49 | */ 50 | public void put(RowTitle rowTitle, ColumnTitle columnTitle, 51 | TableCell cell) { 52 | Map rowData = data.get(rowTitle); 53 | if (rowData == null) { 54 | rowData = Maps.newHashMap(); 55 | data.put(rowTitle, rowData); 56 | } 57 | rowData.put(columnTitle, cell); 58 | } 59 | 60 | /** 61 | * Retrieves a cell from the MetaTable. 62 | * 63 | * @param rowTitle The row from which to retrieve the cell. 64 | * @param columnTitle The column from which to retrieve the cell. 65 | * 66 | * @return The cell that is at row rowTitle and column columnTitle or null 67 | * if no such cell exists. 68 | */ 69 | public TableCell getCell(RowTitle rowTitle, ColumnTitle columnTitle) { 70 | Map rowData = data.get(rowTitle); 71 | if (rowData == null) { 72 | return null; 73 | } 74 | return rowData.get(columnTitle); 75 | } 76 | 77 | /** 78 | * Retrieves an entire row, in the form of a hashtable that maps a ColumnTitle 79 | * to a TableCell. 80 | * 81 | * @param rowTitle The title of the row to retrieve. 82 | * 83 | * @return The row. 84 | */ 85 | public Map getRow(RowTitle rowTitle) { 86 | return data.get(rowTitle); 87 | } 88 | 89 | /** 90 | * Returns true if this MetaTable is empty, i.e., contains no rows. 91 | * 92 | * @return True if this MetaTable is empty. 93 | */ 94 | public boolean isEmpty() { 95 | return data.isEmpty(); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/test/java/com/google/visualization/datasource/base/ResponseStatusTest.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.base; 16 | 17 | import junit.framework.TestCase; 18 | 19 | import java.util.Locale; 20 | 21 | /** 22 | * Unit test for ResponseStatus. 23 | * 24 | * @author Nimrod T. 25 | */ 26 | public class ResponseStatusTest extends TestCase { 27 | public void testBasic() { 28 | // Test getMessageForReasonType with default locale. 29 | assertEquals("Invalid query", ReasonType.INVALID_QUERY.getMessageForReasonType()); 30 | 31 | // Test getMessageForReasonType with specified locale. 32 | assertEquals("Retrieved data was truncated", 33 | ReasonType.DATA_TRUNCATED.getMessageForReasonType(new Locale("en", "US"))); 34 | } 35 | 36 | public void testGetModifiedResponseStatus() { 37 | String urlMessage = "http://www.google.com"; 38 | ResponseStatus responseStatusAccessDenied = new ResponseStatus(StatusType.ERROR, 39 | ReasonType.ACCESS_DENIED, urlMessage); 40 | ResponseStatus responseStatusUserNotAuthenticated = new ResponseStatus(StatusType.ERROR, 41 | ReasonType.USER_NOT_AUTHENTICATED, urlMessage); 42 | ResponseStatus responseStatusUserNotAuthenticatedNoUrl = new ResponseStatus(StatusType.ERROR, 43 | ReasonType.USER_NOT_AUTHENTICATED, "123"); 44 | 45 | // no modification 46 | assertEquals(responseStatusAccessDenied, 47 | ResponseStatus.getModifiedResponseStatus(responseStatusAccessDenied)); 48 | 49 | assertEquals(responseStatusUserNotAuthenticatedNoUrl, 50 | ResponseStatus.getModifiedResponseStatus(responseStatusUserNotAuthenticatedNoUrl)); 51 | 52 | // modified 53 | ResponseStatus modifiedResponse = 54 | ResponseStatus.getModifiedResponseStatus(responseStatusUserNotAuthenticated); 55 | assertEquals(StatusType.ERROR, modifiedResponse.getStatusType()); 56 | assertEquals(ReasonType.USER_NOT_AUTHENTICATED, modifiedResponse.getReasonType()); 57 | String htmlSignInString = "Sign in"; 58 | assertEquals(htmlSignInString, modifiedResponse.getDescription()); 59 | } 60 | 61 | public void testCreateResponseStatus() { 62 | DataSourceException dse = new DataSourceException(ReasonType.INTERNAL_ERROR, "123"); 63 | ResponseStatus responseStatus = ResponseStatus.createResponseStatus(dse); 64 | 65 | assertEquals(StatusType.ERROR, responseStatus.getStatusType()); 66 | assertEquals(ReasonType.INTERNAL_ERROR, responseStatus.getReasonType()); 67 | assertEquals("123", responseStatus.getDescription()); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/com/google/visualization/datasource/query/scalarfunction/ScalarFunction.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.query.scalarfunction; 16 | 17 | import com.google.visualization.datasource.base.InvalidQueryException; 18 | import com.google.visualization.datasource.datatable.value.Value; 19 | import com.google.visualization.datasource.datatable.value.ValueType; 20 | 21 | import java.util.List; 22 | 23 | /** 24 | * A scalar function. 25 | * A scalar function can have any arity, including 0, and can also have dynamic arity. 26 | * It must always produce a single value. The return type of such a function may depend on the 27 | * number and types of its arguments but never on their values. An instance of a class that 28 | * implements this interface can be used within a ScalarFunctionColumn. 29 | * 30 | * @author Liron L. 31 | */ 32 | public interface ScalarFunction { 33 | 34 | /** 35 | * Returns the function's name. 36 | * 37 | * @return The function's name. 38 | */ 39 | String getFunctionName(); 40 | 41 | /** 42 | * Executes the scalar function on the given list of values, and returns the 43 | * Value which is the result of the execution the function. 44 | * 45 | * @param values The given list of parameter values for the scalar function. 46 | * 47 | * @return A Value which is the result of the executing the function. 48 | */ 49 | Value evaluate(List values); 50 | 51 | /** 52 | * Returns the return type of the function, given specific types for its parameters. Some 53 | * functions can be polymorphic, i.e., their return type changes according to the types of their 54 | * parameters. 55 | * 56 | * @param types A list of the types of the function's parameters. 57 | * 58 | * @return The return type of the function. 59 | */ 60 | ValueType getReturnType(List types); 61 | 62 | /** 63 | * Validates that the number and types of the function parameters are valid. 64 | * Throws an exception if they are not valid. 65 | * 66 | * @param types The given types of the function's parameters. 67 | * 68 | * @throws InvalidQueryException Thrown when the parameters are invalid. 69 | */ 70 | void validateParameters(List types) throws InvalidQueryException; 71 | 72 | /** 73 | * Returns a string that when given to the query parser will yield a similar scalar function. 74 | * Takes as arguments the query strings of the arguments. 75 | * 76 | * @param argumentQueryStrings The query strings of the actual arguments. 77 | * 78 | * @return The query string. 79 | */ 80 | String toQueryString(List argumentQueryStrings); 81 | } 82 | -------------------------------------------------------------------------------- /src/test/java/com/google/visualization/datasource/query/ColumnColumnFilterTest.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.query; 16 | 17 | import com.google.visualization.datasource.datatable.ColumnDescription; 18 | import com.google.visualization.datasource.datatable.DataTable; 19 | import com.google.visualization.datasource.datatable.TableCell; 20 | import com.google.visualization.datasource.datatable.TableRow; 21 | import com.google.visualization.datasource.datatable.value.ValueType; 22 | 23 | import junit.framework.TestCase; 24 | 25 | 26 | /** 27 | * Test for ColumnColumnFilter 28 | * 29 | * @author Yonatan B.Y. 30 | */ 31 | public class ColumnColumnFilterTest extends TestCase { 32 | public void testMatch() { 33 | TableRow row = new TableRow(); 34 | row.addCell(new TableCell("a")); 35 | row.addCell(new TableCell(123)); 36 | row.addCell(new TableCell("a")); 37 | 38 | DataTable table = new DataTable(); 39 | table.addColumn(new ColumnDescription("c1", ValueType.TEXT, "c1")); 40 | table.addColumn(new ColumnDescription("c2", ValueType.TEXT, "c2")); 41 | table.addColumn(new ColumnDescription("c3", ValueType.TEXT, "c3")); 42 | 43 | ColumnColumnFilter filter = new ColumnColumnFilter(new SimpleColumn("c1"), 44 | new SimpleColumn("c3"), ComparisonFilter.Operator.LE); 45 | assertTrue(filter.isMatch(table, row)); 46 | } 47 | 48 | public void testNoMatch() { 49 | TableRow row = new TableRow(); 50 | row.addCell(new TableCell("a")); 51 | row.addCell(new TableCell(123)); 52 | row.addCell(new TableCell("a")); 53 | 54 | DataTable table = new DataTable(); 55 | table.addColumn(new ColumnDescription("c1", ValueType.TEXT, "c1")); 56 | table.addColumn(new ColumnDescription("c2", ValueType.TEXT, "c2")); 57 | table.addColumn(new ColumnDescription("c3", ValueType.TEXT, "c3")); 58 | 59 | ColumnColumnFilter filter = new ColumnColumnFilter(new SimpleColumn("c3"), 60 | new SimpleColumn("c1"), ComparisonFilter.Operator.NE); 61 | assertFalse(filter.isMatch(table, row)); 62 | } 63 | 64 | public void testToQueryString() { 65 | ColumnColumnFilter filter1 = new ColumnColumnFilter(new SimpleColumn("c3"), 66 | new AggregationColumn(new SimpleColumn("c4"), AggregationType.AVG), 67 | ComparisonFilter.Operator.NE); 68 | ColumnColumnFilter filter2 = new ColumnColumnFilter( 69 | new AggregationColumn(new SimpleColumn("c4"), AggregationType.SUM), 70 | new SimpleColumn("c1"), ComparisonFilter.Operator.STARTS_WITH); 71 | 72 | assertEquals("`c3` != AVG(`c4`)", filter1.toQueryString()); 73 | assertEquals("SUM(`c4`) STARTS WITH `c1`", filter2.toQueryString()); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /examples/src/java/SqlDataSourceServlet.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import com.google.visualization.datasource.Capabilities; 16 | import com.google.visualization.datasource.DataSourceServlet; 17 | import com.google.visualization.datasource.base.DataSourceException; 18 | import com.google.visualization.datasource.datatable.DataTable; 19 | import com.google.visualization.datasource.query.Query; 20 | import com.google.visualization.datasource.util.SqlDataSourceHelper; 21 | import com.google.visualization.datasource.util.SqlDatabaseDescription; 22 | 23 | import javax.servlet.http.HttpServletRequest; 24 | 25 | /** 26 | * An example data source servlet that can query an SQL database. 27 | * This makes use of the SqlDataSourceHelper class that is part of this library. 28 | * 29 | * Query language operations affect the result. This includes operations 30 | * that are not part of SQL itself, such as pivoting, which is executed by 31 | * the query engine. 32 | * 33 | * Four URL parameters must be specified, these are then passed to 34 | * the underlying SQL DB. The parameters are as follows: 35 | * url - The url of the sql DB. 36 | * user - The username to use when accessing the DB. 37 | * password - The password to use when accessing the DB. 38 | * table - The SQL table name. 39 | * 40 | * @author Yaniv S. 41 | */ 42 | public class SqlDataSourceServlet extends DataSourceServlet { 43 | 44 | /** 45 | * The SQL predefined capabilities set is a special custom set for SQL 46 | * databases. This implements most of the data source capabilities more 47 | * efficiently. 48 | */ 49 | @Override 50 | public Capabilities getCapabilities() { 51 | return Capabilities.SQL; 52 | } 53 | 54 | @Override 55 | public DataTable generateDataTable(Query query, HttpServletRequest request) 56 | throws DataSourceException { 57 | SqlDatabaseDescription dbDescription = new SqlDatabaseDescription( 58 | request.getParameter("url"), 59 | request.getParameter("user"), 60 | request.getParameter("password"), 61 | request.getParameter("table")); 62 | return SqlDataSourceHelper.executeQuery(query, dbDescription); 63 | } 64 | 65 | /** 66 | * NOTE: By default, this function returns true, which means that cross 67 | * domain requests are rejected. 68 | * This check is disabled here so examples can be used directly from the 69 | * address bar of the browser. Bear in mind that this exposes your 70 | * data source to xsrf attacks. 71 | * If the only use of the data source url is from your application, 72 | * that runs on the same domain, it is better to remain in restricted mode. 73 | */ 74 | @Override 75 | protected boolean isRestrictedAccessMode() { 76 | return false; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/test/java/com/google/visualization/datasource/query/ColumnValueFilterTest.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.query; 16 | 17 | import com.google.visualization.datasource.datatable.ColumnDescription; 18 | import com.google.visualization.datasource.datatable.DataTable; 19 | import com.google.visualization.datasource.datatable.TableCell; 20 | import com.google.visualization.datasource.datatable.TableRow; 21 | import com.google.visualization.datasource.datatable.value.DateValue; 22 | import com.google.visualization.datasource.datatable.value.NumberValue; 23 | import com.google.visualization.datasource.datatable.value.TextValue; 24 | import com.google.visualization.datasource.datatable.value.ValueType; 25 | 26 | import junit.framework.TestCase; 27 | 28 | 29 | /** 30 | * Test for ColumnValueFilter 31 | * 32 | * @author Yonatan B.Y. 33 | */ 34 | public class ColumnValueFilterTest extends TestCase { 35 | 36 | public void testVariousFilters() { 37 | TableRow row = new TableRow(); 38 | row.addCell(new TableCell("a")); 39 | row.addCell(new TableCell(123)); 40 | row.addCell(new TableCell("a")); 41 | 42 | DataTable table = new DataTable(); 43 | table.addColumn(new ColumnDescription("c1", ValueType.TEXT, "c1")); 44 | table.addColumn(new ColumnDescription("c2", ValueType.TEXT, "c2")); 45 | table.addColumn(new ColumnDescription("c3", ValueType.TEXT, "c3")); 46 | 47 | ColumnValueFilter filter = new ColumnValueFilter(new SimpleColumn("c2"), 48 | new NumberValue(100), ComparisonFilter.Operator.GE); 49 | assertTrue(filter.isMatch(table, row)); 50 | filter = new ColumnValueFilter(new SimpleColumn("c2"), 51 | new NumberValue(100), ComparisonFilter.Operator.LE, true); 52 | assertTrue(filter.isMatch(table, row)); 53 | filter = new ColumnValueFilter(new SimpleColumn("c2"), 54 | new NumberValue(100), ComparisonFilter.Operator.LE); 55 | assertFalse(filter.isMatch(table, row)); 56 | filter = new ColumnValueFilter(new SimpleColumn("c1"), 57 | new TextValue("b"), ComparisonFilter.Operator.GT); 58 | assertFalse(filter.isMatch(table, row)); 59 | filter = new ColumnValueFilter(new SimpleColumn("c1"), 60 | new TextValue("b"), ComparisonFilter.Operator.LT, true); 61 | assertFalse(filter.isMatch(table, row)); 62 | } 63 | 64 | public void testToQueryString() { 65 | ColumnValueFilter filter1 = new ColumnValueFilter(new SimpleColumn("c2"), 66 | new NumberValue(100.23), ComparisonFilter.Operator.GE); 67 | ColumnValueFilter filter2 = new ColumnValueFilter( 68 | new AggregationColumn(new SimpleColumn("c3"), AggregationType.MAX), 69 | new DateValue(2007, 2, 3), ComparisonFilter.Operator.LIKE, true); 70 | 71 | assertEquals("`c2` >= 100.23", filter1.toQueryString()); 72 | assertEquals("DATE '2007-3-3' LIKE MAX(`c3`)", filter2.toQueryString()); 73 | 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/test/java/com/google/visualization/datasource/query/scalarfunction/ToDateTest.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.query.scalarfunction; 16 | 17 | import com.google.common.collect.Lists; 18 | import com.google.visualization.datasource.base.InvalidQueryException; 19 | import com.google.visualization.datasource.datatable.value.DateTimeValue; 20 | import com.google.visualization.datasource.datatable.value.DateValue; 21 | import com.google.visualization.datasource.datatable.value.NumberValue; 22 | import com.google.visualization.datasource.datatable.value.Value; 23 | import com.google.visualization.datasource.datatable.value.ValueType; 24 | 25 | import junit.framework.TestCase; 26 | 27 | import java.util.List; 28 | 29 | /** 30 | * Tests for the ToDate scalar function. 31 | * 32 | * @author Liron L. 33 | */ 34 | public class ToDateTest extends TestCase { 35 | public void testValidateParameters() throws InvalidQueryException { 36 | ToDate toDate = ToDate.getInstance(); 37 | 38 | // Validate datetime, date, number and string paremeters. 39 | toDate.validateParameters(Lists.newArrayList(ValueType.DATETIME)); 40 | toDate.validateParameters(Lists.newArrayList(ValueType.DATE)); 41 | toDate.validateParameters(Lists.newArrayList(ValueType.NUMBER)); 42 | 43 | // Should throw an exception. 44 | try { 45 | toDate.validateParameters(Lists.newArrayList(ValueType.TIMEOFDAY)); 46 | fail("Should have thrown a ScalarFunctionException: The toDiff " 47 | + "function was given a timeofday parameter to validate."); 48 | } catch (InvalidQueryException e) { 49 | // Expected behavior. 50 | } 51 | 52 | // Should throw an exception. 53 | try { 54 | toDate.validateParameters(Lists.newArrayList(ValueType.DATE, 55 | ValueType.NUMBER)); 56 | fail("Should have thrown a ScalarFunctionException: The toDAte " 57 | + "function was given 2 parameters."); 58 | } catch (InvalidQueryException e) { 59 | // Expected behavior. 60 | } 61 | } 62 | 63 | public void testEvaluate() { 64 | ToDate toDate = ToDate.getInstance(); 65 | List valuesList1 = 66 | Lists.newArrayList(new DateValue(2008, 1, 13)); 67 | List valuesList2 = 68 | Lists.newArrayList( 69 | new DateTimeValue(2008, 2, 23, 9, 12, 22, 333)); 70 | List valuesList3 = 71 | Lists.newArrayList(new NumberValue(1234567890000.53421423424)); 72 | List valuesList4 = 73 | Lists.newArrayList(new NumberValue(-1234567890000.0)); 74 | assertEquals(new DateValue(2008, 1, 13), toDate.evaluate(valuesList1)); 75 | assertEquals(new DateValue(2008, 2, 23), toDate.evaluate(valuesList2)); 76 | assertEquals(new DateValue(2009, 1, 13), toDate.evaluate(valuesList3)); 77 | assertEquals(new DateValue(1930, 10, 18), toDate.evaluate(valuesList4)); 78 | 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /examples/src/html/all_examples.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | All Examples 5 | 6 | 7 | 78 | 79 | 80 |

Hello! Data Source!

81 | A pie chart to show the population of a group of animals. 82 | The data is taken from the simple data source. 83 |
84 | Use this toolbar to get the data in CSV/HTML. 85 |
86 | 87 |

CSV Data Source

88 | An organization chart. 89 | The data is taken from the csv data source. 90 |
91 | 92 |

Advanced Data Source

93 | A bar chart to show planetary masses. 94 | The data is taken from the advanced data source. 95 |
96 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /src/test/java/com/google/visualization/datasource/query/engine/ColumnValueAggregatorTest.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.query.engine; 16 | 17 | import com.google.visualization.datasource.datatable.value.DateValue; 18 | import com.google.visualization.datasource.datatable.value.NumberValue; 19 | import com.google.visualization.datasource.datatable.value.TextValue; 20 | import com.google.visualization.datasource.datatable.value.ValueType; 21 | import com.google.visualization.datasource.query.AggregationType; 22 | 23 | import junit.framework.TestCase; 24 | 25 | /** 26 | * Tests for ColumnValueAggregator.java. 27 | * 28 | * @author Yoav G. 29 | */ 30 | 31 | public class ColumnValueAggregatorTest extends TestCase { 32 | 33 | /** 34 | * Test all functionalities by aggregating two numbers. 35 | */ 36 | public void testNumberAggregation() { 37 | ValueAggregator aggregator = new ValueAggregator(ValueType.NUMBER); 38 | aggregator.aggregate(new NumberValue(1)); 39 | aggregator.aggregate(new NumberValue(3)); 40 | 41 | assertEquals(new NumberValue(4.0), aggregator.getValue(AggregationType.SUM)); 42 | assertEquals(new NumberValue(2.0), aggregator.getValue(AggregationType.AVG)); 43 | assertEquals(new NumberValue(2), aggregator.getValue(AggregationType.COUNT)); 44 | assertEquals(new NumberValue(1.0), aggregator.getValue(AggregationType.MIN)); 45 | assertEquals(new NumberValue(3.0), aggregator.getValue(AggregationType.MAX)); 46 | } 47 | 48 | /** 49 | * Test string aggregation. 50 | */ 51 | public void testStringAggregation() { 52 | ValueAggregator aggregator = new ValueAggregator(ValueType.TEXT); 53 | aggregator.aggregate(new TextValue("a")); 54 | aggregator.aggregate(new TextValue("b")); 55 | 56 | try { 57 | aggregator.getValue(AggregationType.SUM); 58 | fail(); 59 | } catch (UnsupportedOperationException e) { 60 | // Expected behavior. 61 | } 62 | try { 63 | aggregator.getValue(AggregationType.AVG); 64 | fail(); 65 | } catch (UnsupportedOperationException e) { 66 | // Expected behavior. 67 | } 68 | 69 | assertEquals(new NumberValue(2), aggregator.getValue(AggregationType.COUNT)); 70 | assertEquals(new TextValue("a"), aggregator.getValue(AggregationType.MIN)); 71 | assertEquals(new TextValue("b"), aggregator.getValue(AggregationType.MAX)); 72 | 73 | } 74 | 75 | public void testGetValueFromEmptyAggregation() { 76 | ValueAggregator aggregator = new ValueAggregator(ValueType.DATE); 77 | DateValue dateNull = DateValue.getNullValue(); 78 | NumberValue numberNull = NumberValue.getNullValue(); 79 | 80 | assertEquals(new NumberValue(0), aggregator.getValue(AggregationType.COUNT)); 81 | 82 | assertEquals(dateNull, aggregator.getValue(AggregationType.MIN)); 83 | assertEquals(dateNull, aggregator.getValue(AggregationType.MAX)); 84 | 85 | assertEquals(numberNull, aggregator.getValue(AggregationType.AVG)); 86 | assertEquals(numberNull, aggregator.getValue(AggregationType.SUM)); 87 | } 88 | } -------------------------------------------------------------------------------- /src/main/java/com/google/visualization/datasource/query/parser/QueryBuilder.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.query.parser; 16 | 17 | import com.google.visualization.datasource.base.InvalidQueryException; 18 | import com.google.visualization.datasource.base.MessagesEnum; 19 | import com.google.visualization.datasource.query.Query; 20 | 21 | import com.ibm.icu.util.ULocale; 22 | 23 | import org.apache.commons.lang.StringUtils; 24 | import org.apache.commons.logging.Log; 25 | import org.apache.commons.logging.LogFactory; 26 | 27 | 28 | /** 29 | * A singleton class that can parse a user query string, i.e., accept a string such as 30 | * "SELECT dept, max(salary) GROUP BY dept" and return a Query object. This class basically 31 | * wraps the QueryParser class that is auto-generated from the QueryParser.jj specification. 32 | * 33 | * @author Hillel M. 34 | */ 35 | public class QueryBuilder { 36 | 37 | /** 38 | * Log. 39 | */ 40 | private static final Log log = LogFactory.getLog(QueryBuilder.class.getName()); 41 | 42 | /** 43 | * A singleton instance of this class. 44 | */ 45 | private static final QueryBuilder SINGLETON = new QueryBuilder(); 46 | 47 | /** 48 | * Returns the singleton instance of this class. 49 | * 50 | * @return The singleton query builder. 51 | */ 52 | public static QueryBuilder getInstance() { 53 | return SINGLETON; 54 | } 55 | 56 | /** 57 | * Private constructor, to prevent instantiation other than that of the singleton instance. 58 | */ 59 | private QueryBuilder() { 60 | } 61 | 62 | /** 63 | * Parses a user query into a Query object. 64 | * 65 | * @param tqValue The user query string. 66 | * 67 | * @return The parsed Query object. 68 | * 69 | * @throws InvalidQueryException Thrown if the query is invalid. 70 | */ 71 | public Query parseQuery(String tqValue) throws InvalidQueryException { 72 | return parseQuery(tqValue, null); 73 | } 74 | 75 | /** 76 | * Parses a user query into a Query object. 77 | * 78 | * @param tqValue The user query string. 79 | * @param ulocale The user locale. 80 | * 81 | * @return The parsed Query object. 82 | * 83 | * @throws InvalidQueryException Thrown if the query is invalid. 84 | */ 85 | public Query parseQuery(String tqValue, ULocale ulocale) throws InvalidQueryException { 86 | Query query; 87 | if (StringUtils.isEmpty(tqValue)) { 88 | query = new Query(); 89 | } else { 90 | try { 91 | query = QueryParser.parseString(tqValue); 92 | } catch (ParseException ex) { 93 | String messageToUserAndLog = ex.getMessage(); 94 | log.error("Parsing error: " + messageToUserAndLog); 95 | throw new InvalidQueryException(MessagesEnum.PARSE_ERROR.getMessageWithArgs(ulocale, 96 | messageToUserAndLog)); 97 | } 98 | query.setLocaleForUserMessages(ulocale); 99 | query.validate(); 100 | } 101 | return query; 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/main/java/com/google/visualization/datasource/query/scalarfunction/CurrentDateTime.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.query.scalarfunction; 16 | 17 | import com.google.visualization.datasource.base.InvalidQueryException; 18 | import com.google.visualization.datasource.datatable.value.DateTimeValue; 19 | import com.google.visualization.datasource.datatable.value.Value; 20 | import com.google.visualization.datasource.datatable.value.ValueType; 21 | 22 | import com.ibm.icu.util.GregorianCalendar; 23 | import com.ibm.icu.util.TimeZone; 24 | 25 | import java.util.List; 26 | 27 | /** 28 | * A 0-ary function that returns the current datetime. The return type is always DateTime. 29 | * 30 | * @author Liron L. 31 | */ 32 | public class CurrentDateTime implements ScalarFunction { 33 | 34 | /** 35 | * The name of this function. 36 | */ 37 | private static final String FUNCTION_NAME = "now"; 38 | 39 | /** 40 | * A singleton instance of this class. 41 | */ 42 | private static final CurrentDateTime INSTANCE = new CurrentDateTime(); 43 | 44 | /** 45 | * Private constructor, to prevent instantiation other than by the singleton. 46 | */ 47 | private CurrentDateTime() {} 48 | 49 | /** 50 | * Returns the singleton instance of this class. 51 | * 52 | * @return The singleton instance of this class. 53 | */ 54 | public static CurrentDateTime getInstance() { 55 | return INSTANCE; 56 | } 57 | 58 | /** 59 | * {@inheritDoc} 60 | */ 61 | public String getFunctionName() { 62 | return FUNCTION_NAME; 63 | } 64 | 65 | /** 66 | * Evaluates this scalar function. Returns a DateTime with the current time. 67 | * 68 | * @param values Ignored. 69 | * 70 | * @return A DateTime value with the current time. 71 | */ 72 | public Value evaluate(List values) { 73 | return new DateTimeValue(new GregorianCalendar( 74 | TimeZone.getTimeZone("GMT"))); 75 | } 76 | 77 | /** 78 | * Returns the return type of the function. In this case, DATETIME. 79 | * 80 | * @param types Ignored. 81 | * 82 | * @return The type of the returned value: DATETIME. 83 | */ 84 | public ValueType getReturnType(List types) { 85 | return ValueType.DATETIME; 86 | } 87 | 88 | /** 89 | * Validates that there are no parameters given for the function. Throws a 90 | * ScalarFunctionException otherwise. 91 | * 92 | * @param types A list with parameters types. Should be empty for this type of function. 93 | * 94 | * @throws InvalidQueryException Thrown if the parameters are invalid. 95 | */ 96 | public void validateParameters(List types) 97 | throws InvalidQueryException { 98 | if (types.size() != 0) { 99 | throw new InvalidQueryException("The " + FUNCTION_NAME + " function should not get " 100 | + "any parameters"); 101 | } 102 | } 103 | 104 | /** 105 | * {@inheritDoc} 106 | */ 107 | public String toQueryString(List argumentsQueryStrings) { 108 | return FUNCTION_NAME + "()"; 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/test/java/com/google/visualization/datasource/query/scalarfunction/DateDiffTest.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.query.scalarfunction; 16 | 17 | import com.google.common.collect.Lists; 18 | import com.google.visualization.datasource.base.InvalidQueryException; 19 | import com.google.visualization.datasource.datatable.value.DateTimeValue; 20 | import com.google.visualization.datasource.datatable.value.DateValue; 21 | import com.google.visualization.datasource.datatable.value.NumberValue; 22 | import com.google.visualization.datasource.datatable.value.Value; 23 | import com.google.visualization.datasource.datatable.value.ValueType; 24 | 25 | import junit.framework.TestCase; 26 | 27 | import java.util.List; 28 | 29 | /** 30 | * Tests for the DateDiff scalar function. 31 | * 32 | * @author Liron L. 33 | */ 34 | public class DateDiffTest extends TestCase { 35 | public void testValidateParameters() throws InvalidQueryException { 36 | List types = Lists.newArrayList(ValueType.DATE, 37 | ValueType.DATETIME); 38 | DateDiff dateDiff = DateDiff.getInstance(); 39 | 40 | // Validate date paremeter. 41 | dateDiff.validateParameters(types); 42 | 43 | // Should throw an exception. 44 | try { 45 | dateDiff.validateParameters(Lists.newArrayList(ValueType.DATE, 46 | ValueType.NUMBER)); 47 | fail("Should have thrown a ScalarFunctionException: The dateDiff " 48 | + "function was given a number parameter to validate."); 49 | } catch (InvalidQueryException e) { 50 | // do nothing 51 | } 52 | 53 | // Validate datetime paremeter. 54 | types = Lists.newArrayList(ValueType.DATETIME, ValueType.DATETIME); 55 | dateDiff.validateParameters(types); 56 | 57 | // Should throw an exception. 58 | try { 59 | dateDiff.validateParameters(Lists.newArrayList(ValueType.DATE)); 60 | fail("Should have thrown a ScalarFunctionException: The dateDiff " 61 | + "function was given only 1 parameter."); 62 | } catch (InvalidQueryException e) { 63 | // Expected behavior. 64 | } 65 | } 66 | 67 | public void testEvaluate() { 68 | DateDiff dateDiff = DateDiff.getInstance(); 69 | List valuesList1 = 70 | Lists.newArrayList(new DateValue(2008, 1, 13), 71 | new DateValue(2008, 2, 13)); 72 | List valuesList2 = Lists.newArrayList(new DateValue(2008, 1, 13), 73 | new DateTimeValue(2008, 1, 13, 9, 12, 22, 333)); 74 | List valuesList3 = 75 | Lists.newArrayList(new DateTimeValue(2008, 6, 1, 9, 12, 22, 333), 76 | new DateTimeValue(2008, 10, 1, 9, 12, 22, 333)); 77 | List valuesList4 = Lists.newArrayList(new DateTimeValue( 78 | 2008, 10, 1, 9, 12, 22, 333), 79 | new DateTimeValue(2008, 6, 1, 9, 12, 20, 333)); 80 | 81 | assertEquals(new NumberValue(-29), dateDiff.evaluate(valuesList1)); 82 | assertEquals(new NumberValue(0), dateDiff.evaluate(valuesList2)); 83 | assertEquals(new NumberValue(-123), dateDiff.evaluate(valuesList3)); 84 | assertEquals(new NumberValue(123), dateDiff.evaluate(valuesList4)); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/com/google/visualization/datasource/query/scalarfunction/Constant.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.query.scalarfunction; 16 | 17 | import com.google.visualization.datasource.base.InvalidQueryException; 18 | import com.google.visualization.datasource.datatable.value.Value; 19 | import com.google.visualization.datasource.datatable.value.ValueType; 20 | 21 | import java.util.List; 22 | 23 | /** 24 | * A constant function, i.e., a 0-ary function that always returns the same value, given at 25 | * construction time. The value can be of any supported {@link ValueType}. 26 | * 27 | * @author Liron L. 28 | */ 29 | public class Constant implements ScalarFunction { 30 | 31 | /** 32 | * The value of this constant. 33 | */ 34 | private Value value; 35 | 36 | /** 37 | * Constructs a new constant function that always returns the given value. 38 | * 39 | * @param value The value to constantly return. 40 | */ 41 | public Constant(Value value) { 42 | this.value = value; 43 | } 44 | 45 | /** 46 | * {@inheritDoc} 47 | */ 48 | public String getFunctionName() { 49 | return value.toQueryString(); 50 | } 51 | 52 | /** 53 | * Executes the scalar function constant(). The values parameter is ignored. 54 | * Returns the value supplied at construction time. 55 | * 56 | * @param values Ignored. 57 | * 58 | * @return The value supplied at construction time. 59 | */ 60 | public Value evaluate(List values) { 61 | return value; 62 | } 63 | 64 | /** 65 | * Returns the return type of the function. This matches the type of the value 66 | * supplied at construction time. The types parameter is ignored. 67 | * 68 | * @param types Ignored. 69 | * 70 | * @return The return type of this function. 71 | */ 72 | public ValueType getReturnType(List types) { 73 | return value.getType(); 74 | } 75 | 76 | /** 77 | * Validates that there are no parameters given for the function. Throws a 78 | * ScalarFunctionException otherwise. 79 | * 80 | * @param types A list with parameters types. Should be empty for this type of function. 81 | * 82 | * @throws InvalidQueryException Thrown if the parameters are invalid. 83 | */ 84 | public void validateParameters(List types) 85 | throws InvalidQueryException { 86 | if (types.size() != 0) { 87 | throw new InvalidQueryException("The constant function should not get " 88 | + "any parameters"); 89 | } 90 | } 91 | 92 | @Override 93 | public boolean equals(Object o) { 94 | if (o instanceof Constant) { 95 | Constant other = (Constant) o; 96 | return value.equals(other.value); 97 | } 98 | return false; 99 | } 100 | 101 | @Override 102 | public int hashCode() { 103 | return (value == null) ? 0 : value.hashCode(); 104 | } 105 | 106 | /** 107 | * {@inheritDoc} 108 | */ 109 | public String toQueryString(List argumentsQueryStrings) { 110 | return value.toQueryString(); 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 4.0.0 5 | 6 | com.google 7 | google 8 | 1 9 | 10 | com.google.visualization 11 | visualization-datasource 12 | Google Visualization Data Source Library 13 | 1.1.2 14 | This library makes it easy to implement a Visualization data source so that you can 15 | easily chart or visualize your data from any of your data stores. 16 | The library implements the Google Visualization API wire protocol and query language. 17 | You therefore need write only the code required to make your data available to the library in 18 | the form of a data table. 19 | This task is made easier by the provision of abstract classes and helper 20 | functions. 21 | 22 | UTF-8 23 | 24 | 25 | 26 | commons-lang 27 | commons-lang 28 | 2.4 29 | 30 | 31 | commons-logging 32 | commons-logging 33 | 1.1.1 34 | 35 | 36 | com.google.guava 37 | guava 38 | r07 39 | 40 | 41 | com.ibm.icu 42 | icu4j 43 | 4.0.1 44 | 45 | 46 | net.sf.opencsv 47 | opencsv 48 | 1.8 49 | 50 | 51 | javax.servlet 52 | servlet-api 53 | 2.5 54 | provided 55 | 56 | 57 | junit 58 | junit 59 | 4.6 60 | test 61 | 62 | 63 | org.easymock 64 | easymock 65 | 2.5 66 | test 67 | 68 | 69 | 70 | ${basedir}/build 71 | ${basedir}/build/class/main 72 | ${basedir}/build/class/test 73 | 74 | 75 | 76 | org.apache.maven.plugins 77 | maven-compiler-plugin 78 | 79 | 1.6 80 | 1.6 81 | 82 | 83 | 84 | org.codehaus.mojo 85 | javacc-maven-plugin 86 | 2.5 87 | 88 | 89 | javacc 90 | 91 | javacc 92 | 93 | 94 | ${basedir}/src/main/java 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /src/main/java/com/google/visualization/datasource/query/engine/TableRowComparator.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.query.engine; 16 | 17 | import com.google.visualization.datasource.datatable.TableRow; 18 | import com.google.visualization.datasource.datatable.value.Value; 19 | import com.google.visualization.datasource.query.AbstractColumn; 20 | import com.google.visualization.datasource.query.ColumnLookup; 21 | import com.google.visualization.datasource.query.ColumnSort; 22 | import com.google.visualization.datasource.query.QuerySort; 23 | import com.google.visualization.datasource.query.SortOrder; 24 | import com.ibm.icu.util.ULocale; 25 | 26 | import java.util.Comparator; 27 | import java.util.List; 28 | 29 | /** 30 | * A comparator comparing two {@link TableRow}s according to the query's ORDER BY, i.e., 31 | * {@link QuerySort}. 32 | * 33 | * @author Yoah B.D. 34 | */ 35 | /*package*/ class TableRowComparator implements Comparator { 36 | 37 | /** 38 | * The columns to order by, in sequence of importance. 39 | */ 40 | private AbstractColumn[] sortColumns; 41 | 42 | /** 43 | * The sort order of the columns to order by, in sequence of importance. Will 44 | * be of same size as sortColumnIndex. 45 | */ 46 | private SortOrder[] sortColumnOrder; 47 | 48 | /** 49 | * A value comparator. 50 | */ 51 | private Comparator valueComparator; 52 | 53 | /** 54 | * The column lookup. 55 | */ 56 | private ColumnLookup columnLookup; 57 | 58 | /** 59 | * Construct a new TableRowComparator. 60 | * 61 | * @param sort The ordering criteria. 62 | * @param locale The locale defining the order relation of text values. 63 | * @param lookup The column lookup. 64 | */ 65 | public TableRowComparator(QuerySort sort, ULocale locale, ColumnLookup lookup) { 66 | valueComparator = Value.getLocalizedComparator(locale); 67 | columnLookup = lookup; 68 | List columns = sort.getSortColumns(); 69 | sortColumns = new AbstractColumn[columns.size()]; 70 | sortColumnOrder = new SortOrder[columns.size()]; 71 | for (int i = 0; i < columns.size(); i++) { 72 | ColumnSort columnSort = columns.get(i); 73 | sortColumns[i] = columnSort.getColumn(); 74 | sortColumnOrder[i] = columnSort.getOrder(); 75 | } 76 | } 77 | 78 | /** 79 | * Compares two arguments for order. Returns a negative integer, zero, or 80 | * a positive integer if the first argument is less than, equal to, or greater 81 | * than the second. 82 | * 83 | * @param r1 the first row to be compared. 84 | * @param r2 the second row to be compared. 85 | * 86 | * @return a negative integer, zero, or a positive integer as the first 87 | * argument is less than, equal to, or greater than the second. 88 | */ 89 | public int compare(TableRow r1, TableRow r2) { 90 | for (int i = 0; i < sortColumns.length; i++) { 91 | AbstractColumn col = sortColumns[i]; 92 | int cc = valueComparator.compare(col.getValue(columnLookup, r1), 93 | col.getValue(columnLookup, r2)); 94 | if (cc != 0) { 95 | return (sortColumnOrder[i] == SortOrder.ASCENDING) ? cc : -cc; 96 | } 97 | } 98 | return 0; 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/main/java/com/google/visualization/datasource/datatable/value/NumberValue.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.datatable.value; 16 | 17 | /** 18 | * A value of type number. Valid values are double-precision floating-point numbers 19 | * (including integers) or NULL_VALUE. 20 | * 21 | * @author Yoah B.D. 22 | */ 23 | public class NumberValue extends Value { 24 | 25 | /** 26 | * A single static null value. 27 | */ 28 | private static final NumberValue NULL_VALUE = new NumberValue(-9999); 29 | 30 | /** 31 | * Static method to return the null value (same one for all calls). 32 | * @return Null value. 33 | */ 34 | public static NumberValue getNullValue() { 35 | return NULL_VALUE; 36 | } 37 | 38 | /** 39 | * The underlying value. 40 | */ 41 | private double value; 42 | 43 | /** 44 | * Create a new number value. 45 | * 46 | * @param value The underlying value. 47 | */ 48 | public NumberValue(double value) { 49 | this.value = value; 50 | } 51 | 52 | @Override 53 | public ValueType getType() { 54 | return ValueType.NUMBER; 55 | } 56 | 57 | /** 58 | * Returns the underlying value. 59 | * 60 | * @return The underlying value. 61 | */ 62 | public double getValue() { 63 | if (this == NULL_VALUE) { 64 | throw new NullValueException("This null number has no value"); 65 | } 66 | return value; 67 | } 68 | 69 | /** 70 | * Returns the number as a String using default formatting. 71 | * 72 | * @return The number as a String using default formatting. 73 | */ 74 | @Override 75 | public String toString() { 76 | if (this == NULL_VALUE) { 77 | return "null"; 78 | } 79 | return Double.toString(value); 80 | } 81 | 82 | /** 83 | * Tests whether this value is a logical null. 84 | * 85 | * @return Indication of whether the value is null. 86 | */ 87 | @Override 88 | public boolean isNull() { 89 | return (this == NULL_VALUE); 90 | } 91 | 92 | /** 93 | * Compares this value to another value of the same type. 94 | * 95 | * @param other Other value. 96 | * 97 | * @return 0 if equal, negative if this is smaller, positive if larger. 98 | */ 99 | @Override 100 | public int compareTo(Value other) { 101 | if (this == other) { 102 | return 0; // If same value, or both are null. 103 | } 104 | NumberValue otherNumber = (NumberValue) other; 105 | if (isNull()) { 106 | return -1; 107 | } 108 | if (otherNumber.isNull()) { 109 | return 1; 110 | } 111 | return Double.compare(value, otherNumber.value); 112 | } 113 | 114 | /** 115 | * Returns a hash code for this number value. 116 | * 117 | * @return A hash code for this number value. 118 | */ 119 | @Override 120 | public int hashCode() { 121 | if (isNull()) { 122 | return 0; 123 | } 124 | return new Double(value).hashCode(); 125 | } 126 | 127 | @Override 128 | public Number getObjectToFormat() { 129 | if (isNull()) { 130 | return null; 131 | } 132 | return value; 133 | } 134 | 135 | /** 136 | * {@inheritDoc} 137 | */ 138 | @Override 139 | protected String innerToQueryString() { 140 | return Double.toString(value); 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /src/main/java/com/google/visualization/datasource/query/QueryOptions.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.query; 16 | 17 | /** 18 | * Options definition for a query. 19 | * Holds options for the query that fall under the options clause. 20 | * 21 | * @author Yonatan B.Y. 22 | */ 23 | public class QueryOptions { 24 | 25 | /** 26 | * Should be set to indicate not to return the values, but only the column 27 | * labels and types (table description). 28 | */ 29 | private boolean noValues; 30 | 31 | /** 32 | * Should be set to indicate not to format the values, but to return only the 33 | * raw data. By default returns both raw and formatted values. 34 | */ 35 | private boolean noFormat; 36 | 37 | /** 38 | * Constructs query options with all boolean options set to false. 39 | */ 40 | public QueryOptions() { 41 | noValues = false; 42 | noFormat = false; 43 | } 44 | 45 | /** 46 | * Returns the value of the noValues option. 47 | * 48 | * @return The value of the noValues option. 49 | */ 50 | public boolean isNoValues() { 51 | return noValues; 52 | } 53 | 54 | /** 55 | * Sets the value of the noValues option. 56 | * 57 | * @param noValues The new value of the noValues option. 58 | */ 59 | public void setNoValues(boolean noValues) { 60 | this.noValues = noValues; 61 | } 62 | 63 | /** 64 | * Returns the value of the noFormat option. 65 | * 66 | * @return The value of the noFormat option. 67 | */ 68 | public boolean isNoFormat() { 69 | return noFormat; 70 | } 71 | 72 | /** 73 | * Sets the value of the noFormat option. 74 | * 75 | * @param noFormat The new value of the noFormat option. 76 | */ 77 | public void setNoFormat(boolean noFormat) { 78 | this.noFormat = noFormat; 79 | } 80 | 81 | /** 82 | * Returns true if all options are set to their default values. 83 | * 84 | * @return True if all options are set to their default values. 85 | */ 86 | public boolean isDefault() { 87 | return !noFormat && !noValues; 88 | } 89 | 90 | @Override 91 | public int hashCode() { 92 | final int prime = 31; 93 | int result = 1; 94 | result = prime * result + (noFormat ? 1231 : 1237); 95 | result = prime * result + (noValues ? 1231 : 1237); 96 | return result; 97 | } 98 | 99 | @Override 100 | public boolean equals(Object obj) { 101 | if (this == obj) { 102 | return true; 103 | } 104 | if (obj == null) { 105 | return false; 106 | } 107 | if (getClass() != obj.getClass()) { 108 | return false; 109 | } 110 | QueryOptions other = (QueryOptions) obj; 111 | if (noFormat != other.noFormat) { 112 | return false; 113 | } 114 | if (noValues != other.noValues) { 115 | return false; 116 | } 117 | return true; 118 | } 119 | 120 | /** 121 | * Returns a string that when fed to the query parser should return a QueryOptions equal to this 122 | * one. Used mainly for debugging purposes. The string returned does not contain the 123 | * OPTIONS keyword. 124 | * 125 | * @return The query string. 126 | */ 127 | public String toQueryString() { 128 | return (noValues ? "NO_VALUES" : "") + (noFormat ? "NO_FORMAT" : ""); 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /src/main/java/com/google/visualization/datasource/query/ColumnIsNullFilter.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.query; 16 | 17 | import com.google.common.collect.Sets; 18 | import com.google.visualization.datasource.datatable.DataTable; 19 | import com.google.visualization.datasource.datatable.TableRow; 20 | 21 | import java.util.List; 22 | import java.util.Set; 23 | 24 | /** 25 | * A filter that matches null values. Its isMatch function returns true if 26 | * the value at the column is a null value (as defined by TableCell.isNull()). 27 | * 28 | * @author Yonatan B.Y. 29 | */ 30 | public class ColumnIsNullFilter extends QueryFilter { 31 | 32 | /** 33 | * The ID of the column that should be null. 34 | */ 35 | private AbstractColumn column; 36 | 37 | /** 38 | * Constructs a new instance of this class with the given column ID. 39 | * 40 | * @param column The column that should be null. 41 | */ 42 | public ColumnIsNullFilter(AbstractColumn column) { 43 | this.column = column; 44 | } 45 | 46 | /** 47 | * Returns the column that should be null. 48 | * 49 | * @return The column that should be null. 50 | */ 51 | public AbstractColumn getColumn() { 52 | return column; 53 | } 54 | 55 | /** 56 | * {@inheritDoc} 57 | */ 58 | @Override 59 | public Set getAllColumnIds() { 60 | return Sets.newHashSet(column.getAllSimpleColumnIds()); 61 | } 62 | 63 | /** 64 | * Returns a list of all scalarFunctionColumns this filter uses, in this case 65 | * the scalarFunctionColumns in column (e.g, in the filter 'year(a) is null' 66 | * it will return year(a). 67 | * 68 | * @return A list of all scalarFunctionColumns this filter uses. 69 | */ 70 | @Override 71 | public List getScalarFunctionColumns() { 72 | return column.getAllScalarFunctionColumns(); 73 | } 74 | 75 | /** 76 | * {@inheritDoc} 77 | */ 78 | @Override 79 | protected List getAggregationColumns() { 80 | return column.getAllAggregationColumns(); 81 | } 82 | 83 | /** 84 | * {@inheritDoc} 85 | */ 86 | @Override 87 | public boolean isMatch(DataTable table, TableRow row) { 88 | DataTableColumnLookup lookup = new DataTableColumnLookup(table); 89 | return column.getValue(lookup, row).isNull(); 90 | } 91 | 92 | /** 93 | * {@inheritDoc} 94 | */ 95 | @Override 96 | public String toQueryString() { 97 | return column.toQueryString() + " IS NULL"; 98 | } 99 | 100 | @Override 101 | public int hashCode() { 102 | final int prime = 31; 103 | int result = 1; 104 | result = prime * result + ((column == null) ? 0 : column.hashCode()); 105 | return result; 106 | } 107 | 108 | @Override 109 | public boolean equals(Object obj) { 110 | if (this == obj) { 111 | return true; 112 | } 113 | if (obj == null) { 114 | return false; 115 | } 116 | if (getClass() != obj.getClass()) { 117 | return false; 118 | } 119 | ColumnIsNullFilter other = (ColumnIsNullFilter) obj; 120 | if (column == null) { 121 | if (other.column != null) { 122 | return false; 123 | } 124 | } else if (!column.equals(other.column)) { 125 | return false; 126 | } 127 | return true; 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /src/main/java/com/google/visualization/datasource/query/NegationFilter.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.query; 16 | 17 | import com.google.visualization.datasource.datatable.DataTable; 18 | import com.google.visualization.datasource.datatable.TableRow; 19 | 20 | import java.util.List; 21 | import java.util.Set; 22 | 23 | /** 24 | * A negation filter. 25 | * Holds a sub-filter and negates its result, acting like the NOT operator. 26 | * 27 | * @author Yonatan B.Y. 28 | */ 29 | public class NegationFilter extends QueryFilter { 30 | 31 | /** 32 | * The sub-filter of this negation filter. 33 | */ 34 | private QueryFilter subFilter; 35 | 36 | /** 37 | * Constructs a negation filter, with the given sub-filter. 38 | * 39 | * @param subFilter The sub-filter of this negation filter. 40 | */ 41 | public NegationFilter(QueryFilter subFilter) { 42 | this.subFilter = subFilter; 43 | } 44 | 45 | /** 46 | * Implements isMatch (from the QueryFilter interface) by recursively calling 47 | * isMatch on the sub-filter and negating the result. 48 | * 49 | * @param table The table containing this row. 50 | * @param row The row to check. 51 | * 52 | * @return true if this row should be part of the result set, false otherwise. 53 | */ 54 | @Override 55 | public boolean isMatch(DataTable table, TableRow row) { 56 | return !subFilter.isMatch(table, row); 57 | } 58 | 59 | /** 60 | * Returns all the columnIds this filter uses, in this case exactly all the 61 | * columnIds that the sub-filter uses. 62 | * 63 | * @return All the columnIds this filter uses. 64 | */ 65 | @Override 66 | public Set getAllColumnIds() { 67 | return subFilter.getAllColumnIds(); 68 | } 69 | 70 | /** 71 | * Returns a list of all scalarFunctionColumns this filter uses, in this case 72 | * the scalarFunctionColumns its sub-filter uses. 73 | * 74 | * @return A list of all scalarFunctionColumns this filter uses. 75 | */ 76 | @Override 77 | public List getScalarFunctionColumns() { 78 | return subFilter.getScalarFunctionColumns(); 79 | } 80 | 81 | /** 82 | * {@InheritDoc} 83 | */ 84 | @Override 85 | protected List getAggregationColumns() { 86 | return subFilter.getAggregationColumns(); 87 | } 88 | 89 | /** 90 | * Returns the sub-filter associated with this NegationFilter. 91 | * 92 | * @return The sub-filter associated with this NegationFilter. 93 | */ 94 | public QueryFilter getSubFilter() { 95 | return subFilter; 96 | } 97 | 98 | /** 99 | * {@inheritDoc} 100 | */ 101 | @Override 102 | public String toQueryString() { 103 | return "NOT (" + subFilter.toQueryString() + ")"; 104 | } 105 | 106 | @Override 107 | public int hashCode() { 108 | final int prime = 31; 109 | int result = 1; 110 | result = prime * result + ((subFilter == null) ? 0 : subFilter.hashCode()); 111 | return result; 112 | } 113 | 114 | @Override 115 | public boolean equals(Object obj) { 116 | if (this == obj) { 117 | return true; 118 | } 119 | if (obj == null) { 120 | return false; 121 | } 122 | if (getClass() != obj.getClass()) { 123 | return false; 124 | } 125 | NegationFilter other = (NegationFilter) obj; 126 | if (subFilter == null) { 127 | if (other.subFilter != null) { 128 | return false; 129 | } 130 | } else if (!subFilter.equals(other.subFilter)) { 131 | return false; 132 | } 133 | return true; 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /src/main/java/com/google/visualization/datasource/query/SimpleColumn.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.query; 16 | 17 | import com.google.common.collect.Lists; 18 | import com.google.visualization.datasource.datatable.DataTable; 19 | import com.google.visualization.datasource.datatable.value.ValueType; 20 | 21 | import java.util.List; 22 | 23 | /** 24 | * A column referred to by an explicit string ID. 25 | * 26 | * @author Yonatan B.Y. 27 | */ 28 | public class SimpleColumn extends AbstractColumn { 29 | 30 | /** 31 | * The explicit string ID of the column. 32 | */ 33 | private String columnId; 34 | 35 | /** 36 | * Creates a new instance of this class, with the given column ID. 37 | * 38 | * @param columnId The column ID. 39 | */ 40 | public SimpleColumn(String columnId) { 41 | this.columnId = columnId; 42 | } 43 | 44 | /** 45 | * Returns the column ID. 46 | * 47 | * @return The column ID. 48 | */ 49 | public String getColumnId() { 50 | return columnId; 51 | } 52 | 53 | @Override 54 | public String getId() { 55 | return columnId; 56 | } 57 | 58 | @Override 59 | public List getAllSimpleColumnIds() { 60 | return Lists.newArrayList(columnId); 61 | } 62 | 63 | @Override 64 | public boolean equals(Object o) { 65 | if (o instanceof SimpleColumn) { 66 | SimpleColumn other = (SimpleColumn) o; 67 | return columnId.equals(other.columnId); 68 | } 69 | return false; 70 | } 71 | 72 | @Override 73 | public int hashCode() { 74 | int hash = 1279; // Some arbitrary prime number. 75 | hash = (hash * 17) + columnId.hashCode(); 76 | return hash; 77 | } 78 | 79 | @Override 80 | public String toString() { 81 | return columnId; 82 | } 83 | 84 | /** 85 | * Returns a list of all simple columns. In this case, returns only itself. 86 | * 87 | * @return A list of all simple columns. 88 | */ 89 | @Override 90 | public List getAllSimpleColumns() { 91 | return Lists.newArrayList(this); 92 | } 93 | 94 | /** 95 | * Returns a list of all aggregation columns. In this case, returns an empty 96 | * list. 97 | * 98 | * @return A list of all aggregation columns. 99 | */ 100 | @Override 101 | public List getAllAggregationColumns() { 102 | return Lists.newArrayList(); 103 | } 104 | 105 | /** 106 | * Returns a list of all scalar function columns. In this case, returns an 107 | * empty list. 108 | * 109 | * @return A list of all scalar function columns. 110 | */ 111 | @Override 112 | public List getAllScalarFunctionColumns() { 113 | return Lists.newArrayList(); 114 | } 115 | 116 | /** 117 | * Checks if the column is valid. In this case always does nothing. 118 | * 119 | * @param dataTable The data table. 120 | */ 121 | @Override 122 | public void validateColumn(DataTable dataTable) { 123 | } 124 | 125 | /** 126 | * Returns the value type of the column. In this case returns the value type 127 | * of the column itself. 128 | * 129 | * @param dataTable The data table. 130 | * 131 | * @return the value type of the column. 132 | */ 133 | @Override 134 | public ValueType getValueType(DataTable dataTable) { 135 | return dataTable.getColumnDescription(columnId).getType(); 136 | } 137 | 138 | @Override 139 | public String toQueryString() { 140 | if (columnId.contains("`")) { 141 | throw new RuntimeException("Column ID cannot contain backtick (`)"); 142 | } 143 | return "`" + columnId + "`"; 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /src/main/java/com/google/visualization/datasource/query/scalarfunction/Sum.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.query.scalarfunction; 16 | 17 | import com.google.visualization.datasource.base.InvalidQueryException; 18 | import com.google.visualization.datasource.datatable.value.NumberValue; 19 | import com.google.visualization.datasource.datatable.value.Value; 20 | import com.google.visualization.datasource.datatable.value.ValueType; 21 | 22 | import java.util.List; 23 | 24 | /** 25 | * The binary scalar function sum(). 26 | * Returns the sum of two number values. 27 | * 28 | * @author Liron L. 29 | */ 30 | public class Sum implements ScalarFunction { 31 | 32 | /** 33 | * The name of this function. 34 | */ 35 | private static final String FUNCTION_NAME = "sum"; 36 | 37 | /** 38 | * A singleton instance of this class. 39 | */ 40 | private static final Sum INSTANCE = new Sum(); 41 | 42 | /** 43 | * A private constructor, to prevent instantiation other than by the singleton. 44 | */ 45 | private Sum() {} 46 | 47 | /** 48 | * Returns the singleton instance of this class. 49 | * 50 | * @return The singleton instance of this class. 51 | */ 52 | public static Sum getInstance() { 53 | return INSTANCE; 54 | } 55 | 56 | /** 57 | * {@inheritDoc} 58 | */ 59 | public String getFunctionName() { 60 | return FUNCTION_NAME; 61 | } 62 | 63 | /** 64 | * Executes the scalar function sum() on the given values. Returns the sum of 65 | * the given values. All values are number values. 66 | * The method does not validate the parameters, the user must check the 67 | * parameters before calling this method. 68 | * 69 | * @param values A list of values on which the scalar function is performed. 70 | * 71 | * @return Value with the sum of all given values, or number null value if one 72 | * of the values is null. 73 | */ 74 | public Value evaluate(List values) { 75 | if (values.get(0).isNull() || values.get(1).isNull()) { 76 | return NumberValue.getNullValue(); 77 | } 78 | double sum = ((NumberValue) values.get(0)).getValue() + 79 | ((NumberValue) values.get(1)).getValue(); 80 | return new NumberValue(sum); 81 | } 82 | 83 | /** 84 | * Returns the return type of the function. In this case, NUMBER. The method 85 | * does not validate the parameters, the user must check the parameters 86 | * before calling this method. 87 | * 88 | * @param types A list of the types of the scalar function parameters. 89 | * 90 | * @return The type of the returned value: Number. 91 | */ 92 | public ValueType getReturnType(List types) { 93 | return ValueType.NUMBER; 94 | } 95 | 96 | /** 97 | * Validates that all function parameters are of type NUMBER, and that there 98 | * are exactly 2 parameters. Throws a ScalarFunctionException otherwise. 99 | * 100 | * @param types A list of parameter types. 101 | * 102 | * @throws InvalidQueryException Thrown if the parameters are invalid. 103 | */ 104 | public void validateParameters(List types) throws InvalidQueryException { 105 | if (types.size() != 2) { 106 | throw new InvalidQueryException("The function " + FUNCTION_NAME 107 | + " requires 2 parmaeters "); 108 | } 109 | for (ValueType type : types) { 110 | if (type != ValueType.NUMBER) { 111 | throw new InvalidQueryException("Can't perform the function " 112 | + FUNCTION_NAME + " on values that are not numbers"); 113 | } 114 | } 115 | } 116 | 117 | /** 118 | * {@inheritDoc} 119 | */ 120 | public String toQueryString(List argumentsQueryStrings) { 121 | return "(" + argumentsQueryStrings.get(0) + " + " + argumentsQueryStrings.get(1) + ")"; 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/main/java/com/google/visualization/datasource/query/scalarfunction/Product.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.query.scalarfunction; 16 | 17 | import com.google.visualization.datasource.base.InvalidQueryException; 18 | import com.google.visualization.datasource.datatable.value.NumberValue; 19 | import com.google.visualization.datasource.datatable.value.Value; 20 | import com.google.visualization.datasource.datatable.value.ValueType; 21 | 22 | import java.util.List; 23 | 24 | /** 25 | * The binary scalar function product(). 26 | * Returns the product of two number values. 27 | * 28 | * @author Liron L. 29 | */ 30 | public class Product implements ScalarFunction { 31 | 32 | /** 33 | * The name of this function. 34 | */ 35 | private static final String FUNCTION_NAME = "product"; 36 | 37 | /** 38 | * A singleton instance of this class. 39 | */ 40 | private static final Product INSTANCE = new Product(); 41 | 42 | /** 43 | * A private constructor, to prevent instantiation other than by the singleton. 44 | */ 45 | private Product() {} 46 | 47 | /** 48 | * Returns the singleton instance of this class. 49 | * 50 | * @return The singleton instance of this class. 51 | */ 52 | public static Product getInstance() { 53 | return INSTANCE; 54 | } 55 | 56 | /** 57 | * {@inheritDoc} 58 | */ 59 | public String getFunctionName() { 60 | return FUNCTION_NAME; 61 | } 62 | 63 | /** 64 | * Executes the scalar function product() on the given values. Returns the 65 | * product of the given values. All values are number values. 66 | * The method does not validate the parameters, the user must check the 67 | * parameters before calling this method. 68 | * 69 | * @param values A list of values on which the scalar function is performed. 70 | * 71 | * @return Value with the product of all given values, or number null value 72 | * if one of the values is null. 73 | */ 74 | public Value evaluate(List values) { 75 | if (values.get(0).isNull() || values.get(1).isNull()) { 76 | return NumberValue.getNullValue(); 77 | } 78 | double product = ((NumberValue) values.get(0)).getValue() * 79 | ((NumberValue) values.get(1)).getValue(); 80 | return new NumberValue(product); 81 | } 82 | 83 | /** 84 | * Returns the return type of the function. In this case, NUMBER. The method 85 | * does not validate the parameters, the user must check the parameters 86 | * before calling this method. 87 | * 88 | * @param types A list of the types of the scalar function parameters. 89 | * 90 | * @return The type of the returned value: Number. 91 | */ 92 | public ValueType getReturnType(List types) { 93 | return ValueType.NUMBER; 94 | } 95 | 96 | /** 97 | * Validates that all function parameters are of type NUMBER, and that there 98 | * are exactly 2 parameters. Throws a ScalarFunctionException otherwise. 99 | * 100 | * @param types A list with parameters types. 101 | * 102 | * @throws InvalidQueryException Thrown if the parameters are invalid. 103 | */ 104 | public void validateParameters(List types) throws InvalidQueryException { 105 | if (types.size() != 2) { 106 | throw new InvalidQueryException("The function " + FUNCTION_NAME 107 | + " requires 2 parmaeters "); 108 | } 109 | for (ValueType type : types) { 110 | if (type != ValueType.NUMBER) { 111 | throw new InvalidQueryException("Can't perform the function " 112 | + FUNCTION_NAME + " on values that are not numbers"); 113 | } 114 | } 115 | } 116 | 117 | /** 118 | * {@inheritDoc} 119 | */ 120 | public String toQueryString(List argumentsQueryStrings) { 121 | return "(" + argumentsQueryStrings.get(0) + " * " + argumentsQueryStrings.get(1) + ")"; 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/main/java/com/google/visualization/datasource/query/scalarfunction/Difference.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.query.scalarfunction; 16 | 17 | import com.google.visualization.datasource.base.InvalidQueryException; 18 | import com.google.visualization.datasource.datatable.value.NumberValue; 19 | import com.google.visualization.datasource.datatable.value.Value; 20 | import com.google.visualization.datasource.datatable.value.ValueType; 21 | 22 | 23 | import java.util.List; 24 | 25 | /** 26 | * The binary scalar function difference(). 27 | * Returns the difference between two number values. 28 | * 29 | * @author Liron L. 30 | */ 31 | public class Difference implements ScalarFunction { 32 | 33 | /** 34 | * The name of this function. 35 | */ 36 | private static final String FUNCTION_NAME = "difference"; 37 | 38 | /** 39 | * A singleton instance of this class. 40 | */ 41 | private static final Difference INSTANCE = new Difference(); 42 | 43 | /** 44 | * A private constructor. 45 | */ 46 | private Difference() {} 47 | 48 | /** 49 | * Returns the singleton instance of this class. 50 | * 51 | * @return The singleton instance of this class. 52 | */ 53 | public static Difference getInstance() { 54 | return INSTANCE; 55 | } 56 | 57 | /** 58 | * {@inheritDoc} 59 | */ 60 | public String getFunctionName() { 61 | return FUNCTION_NAME; 62 | } 63 | 64 | /** 65 | * Executes the scalar function difference() on the given values. Returns the 66 | * difference between the given values. All values are number values. 67 | * The method does not validate the parameters, the user must check the 68 | * parameters before calling this method. 69 | * 70 | * @param values A list of the values on which the scalar function will be performed. 71 | * 72 | * @return Value with the difference of all given values, or number null value 73 | * if one of the values is null. 74 | */ 75 | public Value evaluate(List values) { 76 | if (values.get(0).isNull() || values.get(1).isNull()) { 77 | return NumberValue.getNullValue(); 78 | } 79 | double difference = ((NumberValue) values.get(0)).getValue() - 80 | ((NumberValue) values.get(1)).getValue(); 81 | return new NumberValue(difference); 82 | } 83 | 84 | /** 85 | * Returns the return type of the function. In this case, NUMBER. The method 86 | * does not validate the parameters, the user must check the parameters 87 | * before calling this method. 88 | * 89 | * @param types A list of the types of the scalar function parameters. 90 | * 91 | * @return The type of the returned value: Number. 92 | */ 93 | public ValueType getReturnType(List types) { 94 | return ValueType.NUMBER; 95 | } 96 | 97 | /** 98 | * Validates that all function parameters are of type NUMBER, and that there 99 | * are exactly 2 parameters. Throws a ScalarFunctionException otherwise. 100 | * 101 | * @param types A list with parameters types. 102 | * 103 | * @throws InvalidQueryException Thrown if the parameters are invalid. 104 | */ 105 | public void validateParameters(List types) throws InvalidQueryException { 106 | if (types.size() != 2) { 107 | throw new InvalidQueryException("The function " + FUNCTION_NAME 108 | + " requires 2 parmaeters "); 109 | } 110 | for (ValueType type : types) { 111 | if (type != ValueType.NUMBER) { 112 | throw new InvalidQueryException("Can't perform the function " 113 | + FUNCTION_NAME + " on values that are not numbers"); 114 | } 115 | } 116 | } 117 | 118 | /** 119 | * {@inheritDoc} 120 | */ 121 | public String toQueryString(List argumentsQueryStrings) { 122 | return "(" + argumentsQueryStrings.get(0) + " - " + argumentsQueryStrings.get(1) + ")"; 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/main/java/com/google/visualization/datasource/query/scalarfunction/Modulo.java: -------------------------------------------------------------------------------- 1 | // Copyright 2010 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.query.scalarfunction; 16 | 17 | import com.google.visualization.datasource.base.InvalidQueryException; 18 | import com.google.visualization.datasource.datatable.value.NumberValue; 19 | import com.google.visualization.datasource.datatable.value.Value; 20 | import com.google.visualization.datasource.datatable.value.ValueType; 21 | 22 | import java.util.List; 23 | 24 | /** 25 | * The binary scalar function modulo(). 26 | * Returns the modulo between two number values. 27 | * 28 | * @author Roee E. 29 | */ 30 | public class Modulo implements ScalarFunction { 31 | 32 | /** 33 | * The name of this function. 34 | */ 35 | private static final String FUNCTION_NAME = "modulo"; 36 | 37 | /** 38 | * A singleton instance of this class. 39 | */ 40 | private static final Modulo INSTANCE = new Modulo(); 41 | 42 | /** 43 | * A private constructor, to prevent instantiation other than by the singleton. 44 | */ 45 | private Modulo() {} 46 | 47 | /** 48 | * Returns the singleton instance of this class. 49 | * 50 | * @return The singleton instance of this class. 51 | */ 52 | public static Modulo getInstance() { 53 | return INSTANCE; 54 | } 55 | 56 | /** 57 | * {@inheritDoc} 58 | */ 59 | public String getFunctionName() { 60 | return FUNCTION_NAME; 61 | } 62 | 63 | /** 64 | * Executes a binary scalar function modulo() between the first and the second 65 | * values in the list. Returns the modulo between the given values. All values 66 | * are number values. The method does not validate the parameters, 67 | * the user must check the parameters before calling this method. 68 | * 69 | * @param values A list of values on which the scalar function is performed. 70 | * 71 | * 72 | * @return Value with the modulo between two given values, or number null value 73 | * if one of the values is null. 74 | */ 75 | public Value evaluate(List values) { 76 | if (values.get(0).isNull() || values.get(1).isNull()) { 77 | return NumberValue.getNullValue(); 78 | } 79 | double modulo = ((NumberValue) values.get(0)).getValue() % 80 | ((NumberValue) values.get(1)).getValue(); 81 | return new NumberValue(modulo); 82 | } 83 | 84 | /** 85 | * Returns the return type of the function. In this case, NUMBER. The method 86 | * does not validate the parameters, the user must check the parameters 87 | * before calling this method. 88 | * 89 | * @param types A list of the types of the scalar function parameters. 90 | * 91 | * @return The type of the returned value: Number. 92 | */ 93 | public ValueType getReturnType(List types) { 94 | return ValueType.NUMBER; 95 | } 96 | 97 | /** 98 | * Validates that all function parameters are of type NUMBER, and that there 99 | * are exactly 2 parameters. Throws a ScalarFunctionException otherwise. 100 | * 101 | * @param types A list with parameters types. 102 | * 103 | * @throws InvalidQueryException Thrown if the parameters are invalid. 104 | */ 105 | public void validateParameters(List types) throws InvalidQueryException { 106 | if (types.size() != 2) { 107 | throw new InvalidQueryException("The function " + FUNCTION_NAME 108 | + " requires 2 parmaeters "); 109 | } 110 | for (ValueType type : types) { 111 | if (type != ValueType.NUMBER) { 112 | throw new InvalidQueryException("Can't perform the function " 113 | + FUNCTION_NAME + " on values that are not numbers"); 114 | } 115 | } 116 | } 117 | 118 | /** 119 | * {@inheritDoc} 120 | */ 121 | public String toQueryString(List argumentsQueryStrings) { 122 | return "(" + argumentsQueryStrings.get(0) + " % " + argumentsQueryStrings.get(1) + ")"; 123 | } 124 | } -------------------------------------------------------------------------------- /src/main/java/com/google/visualization/datasource/datatable/value/TextValue.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.datatable.value; 16 | 17 | import com.ibm.icu.text.Collator; 18 | import com.ibm.icu.util.ULocale; 19 | 20 | import java.util.Comparator; 21 | 22 | /** 23 | * A value of type text (string). 24 | * 25 | * @author Yoah B.D. 26 | */ 27 | public class TextValue extends Value { 28 | 29 | /** 30 | * A single static null value. 31 | */ 32 | private static final TextValue NULL_VALUE = new TextValue(""); 33 | 34 | /** 35 | * The underlying value. 36 | */ 37 | private String value; 38 | 39 | /** 40 | * Creates a new text cell. 41 | * 42 | * @param value The cell's value. 43 | */ 44 | public TextValue(String value) { 45 | if (value == null) { 46 | throw new NullPointerException("Cannot create a text value from null."); 47 | } 48 | this.value = value; 49 | } 50 | 51 | @Override 52 | public ValueType getType() { 53 | return ValueType.TEXT; 54 | } 55 | 56 | /** 57 | * Returns the text. 58 | * 59 | * @return The underlying text. 60 | */ 61 | @Override 62 | public String toString() { 63 | return value; 64 | } 65 | 66 | /** 67 | * Static method to return the null value (same one for all calls). 68 | * 69 | * @return Null value. 70 | */ 71 | public static TextValue getNullValue() { 72 | return NULL_VALUE; 73 | } 74 | 75 | /** 76 | * Tests whether this cell's value is logical null. 77 | * 78 | * @return Indication of whether the cell's value is null. 79 | */ 80 | @Override 81 | public boolean isNull() { 82 | return (this == NULL_VALUE); 83 | } 84 | 85 | /** 86 | * Compares this value to another value of the same type. 87 | * 88 | * @param other Other value. 89 | * 90 | * @return 0 if equal, negative if this is smaller, positive if larger. 91 | */ 92 | @Override 93 | public int compareTo(Value other) { 94 | if (this == other) { 95 | return 0; 96 | } 97 | // TextValue has no NULL_VALUE. 98 | return value.compareTo(((TextValue) other).value); 99 | } 100 | 101 | /** 102 | * Returns a hash code for this string value. 103 | * 104 | * @return A hash code for this string value. 105 | */ 106 | @Override 107 | public int hashCode() { 108 | // TextValue has no NULL_VALUE. 109 | return value.hashCode(); 110 | } 111 | 112 | @Override 113 | public String getObjectToFormat() { 114 | return value; 115 | } 116 | 117 | /** 118 | * Returns a comparator that compares text values according to a given locale. 119 | * 120 | * @param ulocale The ulocale defining the order relation for text values. 121 | * 122 | * @return A comparator that compares text values according to a given locale. 123 | */ 124 | public static Comparator getTextLocalizedComparator(final ULocale ulocale) { 125 | return new Comparator() { 126 | Collator collator = Collator.getInstance(ulocale); 127 | 128 | @Override 129 | public int compare(TextValue tv1, TextValue tv2) { 130 | if (tv1 == tv2) { 131 | return 0; 132 | } 133 | return collator.compare(tv1.value, tv2.value); 134 | } 135 | }; 136 | } 137 | 138 | /** 139 | * Returns the text value. 140 | * 141 | * @return The underlying text value. 142 | */ 143 | public String getValue() { 144 | return value; 145 | } 146 | 147 | /** 148 | * {@inheritDoc} 149 | */ 150 | @Override 151 | protected String innerToQueryString() { 152 | if (value.contains("\"")) { 153 | if (value.contains("'")) { 154 | throw new RuntimeException("Cannot run toQueryString() on string" 155 | + " values that contain both \" and '."); 156 | } else { 157 | return "'" + value + "'"; 158 | } 159 | } else { 160 | return "\"" + value + "\""; 161 | } 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /src/main/java/com/google/visualization/datasource/base/ErrorMessages.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.base; 16 | 17 | import java.util.ListResourceBundle; 18 | 19 | /** 20 | * A resource bundle that contains all the error messages for a datasource in the en-US locale. 21 | * This is the default locale used in this library. 22 | * 23 | * @author Yaniv S. 24 | */ 25 | public class ErrorMessages extends ListResourceBundle { 26 | 27 | /** 28 | * The contents of this bundle. A key to message map. 29 | */ 30 | static final Object[][] CONTENTS = { 31 | {"UNKNOWN_DATA_SOURCE_ID", "Unknown data source ID"}, 32 | {"ACCESS_DENIED", "Access denied"}, 33 | {"USER_NOT_AUTHENTICATED", "User not signed in"}, 34 | {"UNSUPPORTED_QUERY_OPERATION", "Unsupported query operation"}, 35 | {"INVALID_QUERY", "Invalid query"}, 36 | {"INVALID_REQUEST", "Invalid request"}, 37 | {"INTERNAL_ERROR", "Internal error"}, 38 | {"NOT_SUPPORTED", "Operation not supported"}, 39 | {"DATA_TRUNCATED", "Retrieved data was truncated"}, 40 | {"NOT_MODIFIED", "Data not modified"}, 41 | {"TIMEOUT", "Request timeout"}, 42 | {"ILLEGAL_FORMATTING_PATTERNS", "Illegal formatting patterns"}, 43 | {"OTHER", "Could not complete request"}, 44 | {"SIGN_IN", "Sign in"}, 45 | // QUERY Errors 46 | {"NO_COLUMN", "Column [{0}] does not exist in table."}, 47 | {"AVG_SUM_ONLY_NUMERIC", 48 | "'Average' and 'sum' aggreagation functions can be applied only on numeric values."}, 49 | {"INVALID_AGG_TYPE", "Invalid aggregation type: {0}"}, 50 | // Parse 51 | {"PARSE_ERROR", "Query parse error: {0}"}, 52 | {"CANNOT_BE_IN_GROUP_BY", "Column [{0}] cannot be in GROUP BY because it has an aggregation."}, 53 | {"CANNOT_BE_IN_PIVOT", "Column [{0}] cannot be in PIVOT because it has an aggregation."}, 54 | {"CANNOT_BE_IN_WHERE", "Column [{0}] cannot appear in WHERE because it has an aggregation."}, 55 | {"SELECT_WITH_AND_WITHOUT_AGG", 56 | "Column [{0}] cannot be selected both with and without aggregation in SELECT."}, 57 | {"COL_AGG_NOT_IN_SELECT", 58 | "Column [{0}] which is aggregated in SELECT, cannot appear in GROUP BY."}, 59 | {"CANNOT_GROUP_WITNOUT_AGG", "Cannot use GROUP BY when no aggregations are defined in SELECT."}, 60 | {"CANNOT_PIVOT_WITNOUT_AGG", "Cannot use PIVOT when no aggregations are defined in SELECT."}, 61 | {"AGG_IN_SELECT_NO_PIVOT", 62 | "Column [{0}] which is aggregated in SELECT, cannot appear in PIVOT."}, 63 | {"FORMAT_COL_NOT_IN_SELECT", 64 | "Column [{0}] which is referenced in FORMAT, is not part of SELECT clause."}, 65 | {"LABEL_COL_NOT_IN_SELECT", 66 | "Column [{0}] which is referenced in LABEL, is not part of SELECT clause."}, 67 | {"ADD_COL_TO_GROUP_BY_OR_AGG", 68 | "Column [{0}] should be added to GROUP BY, removed from SELECT, or aggregated in SELECT."}, 69 | {"AGG_IN_ORDER_NOT_IN_SELECT", 70 | "Aggregation [{0}] found in ORDER BY but was not found in SELECT"}, 71 | {"NO_AGG_IN_ORDER_WHEN_PIVOT", 72 | "Column [{0}] cannot be aggregated in ORDER BY when PIVOT is used."}, 73 | {"COL_IN_ORDER_MUST_BE_IN_SELECT", 74 | "Column [{0}] which appears in ORDER BY, must be in SELECT as well, " + 75 | "because SELECT contains aggregated columns."}, 76 | {"NO_COL_IN_GROUP_AND_PIVOT", "Column [{0}] cannot appear both in GROUP BY and in PIVOT."}, 77 | {"INVALID_OFFSET", "Invalid value for row offset: {0}"}, 78 | {"INVALID_SKIPPING", "Invalid value for row skipping: {0}"}, 79 | {"COLUMN_ONLY_ONCE", "Column [{0}] cannot appear more than once in {1}."} 80 | 81 | 82 | }; 83 | 84 | /** 85 | * Returns the error messages. 86 | * Note that this method exposes the inner array. This means it can be changed by the outside 87 | * world. We are not cloning here to avoid the computation time hit. Please do not change the 88 | * inner values unless you know what you are doing. 89 | */ 90 | @Override 91 | public Object[][] getContents() { 92 | return CONTENTS; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/main/java/com/google/visualization/datasource/query/QueryPivot.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.query; 16 | 17 | import com.google.common.collect.ImmutableList; 18 | import com.google.common.collect.Lists; 19 | 20 | import java.util.List; 21 | 22 | /** 23 | * Pivoting definition for a query. 24 | * Pivoting is defined as a list of column IDs to pivot. 25 | * 26 | * @author Yoav G. 27 | * @author Yonatan B.Y. 28 | */ 29 | public class QueryPivot { 30 | 31 | /** 32 | * The list of pivot columns. 33 | */ 34 | private List columns; 35 | 36 | /** 37 | * Constructs a query pivot with empty lists. 38 | */ 39 | public QueryPivot() { 40 | columns = Lists.newArrayList(); 41 | } 42 | 43 | /** 44 | * Adds a column to pivot. 45 | * 46 | * @param column The column to add. 47 | */ 48 | public void addColumn(AbstractColumn column) { 49 | columns.add(column); 50 | } 51 | 52 | /** 53 | * Returns the list of pivot column IDs. This list is immutable. 54 | * 55 | * @return The list of pivot column IDs. This list is immutable. 56 | */ 57 | public List getColumnIds() { 58 | List columnIds = Lists.newArrayList(); 59 | for (AbstractColumn col : columns) { 60 | columnIds.add(col.getId()); 61 | } 62 | return ImmutableList.copyOf(columnIds); 63 | } 64 | 65 | /** 66 | * Returns a list of all simple columns' IDs in this pivot. 67 | * 68 | * @return A list of all simple columns' IDs in this pivot. 69 | */ 70 | public List getSimpleColumnIds() { 71 | List columnIds = Lists.newArrayList(); 72 | for (AbstractColumn col : columns) { 73 | columnIds.addAll(col.getAllSimpleColumnIds()); 74 | } 75 | return columnIds; 76 | } 77 | 78 | /** 79 | * Returns the list of pivot columns. This list is immutable. 80 | * 81 | * @return The list of pivot columns. This list is immutable. 82 | */ 83 | public List getColumns() { 84 | return ImmutableList.copyOf(columns); 85 | } 86 | 87 | /** 88 | * Returns the list of pivot simple columns. 89 | * 90 | * @return The list of pivot simple columns. 91 | */ 92 | public List getSimpleColumns() { 93 | List simpleColumns = Lists.newArrayList(); 94 | for (AbstractColumn col : columns) { 95 | simpleColumns.addAll(col.getAllSimpleColumns()); 96 | } 97 | return simpleColumns; 98 | } 99 | 100 | /** 101 | * Returns the list of pivot scalar function columns. 102 | * 103 | * @return The list of pivot scalar function columns. 104 | */ 105 | public List getScalarFunctionColumns() { 106 | List scalarFunctionColumns = Lists.newArrayList(); 107 | for (AbstractColumn col : columns) { 108 | scalarFunctionColumns.addAll(col.getAllScalarFunctionColumns()); 109 | } 110 | return scalarFunctionColumns; 111 | } 112 | 113 | @Override 114 | public int hashCode() { 115 | final int prime = 31; 116 | int result = 1; 117 | result = prime * result + ((columns == null) ? 0 : columns.hashCode()); 118 | return result; 119 | } 120 | 121 | @Override 122 | public boolean equals(Object obj) { 123 | if (this == obj) { 124 | return true; 125 | } 126 | if (obj == null) { 127 | return false; 128 | } 129 | if (getClass() != obj.getClass()) { 130 | return false; 131 | } 132 | QueryPivot other = (QueryPivot) obj; 133 | if (columns == null) { 134 | if (other.columns != null) { 135 | return false; 136 | } 137 | } else if (!columns.equals(other.columns)) { 138 | return false; 139 | } 140 | return true; 141 | } 142 | 143 | /** 144 | * Returns a string that when fed to the query parser would produce an equal QueryPivot. 145 | * The string is returned without the PIVOT keywors. 146 | * 147 | * @return The query string. 148 | */ 149 | public String toQueryString() { 150 | return Query.columnListToQueryString(columns); 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /src/main/java/com/google/visualization/datasource/query/scalarfunction/Quotient.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.query.scalarfunction; 16 | 17 | import com.google.visualization.datasource.base.InvalidQueryException; 18 | import com.google.visualization.datasource.datatable.value.NumberValue; 19 | import com.google.visualization.datasource.datatable.value.Value; 20 | import com.google.visualization.datasource.datatable.value.ValueType; 21 | 22 | import java.util.List; 23 | 24 | /** 25 | * The binary scalar function quotient(). 26 | * Returns the quotient of two values. Division by zero returns a null number 27 | * value. 28 | * 29 | * @author Liron L. 30 | */ 31 | public class Quotient implements ScalarFunction { 32 | 33 | /** 34 | * The name of this function. 35 | */ 36 | private static final String FUNCTION_NAME = "quotient"; 37 | 38 | /** 39 | * A singleton instance of this class. 40 | */ 41 | private static final Quotient INSTANCE = new Quotient(); 42 | 43 | /** 44 | * A private constructor, to prevent instantiation other than by the singleton. 45 | */ 46 | private Quotient() {} 47 | 48 | /** 49 | * Returns the singleton instance of this class. 50 | * 51 | * @return The singleton instance of this class. 52 | */ 53 | public static Quotient getInstance() { 54 | return INSTANCE; 55 | } 56 | 57 | /** 58 | * {@inheritDoc} 59 | */ 60 | public String getFunctionName() { 61 | return FUNCTION_NAME; 62 | } 63 | 64 | /** 65 | * Executes the scalar function quotient() on the given values. Returns the 66 | * quotient of the given values. All values are number values. Division by 67 | * zero returns a null number value. 68 | * The method does not validate the parameters, the user must check the 69 | * parameters before calling this method. 70 | * 71 | * @param values A list of values on which the scalar function is performed. 72 | * 73 | * @return Value with the quotient of all given values, or number null value 74 | * if one of the values is null or if one of the denominators is zero. 75 | */ 76 | public Value evaluate(List values) { 77 | if (values.get(0).isNull() || values.get(1).isNull() 78 | || (((NumberValue) values.get(1)).getValue() == 0)) { 79 | return NumberValue.getNullValue(); 80 | } 81 | double quotient = ((NumberValue) values.get(0)).getValue() / 82 | ((NumberValue) values.get(1)).getValue(); 83 | return new NumberValue(quotient); 84 | } 85 | 86 | /** 87 | * Returns the return type of the function. In this case, NUMBER. The method 88 | * does not validate the parameters, the user must check the parameters 89 | * before calling this method. 90 | * 91 | * @param types A list of the types of the scalar function parameters. 92 | * 93 | * @return The type of the returned value: Number. 94 | */ 95 | public ValueType getReturnType(List types) { 96 | return ValueType.NUMBER; 97 | } 98 | 99 | /** 100 | * Validates that all function parameters are of type NUMBER, and that there 101 | * are exactly 2 parameters. Throws a ScalarFunctionException otherwise. 102 | * 103 | * @param types A list with parameters types. 104 | * 105 | * @throws InvalidQueryException Thrown if the parameters are invalid. 106 | */ 107 | public void validateParameters(List types) throws InvalidQueryException { 108 | if (types.size() != 2) { 109 | throw new InvalidQueryException("The function " + FUNCTION_NAME 110 | + " requires 2 parmaeters "); 111 | } 112 | for (ValueType type : types) { 113 | if (type != ValueType.NUMBER) { 114 | throw new InvalidQueryException("Can't perform the function " 115 | + FUNCTION_NAME + " on values that are not numbers"); 116 | } 117 | } 118 | } 119 | 120 | /** 121 | * {@inheritDoc} 122 | */ 123 | public String toQueryString(List argumentsQueryStrings) { 124 | return "(" + argumentsQueryStrings.get(0) + " / " + argumentsQueryStrings.get(1) + ")"; 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /src/main/java/com/google/visualization/datasource/datatable/value/BooleanValue.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.datatable.value; 16 | 17 | /** 18 | * A value of type boolean. Valid values are TRUE, FALSE and NULL_VALUE. 19 | * 20 | * @author Yoah B.D. 21 | */ 22 | public class BooleanValue extends Value { 23 | 24 | /** 25 | * A single static null value. 26 | */ 27 | private static final BooleanValue NULL_VALUE = new BooleanValue(false); 28 | 29 | /** 30 | * A single static TRUE value. 31 | */ 32 | public static final BooleanValue TRUE = new BooleanValue(true); 33 | 34 | /** 35 | * A single static FALSE value. 36 | */ 37 | public static final BooleanValue FALSE = new BooleanValue(false); 38 | 39 | /** 40 | * Static method to return the null value (same one for all calls) 41 | * 42 | * @return Null value. 43 | */ 44 | public static BooleanValue getNullValue() { 45 | return NULL_VALUE; 46 | } 47 | 48 | /** 49 | * Static method to return a BooleanValue based on a given java boolean. 50 | * If the parameter is null, returns NULL_VALUE. 51 | * 52 | * @param value The java Boolean value to be represented. 53 | * 54 | * @return The static predefined instance of the given value. 55 | */ 56 | public static BooleanValue getInstance(Boolean value) { 57 | if (value == null) { 58 | return NULL_VALUE; 59 | } 60 | return value ? TRUE : FALSE; 61 | } 62 | 63 | /** 64 | * The underlying value 65 | */ 66 | private boolean value; 67 | 68 | /** 69 | * Create a new boolean value. 70 | * This is private so users must use the three predefined values here (Null, 71 | * true, and false), like an enum. 72 | * 73 | * @param value The underlying value. 74 | */ 75 | private BooleanValue(boolean value) { 76 | this.value = value; 77 | } 78 | 79 | @Override 80 | public ValueType getType() { 81 | return ValueType.BOOLEAN; 82 | } 83 | 84 | /** 85 | * Returns the underlying value. 86 | * 87 | * @return The underlying value. 88 | */ 89 | public boolean getValue() { 90 | if (this == NULL_VALUE) { 91 | throw new NullValueException("This null boolean has no value"); 92 | } 93 | return value; 94 | } 95 | 96 | /** 97 | * Returns the value with default formatting. 98 | * 99 | * @return The value with default formatting. 100 | */ 101 | @Override 102 | public String toString() { 103 | if (this == NULL_VALUE) { 104 | return "null"; 105 | } 106 | return Boolean.toString(value); 107 | } 108 | 109 | /** 110 | * Tests whether this cell's value is a logical null. 111 | * 112 | * @return Indication if the call's value is null. 113 | */ 114 | @Override 115 | public boolean isNull() { 116 | return (this == NULL_VALUE); 117 | } 118 | 119 | /** 120 | * Compares this cell to another cell of the same type. 121 | * 122 | * @param other Other cell. 123 | * 124 | * @return 0 if equal, negative if this is smaller, positive if larger. 125 | */ 126 | @Override 127 | public int compareTo(Value other) { 128 | if (this == other) { 129 | return 0; // If same cell, or both are null. 130 | } 131 | BooleanValue otherBoolean = (BooleanValue) other; 132 | if (isNull()) { 133 | return -1; 134 | } 135 | if (otherBoolean.isNull()) { 136 | return 1; 137 | } 138 | return (value == otherBoolean.value ? 0 : (value ? 1 : -1)); 139 | } 140 | 141 | /** 142 | * Returns a hash code for this boolean value. 143 | * 144 | * @return A hash code for this boolean value. Null gets -1, false gets 0, 145 | * true gets 1. 146 | */ 147 | @Override 148 | public int hashCode() { 149 | return (isNull() ? -1 : (value ? 1 : 0)); 150 | } 151 | 152 | 153 | @Override 154 | public Boolean getObjectToFormat() { 155 | if (isNull()) { 156 | return null; 157 | } 158 | return value; 159 | } 160 | 161 | /** 162 | * {@inheritDoc} 163 | */ 164 | @Override 165 | protected String innerToQueryString() { 166 | return value ? "true" : "false"; 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /src/main/java/com/google/visualization/datasource/base/ResponseStatus.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.base; 16 | 17 | /** 18 | * A response status holds three parameters: 19 | * 1) The response type (Ok, Warning or Error). 20 | * 2) The response reason type. 21 | * 3) A string with an error message to the user. 22 | * 23 | * @author Hillel M. 24 | */ 25 | public class ResponseStatus { 26 | 27 | /** 28 | * The response status type. 29 | */ 30 | private StatusType statusType; 31 | 32 | /** 33 | * The response reason type (if OK or ERROR). 34 | */ 35 | private ReasonType reasonType; 36 | 37 | /** 38 | * A message to be passed to the user (if ERROR). 39 | */ 40 | private String description; 41 | 42 | /** 43 | * The sign in message key in the ResourceBundle 44 | */ 45 | public static final String SIGN_IN_MESSAGE_KEY = "SIGN_IN"; 46 | 47 | /** 48 | * Constructs a response status object. 49 | * This object contains a status type, reason type, 50 | * and a message that is sent to the user. 51 | * 52 | * @param statusType The response status type. 53 | * @param reasonType The response reason type. 54 | * @param description A message to be passed to the user. 55 | */ 56 | public ResponseStatus(StatusType statusType, ReasonType reasonType, String description) { 57 | this.statusType = statusType; 58 | this.reasonType = reasonType; 59 | this.description = description; 60 | } 61 | 62 | /** 63 | * Creates a ResponseStatus for the given DataSourceException. 64 | * 65 | * @param dse The data source exception. 66 | * 67 | * @return A response status object for the given data source exception. 68 | */ 69 | public static ResponseStatus createResponseStatus(DataSourceException dse) { 70 | return new ResponseStatus(StatusType.ERROR, dse.getReasonType(), dse.getMessageToUser()); 71 | } 72 | 73 | /** 74 | * Gets a modified response status in case of ReasonType#USER_NOT_AUTHENTICATED 75 | * by adding a sign in html link for the given url. If no url is provided in the 76 | * ResponseStatus# no change is made. 77 | * 78 | * @param responseStatus The response status. 79 | * 80 | * @return The modified response status if modified, or else the original response status. 81 | */ 82 | public static ResponseStatus getModifiedResponseStatus(ResponseStatus responseStatus) { 83 | 84 | String signInString = LocaleUtil.getLocalizedMessageFromBundle( 85 | "com.google.visualization.datasource.base.ErrorMessages", SIGN_IN_MESSAGE_KEY, null); 86 | if (responseStatus.getReasonType() == ReasonType.USER_NOT_AUTHENTICATED) { 87 | String msg = responseStatus.getDescription(); 88 | if (!msg.contains(" ") 89 | && (msg.startsWith("http://") 90 | || msg.startsWith("https://"))) { 91 | // The description is assumed to be a link to sign in page, transform the message into 92 | // an html snippet of a link. 93 | StringBuilder sb = new StringBuilder("") 95 | .append(signInString) 96 | .append(""); 97 | responseStatus = new ResponseStatus(responseStatus.getStatusType(), 98 | responseStatus.getReasonType(), sb.toString()); 99 | } 100 | } 101 | return responseStatus; 102 | } 103 | 104 | public ResponseStatus(StatusType statusType) { 105 | this(statusType, null, null); 106 | } 107 | 108 | /** 109 | * Returns the response status type. 110 | * 111 | * @return the response status type. 112 | */ 113 | public StatusType getStatusType() { 114 | return statusType; 115 | } 116 | 117 | /** 118 | * Returns the response reason type. 119 | * 120 | * @return the response reason type. 121 | */ 122 | public ReasonType getReasonType() { 123 | return reasonType; 124 | } 125 | 126 | /** 127 | * Returns the message to pass to the user. 128 | * 129 | * @return The message to pass to the user. 130 | */ 131 | public String getDescription() { 132 | return description; 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /examples/src/java/CsvDataSourceServlet.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import com.google.visualization.datasource.DataSourceHelper; 16 | import com.google.visualization.datasource.DataSourceServlet; 17 | import com.google.visualization.datasource.base.DataSourceException; 18 | import com.google.visualization.datasource.base.ReasonType; 19 | import com.google.visualization.datasource.datatable.DataTable; 20 | import com.google.visualization.datasource.query.Query; 21 | import com.google.visualization.datasource.util.CsvDataSourceHelper; 22 | 23 | import com.ibm.icu.util.ULocale; 24 | 25 | import org.apache.commons.lang.StringUtils; 26 | import org.apache.commons.logging.Log; 27 | import org.apache.commons.logging.LogFactory; 28 | 29 | import java.io.BufferedReader; 30 | import java.io.IOException; 31 | import java.io.InputStreamReader; 32 | import java.io.Reader; 33 | import java.net.MalformedURLException; 34 | import java.net.URL; 35 | 36 | import javax.servlet.http.HttpServletRequest; 37 | 38 | /** 39 | * A demo servlet for serving a simple, constant data table. 40 | * This servlet extends DataSourceServlet, but does not override the default 41 | * empty implementation of method getCapabilities(). This servlet therefore ignores the 42 | * user query (as passed in the 'tq' url parameter), leaving the 43 | * query engine to apply it to the data table created here. 44 | * 45 | * @author Nimrod T. 46 | */ 47 | public class CsvDataSourceServlet extends DataSourceServlet { 48 | 49 | /** 50 | * Log. 51 | */ 52 | private static final Log log = LogFactory.getLog(CsvDataSourceServlet.class.getName()); 53 | 54 | /** 55 | * The name of the parameter that contains the url of the CSV to load. 56 | */ 57 | private static final String URL_PARAM_NAME = "url"; 58 | 59 | /** 60 | * Generates the data table. 61 | * This servlet assumes a special parameter that contains the CSV URL from which to load 62 | * the data. 63 | */ 64 | @Override 65 | public DataTable generateDataTable(Query query, HttpServletRequest request) 66 | throws DataSourceException { 67 | String url = request.getParameter(URL_PARAM_NAME); 68 | if (StringUtils.isEmpty(url)) { 69 | log.error("url parameter not provided."); 70 | throw new DataSourceException(ReasonType.INVALID_REQUEST, "url parameter not provided"); 71 | } 72 | 73 | Reader reader; 74 | try { 75 | reader = new BufferedReader(new InputStreamReader(new URL(url).openStream())); 76 | } catch (MalformedURLException e) { 77 | log.error("url is malformed: " + url); 78 | throw new DataSourceException(ReasonType.INVALID_REQUEST, "url is malformed: " + url); 79 | } catch (IOException e) { 80 | log.error("Couldn't read from url: " + url, e); 81 | throw new DataSourceException(ReasonType.INVALID_REQUEST, "Couldn't read from url: " + url); 82 | } 83 | DataTable dataTable = null; 84 | ULocale requestLocale = DataSourceHelper.getLocaleFromRequest(request); 85 | try { 86 | // Note: We assume that all the columns in the CSV file are text columns. In cases where the 87 | // column types are known in advance, this behavior can be overridden by passing a list of 88 | // ColumnDescription objects specifying the column types. See CsvDataSourceHelper.read() for 89 | // more details. 90 | dataTable = CsvDataSourceHelper.read(reader, null, true, requestLocale); 91 | } catch (IOException e) { 92 | log.error("Couldn't read from url: " + url, e); 93 | throw new DataSourceException(ReasonType.INVALID_REQUEST, "Couldn't read from url: " + url); 94 | } 95 | return dataTable; 96 | } 97 | 98 | /** 99 | * NOTE: By default, this function returns true, which means that cross 100 | * domain requests are rejected. 101 | * This check is disabled here so examples can be used directly from the 102 | * address bar of the browser. Bear in mind that this exposes your 103 | * data source to xsrf attacks. 104 | * If the only use of the data source url is from your application, 105 | * that runs on the same domain, it is better to remain in restricted mode. 106 | */ 107 | @Override 108 | protected boolean isRestrictedAccessMode() { 109 | return false; 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/main/java/com/google/visualization/datasource/datatable/value/ValueType.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.datatable.value; 16 | 17 | import com.google.common.collect.Maps; 18 | import com.google.visualization.datasource.base.TypeMismatchException; 19 | 20 | import com.ibm.icu.util.GregorianCalendar; 21 | 22 | import java.util.Map; 23 | 24 | /** 25 | * Represents a supported value type for a table. 26 | * 27 | * @author Yoah B.D. 28 | */ 29 | public enum ValueType { 30 | BOOLEAN("BOOLEAN"), 31 | NUMBER("NUMBER"), 32 | TEXT("STRING"), 33 | DATE("DATE"), 34 | TIMEOFDAY("TIMEOFDAY"), 35 | DATETIME("DATETIME"); 36 | 37 | /** 38 | * The type code string for this ValueType. 39 | */ 40 | private String typeCode; 41 | 42 | /** 43 | * Constructs a ValueType with a given type code string. 44 | * 45 | * @param typeCode The type code string for the ValueType. 46 | */ 47 | ValueType(String typeCode) { 48 | this.typeCode = typeCode; 49 | } 50 | 51 | /** 52 | * Returns the type code string for this ValueType. 53 | * 54 | * @return The type code string for this ValueType. 55 | */ 56 | String getTypeCode() { 57 | return typeCode; 58 | } 59 | 60 | /** 61 | * Returns the type code string for this ValueType as a lower case string. 62 | * 63 | * @return The type code string for this ValueType as a lower case string. 64 | */ 65 | public String getTypeCodeLowerCase() { 66 | return typeCode.toLowerCase(); 67 | } 68 | 69 | /** 70 | * Returns the correct ValueType for a given type code string. 71 | * 72 | * @param string The type code string. 73 | * 74 | * @return The correct ValueType for the type code string. 75 | */ 76 | static ValueType getByTypeCode(String string) { 77 | return typeCodeToValueType.get(string); 78 | } 79 | 80 | /** 81 | * Holds the mapping of type code to an instance of this class. 82 | */ 83 | private static Map typeCodeToValueType; 84 | 85 | /** 86 | * Creates a value of this ValueType. The value must be of an appropriate 87 | * class, otherwise an exception is thrown. 88 | * Java native types/classes are translated to Value in the following way: 89 | * String -> TextValue 90 | * Number (inc. all derivatives such as Integer, Double) -> NumberValue 91 | * Boolean -> BooleanValue 92 | * com.ibm.icu.util.GregorianCalendar -> DateValue, DateTimeValue or 93 | * TimeOfDayValue 94 | * 95 | * @param value The value to create. 96 | * @return A Value of this ValueType. 97 | * @throws TypeMismatchException When the type of value does not match this. 98 | */ 99 | public Value createValue(Object value) throws TypeMismatchException { 100 | Value ret = null; 101 | 102 | if (value == null) { 103 | ret = Value.getNullValueFromValueType(this); 104 | } else if ((this == TEXT) && 105 | ((value instanceof String) || value == null)) { 106 | ret = new TextValue((String) value); 107 | } else if ((this == NUMBER) && (value instanceof Number)) { 108 | ret = new NumberValue(((Number) value).doubleValue()); 109 | } else if ((this == BOOLEAN) && (value instanceof Boolean)) { 110 | ret = ((Boolean) value).booleanValue() ? BooleanValue.TRUE 111 | : BooleanValue.FALSE; 112 | } else if ((this == DATE) && (value instanceof GregorianCalendar)) { 113 | ret = new DateValue((GregorianCalendar) value); 114 | } else if ((this == DATETIME) && (value instanceof GregorianCalendar)) { 115 | ret = new DateTimeValue((GregorianCalendar) value); 116 | } else if ((this == TIMEOFDAY) && (value instanceof GregorianCalendar)) { 117 | ret = new TimeOfDayValue((GregorianCalendar) value); 118 | } 119 | 120 | // If none of the above hold, we have a type mismatch. 121 | if (ret == null) { 122 | throw new TypeMismatchException("Value type mismatch."); 123 | } 124 | 125 | return ret; 126 | } 127 | 128 | /** 129 | * Initializes the static map. 130 | */ 131 | static { 132 | typeCodeToValueType = Maps.newHashMap(); 133 | for (ValueType type : ValueType.values()) { 134 | typeCodeToValueType.put(type.typeCode, type); 135 | } 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /src/main/java/com/google/visualization/datasource/query/QueryGroup.java: -------------------------------------------------------------------------------- 1 | // Copyright 2009 Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package com.google.visualization.datasource.query; 16 | 17 | import com.google.common.collect.ImmutableList; 18 | import com.google.common.collect.Lists; 19 | 20 | import java.util.List; 21 | 22 | /** 23 | * Grouping definition for a query. 24 | * Grouping is defined as a list of column IDs to group by. 25 | * 26 | * @author Yoav G. 27 | * @author Yonatan B.Y. 28 | * @author Liron L. 29 | */ 30 | public class QueryGroup { 31 | 32 | /** 33 | * The list of group-by columns. 34 | */ 35 | private List columns; 36 | 37 | /** 38 | * Constructs a query group with empty lists. 39 | */ 40 | public QueryGroup() { 41 | columns = Lists.newArrayList(); 42 | } 43 | 44 | /** 45 | * Add a column to group by. 46 | * 47 | * @param column The column to add. 48 | */ 49 | public void addColumn(AbstractColumn column) { 50 | columns.add(column); 51 | } 52 | 53 | /** 54 | * Returns the list of group-by IDs. This list is immutable. 55 | * 56 | * @return The list of group-by IDs. This list is immutable. 57 | */ 58 | public List getColumnIds() { 59 | List columnIds = Lists.newArrayList(); 60 | for (AbstractColumn col : columns) { 61 | columnIds.add(col.getId()); 62 | } 63 | return ImmutableList.copyOf(columnIds); 64 | } 65 | 66 | /** 67 | * Returns a list of all simple columns' IDs in this group. 68 | * 69 | * @return A list of all simple columns' IDs in this group. 70 | */ 71 | public List getSimpleColumnIds() { 72 | List columnIds = Lists.newArrayList(); 73 | for (AbstractColumn col : columns) { 74 | columnIds.addAll(col.getAllSimpleColumnIds()); 75 | } 76 | return columnIds; 77 | } 78 | 79 | /** 80 | * Returns the list of group-by columns. This list is immutable. 81 | * 82 | * @return The list of group-by columns. This list is immutable. 83 | */ 84 | public List getColumns() { 85 | return ImmutableList.copyOf(columns); 86 | } 87 | 88 | /** 89 | * Returns the list of simple columns included in the group-by section. 90 | * 91 | * @return The list of simple columns included in the group-by section. 92 | */ 93 | public List getSimpleColumns() { 94 | List simpleColumns = Lists.newArrayList(); 95 | for (AbstractColumn col : columns) { 96 | simpleColumns.addAll(col.getAllSimpleColumns()); 97 | } 98 | return simpleColumns; 99 | } 100 | 101 | /** 102 | * Returns the list of scalar function columns included in the group-by 103 | * section. 104 | * 105 | * @return The list of scalar function columns included in the group-by 106 | * section 107 | */ 108 | public List getScalarFunctionColumns() { 109 | List scalarFunctionColumns = Lists.newArrayList(); 110 | for (AbstractColumn col : columns) { 111 | scalarFunctionColumns.addAll(col.getAllScalarFunctionColumns()); 112 | } 113 | return scalarFunctionColumns; 114 | } 115 | 116 | @Override 117 | public int hashCode() { 118 | final int prime = 31; 119 | int result = 1; 120 | result = prime * result + ((columns == null) ? 0 : columns.hashCode()); 121 | return result; 122 | } 123 | 124 | @Override 125 | public boolean equals(Object obj) { 126 | if (this == obj) { 127 | return true; 128 | } 129 | if (obj == null) { 130 | return false; 131 | } 132 | if (getClass() != obj.getClass()) { 133 | return false; 134 | } 135 | QueryGroup other = (QueryGroup) obj; 136 | if (columns == null) { 137 | if (other.columns != null) { 138 | return false; 139 | } 140 | } else if (!columns.equals(other.columns)) { 141 | return false; 142 | } 143 | return true; 144 | } 145 | 146 | /** 147 | * Returns a string that when fed to the query parser would produce an equal QueryGroup. 148 | * The string is returned without the GROUP BY keywords. 149 | * 150 | * @return The query string. 151 | */ 152 | public String toQueryString() { 153 | return Query.columnListToQueryString(columns); 154 | } 155 | } 156 | --------------------------------------------------------------------------------