/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2006-2008, Open Source Geospatial Foundation (OSGeo) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package org.geotools.filter.text.cql2; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.List; import javax.xml.transform.TransformerException; import org.geotools.filter.FilterTransformer; import org.geotools.filter.text.commons.CompilerUtil; import org.opengis.filter.Filter; import org.opengis.filter.FilterFactory; import org.opengis.filter.expression.Expression; /** * Utility class to parse <b>CQL</b> predicates and expressions to GeoAPI * {@link Filter}s and {@link Expression}s, respectively. * * <p> * <b>CQL</b> is an acronym for Contextual Query Language, a query predicate * language whose syntax is similar to a SQL WHERE clause, defined as OGC Common Query Language * in clause 6.2.2 of the OGC Catalog Service for Web, version 2.0.1 implementation * specification. * </p> * <p> * This class provides three methods, {@link #toFilter(String)}, * {@link #toExpression(String)} and {@link #toFilterList(String)}; and an * overloaded version of each one for the user to provide a * {@link FilterFactory} implementation to use. * </p> * <p> * <h2>Usage</h2> * Here are some usage examples. Refer to the <a * href="href="http://docs.geotools.org/latest/userguide/guide/library/cql/internal.html">BNF of * grammar</a> to see what exactly you can do. * * * <pre> * <code> * Filter f = CQL.toFilter("ATTR1 < 10 AND ATTR2 < 2 OR ATTR3 > 10"); * * Filter f = CQL.toFilter("NAME = 'New York' "); * * Filter f = CQL.toFilter("NAME LIKE 'New%' "); * * Filter f = CQL.toFilter("NAME IS NULL"); * * Filter f = CQL.toFilter("DATE BEFORE 2006-11-30T01:30:00Z"); * * Filter f = CQL.toFilter("NAME DOES-NOT-EXIST"); * * Filter f = CQL.toFilter("QUANTITY BETWEEN 10 AND 20"); * * Filter f = CQL.toFilter("CROSSES(SHAPE, LINESTRING(1 2, 10 15))"); * * Filter f = CQL.toFilter("BBOX(SHAPE, 10,20,30,40)"); * * Expression e = CQL.toExpression("NAME"); * * Expression e = CQL.toExpression("QUANTITY * 2"); * * Expression e = CQL.toExpression("strConcat(NAME, 'suffix')"); * * List filters = CQL.toFilterList("NAME IS NULL;BBOX(SHAPE, 10,20,30,40);INCLUDE"); * </code> * </pre> * <A HREF="http://www.opengis.org/docs/02-059.pdf">Implementation specification 1.0</A> * * @since 2.5 * @author Mauricio Pazos (Axios Engineering) * @author Gabriel Roldan (Axios Engineering) * @version $Id$ * @source $URL$ */ public class CQL { private CQL() { // do nothing, private constructor // to indicate it is a pure utility class } /** * Parses the input string in OGC CQL format into a Filter, using the * systems default FilterFactory implementation. * * @param cqlPredicate * a string containing a query predicate in OGC CQL format. * @return a {@link Filter} equivalent to the constraint specified in * <code>cqlPredicate</code>. */ public static Filter toFilter(final String cqlPredicate) throws CQLException { Filter filter = CQL.toFilter(cqlPredicate, null); return filter; } /** * Parses the input string in OGC CQL format into a Filter, using the * provided FilterFactory. * * @param cqlPredicate * a string containing a query predicate in OGC CQL format. * @param filterFactory * the {@link FilterFactory} to use for the creation of the * Filter. If it is null the method finds the default implementation. * @return a {@link Filter} equivalent to the constraint specified in * <code>Predicate</code>. */ public static Filter toFilter(final String cqlPredicate, final FilterFactory filterFactory) throws CQLException { CQLCompilerFactory compilerFactory = new CQLCompilerFactory(); Filter result = CompilerUtil.parseFilter(cqlPredicate, compilerFactory, filterFactory); return result; } /** * Parses the input string in OGC CQL format into an Expression, using the * systems default {@link FilterFactory} implementation. * * @param cqlExpression * a string containing an OGC CQL expression. * @return a {@link Expression} equivalent to the one specified in * <code>cqlExpression</code>. */ public static Expression toExpression(String cqlExpression) throws CQLException { return toExpression(cqlExpression, null); } /** * Parses the input string in OGC CQL format into an {@link Expression}, using the * provided {@link FilterFactory}. * * @param cqlExpression * a string containing a OGC CQL expression. * * @param filterFactory * the {@link FilterFactory} to use for the creation of the * Expression. If it is null the method finds the default implementation. * @return a {@link Filter} equivalent to the constraint specified in * <code>cqlExpression</code>. */ public static Expression toExpression(final String cqlExpression, final FilterFactory filterFactory) throws CQLException { CQLCompilerFactory compilerFactory = new CQLCompilerFactory(); Expression expression = CompilerUtil.parseExpression(cqlExpression, compilerFactory, filterFactory); return expression; } /** * Parses the input string, which has to be a list of OGC CQL predicates * separated by <code>;</code> into a <code>List</code> of * <code>Filter</code>s, using the provided FilterFactory. * * @param cqlFilterList * a list of OGC CQL predicates separated by "<code>;</code>" * * @return a {@link List} of {@link Filter}, one for each input CQL statement */ public static List<Filter> toFilterList(final String cqlFilterList) throws CQLException { List<Filter> filters = CQL.toFilterList(cqlFilterList, null); return filters; } /** * WARNING THIS IS A WORK IN PROGRESS. * * @param filterList * @return */ public static String toCQL( List<Filter> filterList ){ FilterToCQL toCQL = new FilterToCQL(); StringBuffer output = new StringBuffer(); for( Filter filter : filterList ){ filter.accept( toCQL, output ); output.append("; "); } return output.toString(); } /** * WARNING THIS IS A WORK IN PROGRESS. * * @param filter * @return */ public static String toCQL( Filter filter ){ FilterToCQL toCQL = new FilterToCQL(); StringBuffer output = (StringBuffer) filter.accept( toCQL, new StringBuffer() ); return output.toString(); } /** * WARNING THIS IS A WORK IN PROGRESS. * * @param filter * @return */ public static String toCQL( Expression expression ){ FilterToCQL toCQL = new FilterToCQL(); StringBuffer output = (StringBuffer) expression.accept( toCQL, new StringBuffer() ); return output.toString(); } /** * Parses the input string which has to be a list of OGC CQL predicates * separated by "<code>;</code>" into a <code>List</code> of * <code>Filter</code>s, using the provided FilterFactory. * * @param cqlSequencePredicate * a list of OGC CQL predicates separated by "<code>;</code>" * * @param filterFactory * the {@link FilterFactory} to use for the creation of the * Expression. If it is null the method finds the default implementation. * @return a List of {@link Filter}, one for each input CQL statement */ public static List<Filter> toFilterList(final String cqlSequencePredicate, final FilterFactory filterFactory) throws CQLException { CQLCompilerFactory compilerFactory = new CQLCompilerFactory(); List<Filter> filters = CompilerUtil.parseFilterList(cqlSequencePredicate, compilerFactory, filterFactory); return filters; } /** * Command line expression tester used to try out filters and expressions. * @param args */ public static final void main(String[] args) { System.out.println("CQL Filter Tester"); System.out.println("(\"quit\" to finish)"); BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); FilterTransformer filterTransformer = new FilterTransformer(); filterTransformer.setIndentation(4); while (true) { System.out.print(">"); String line = null; try { line = reader.readLine(); if (line.equals("quit")) { System.out.println("Bye!"); break; } List<Filter> filters = CQL.toFilterList(line); for( Filter filter : filters ){ System.out.println(); filterTransformer.transform( filter, System.out); } } catch (IOException e1) { e1.printStackTrace(); } catch (CQLException cqlex) { System.out.println(cqlex.getSyntaxError()); } catch (TransformerException e) { e.printStackTrace(); } } } }