/* * 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.ecql; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.Iterator; import java.util.List; import javax.xml.transform.TransformerException; import org.geotools.filter.FilterTransformer; import org.geotools.filter.text.commons.CompilerUtil; import org.geotools.filter.text.commons.ExpressionToText; import org.geotools.filter.text.cql2.CQLException; import org.opengis.filter.Filter; import org.opengis.filter.FilterFactory; import org.opengis.filter.expression.Expression; /** * Extended Contextual Query Language (ECQL) is an extension of CQL. This class presents the operations available * to parse the ECQL language and generates the correspondent filter. *

*

*

Usage

* Here are some usage examples. Refer to the * BNF of grammar to see what exactly you can do. * *
 * 
 *       Filter filter = ECQL.toFilter("POP_RANK  >  6");
 *        
 *       Filter filter = ECQL.toFilter("POP_RANK > 3 AND POP_RANK < 6");
 *        
 *       Filter filter = ECQL.toFilter("area(the_geom) > 3000");
 *        
 *       Filter filter = ECQL.toFilter("Name LIKE '%omer%'");
 *       
 *       Filter filter = ECQL.toFilter("RELATE( the_geom1,the_geom2) like 'T**F*****'");
 *
 *       Filter filter = ECQL.toFilter("DISJOINT(buffer(the_geom, 10) , POINT(1 2))");
 *
 *       Filter filter = ECQL.toFilter("IN ('river.1', 'river.2')");
 *       
 *       Filter filter = ECQL.toFilter("LENGHT IN (4100001,4100002, 4100003 )");
 *
 *       List <Filter> list = ECQL.toFilterList("LENGHT = 100; NAME like '%omer%'");
 *
 *       Expression expression = ECQL.toExpression("LENGHT + 100");
 *       
 * 
 * 
* * The reverse process is possible too. To generate the ECQL associated to a filter you should use the toCQL(...) methods. *

* @author Jody Garnett * @author Mauricio Pazos (Axios Engineering) * * @since 2.6 * * * * @source $URL$ */ public class ECQL { private ECQL(){ // do nothing, private constructor // to indicate it is a pure utility class } /** * Parses the input string in ECQL format into a Filter, using the * systems default FilterFactory implementation. * * @param ECQLPredicate * a string containing a query predicate in ECQL format. * @return a {@link Filter} equivalent to the constraint specified in * ecqlPredicate. */ public static Filter toFilter(final String ecqlPredicate) throws CQLException { Filter filter = ECQL.toFilter(ecqlPredicate, null); return filter; } /** * Parses the input string in ECQL format into a Filter, using the * provided FilterFactory. * * @param ecqlPredicate * a string containing a query predicate in ECQL 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 * Predicate. */ public static Filter toFilter(final String ecqlPredicate, final FilterFactory filterFactory) throws CQLException { ECQLCompilerFactory compilerFactory = new ECQLCompilerFactory(); Filter result = CompilerUtil.parseFilter(ecqlPredicate, compilerFactory, filterFactory); return result; } /** * Parses the input string in ECQL format into an Expression, using the * systems default {@link FilterFactory} implementation. * * @param ecqlExpression a string containing an ECQL expression. * @return a {@link Expression} equivalent to the one specified in * ecqlExpression. */ public static Expression toExpression(String ecqlExpression) throws CQLException { return toExpression(ecqlExpression, null); } /** * Parses the input string in ECQL format and makes the correspondent Expression , * using the provided FilterFactory. * * @param ecqlExpression * a string containing a ECQL 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 * ecqlExpression. */ public static Expression toExpression(final String ecqlExpression, final FilterFactory filterFactory) throws CQLException { ECQLCompilerFactory compilerFactory = new ECQLCompilerFactory(); Expression expression = CompilerUtil.parseExpression(ecqlExpression, compilerFactory, filterFactory); return expression; } /** * Parses the input string, which has to be a list of ECQL predicates * separated by ";" into a {@link List} of * {@link Filter}, using the provided FilterFactory. * * @param ecqlSequencePredicate * a list of ECQL predicates separated by ";" * * @return a List of {@link Filter}, one for each input ECQL statement */ public static List toFilterList(final String ecqlSequencePredicate) throws CQLException { return toFilterList(ecqlSequencePredicate, null); } /** * Parses the input string, which has to be a list of ECQL predicates * separated by ";" into a {@link List} of * {@link Filter}, using the provided FilterFactory. * * @param ecqlSequencePredicate a ECQL predicate sequence * @param filterFactory the factory used to make the filters * @return a List of {@link Filter}, one for each input ECQL statement * @throws CQLException */ public static List toFilterList(final String ecqlSequencePredicate, FilterFactory filterFactory) throws CQLException { ECQLCompilerFactory compilerFactory = new ECQLCompilerFactory(); List filters = CompilerUtil.parseFilterList(ecqlSequencePredicate, compilerFactory, filterFactory); return filters; } /** * Generates the ecql predicates associated to the {@link List} of {@link Filter}s object. * * @param filterList * @return ecql predicates separated by ";" */ public static String toCQL( List filterList ){ FilterToECQL toECQL = new FilterToECQL(); StringBuilder output = new StringBuilder(); Iterator iter = filterList.iterator(); while( iter.hasNext() ){ Filter filter = iter.next(); filter.accept( toECQL, output ); if(iter.hasNext() ){ output.append("; "); } } return output.toString(); } /** * Generates the ecql predicate associated to the {@link Filter} object. * * @param filter * @return ecql predicate */ public static String toCQL( Filter filter ){ FilterToECQL toCQL = new FilterToECQL(); StringBuilder output = (StringBuilder) filter.accept( toCQL, new StringBuilder() ); return output.toString(); } /** * Generates the expression text associated to the {@link Expression} object. * * @param filter * @return expression as text */ public static String toCQL( Expression expression ){ ExpressionToText toECQL = new ExpressionToText(); StringBuilder output = (StringBuilder) expression.accept( toECQL, new StringBuilder() ); return output.toString(); } /** * Command line expression tester used to try out filters and expressions. * @param args */ public static final void main(String[] args) { System.out.println("ECQL Filters Tester"); System.out.println("Seperate with \";\" or \"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 filters = ECQL.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(); } } } }