001 //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_testing/src/org/deegree/model/filterencoding/FilterTools.java $ 002 /*---------------------------------------------------------------------------- 003 This file is part of deegree, http://deegree.org/ 004 Copyright (C) 2001-2009 by: 005 Department of Geography, University of Bonn 006 and 007 lat/lon GmbH 008 009 This library is free software; you can redistribute it and/or modify it under 010 the terms of the GNU Lesser General Public License as published by the Free 011 Software Foundation; either version 2.1 of the License, or (at your option) 012 any later version. 013 This library is distributed in the hope that it will be useful, but WITHOUT 014 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 015 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 016 details. 017 You should have received a copy of the GNU Lesser General Public License 018 along with this library; if not, write to the Free Software Foundation, Inc., 019 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 020 021 Contact information: 022 023 lat/lon GmbH 024 Aennchenstr. 19, 53177 Bonn 025 Germany 026 http://lat-lon.de/ 027 028 Department of Geography, University of Bonn 029 Prof. Dr. Klaus Greve 030 Postfach 1147, 53001 Bonn 031 Germany 032 http://www.geographie.uni-bonn.de/deegree/ 033 034 e-mail: info@deegree.org 035 ----------------------------------------------------------------------------*/ 036 package org.deegree.model.filterencoding; 037 038 import java.util.ArrayList; 039 import java.util.Iterator; 040 import java.util.List; 041 import java.util.Stack; 042 043 import org.deegree.io.datastore.PropertyPathResolvingException; 044 import org.deegree.model.spatialschema.Envelope; 045 import org.deegree.ogcbase.PropertyPath; 046 047 /** 048 * 049 * 050 * 051 * @version $Revision: 18195 $ 052 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a> 053 * @author last edited by: $Author: mschneider $ 054 * 055 * @version 1.0. $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18. Jun 2009) $ 056 * 057 * @since 2.0 058 */ 059 public class FilterTools { 060 061 /** 062 * Traverses the <tt>Filter</tt> -tree and returns the first BBOX-Operation that is found and 063 * a <tt>Filter</tt> that is equal to the given one minus the BBOX-Operation. 064 * <p> 065 * 066 * @param filter 067 * search starts here 068 * @return [0]: <tt>Envelope</tt> (BBOX), [1]: <tt>Filter</tt> 069 * @throws Exception 070 */ 071 public static Object[] extractFirstBBOX( ComplexFilter filter ) 072 throws Exception { 073 074 // [0]: Envelope, [1]: Filter 075 Object[] objects = new Object[2]; 076 objects[1] = filter; 077 078 // sanity check (Filter empty) 079 if ( filter == null ) { 080 return objects; 081 } 082 083 // used as LIFO-queue 084 Stack<Operation> operations = new Stack<Operation>(); 085 operations.push( filter.getOperation() ); 086 087 while ( !operations.isEmpty() ) { 088 // get the first element of the queue 089 Operation operation = operations.pop(); 090 091 switch ( operation.getOperatorId() ) { 092 case OperationDefines.BBOX: { 093 // found BBOX 094 objects[0] = ( (SpatialOperation) operation ).getGeometry().getEnvelope(); 095 break; 096 } 097 case OperationDefines.AND: { 098 List<Operation> arguments = ( (LogicalOperation) operation ).getArguments(); 099 100 for ( int i = 0; i < arguments.size(); i++ ) { 101 operations.push( arguments.get( i ) ); 102 } 103 104 break; 105 } 106 } 107 108 // BBOX found? 109 if ( objects[0] != null ) { 110 break; 111 } 112 } 113 114 // special case: Filter contains only the BBOX-Operation 115 if ( filter.getOperation().getOperatorId() == OperationDefines.BBOX ) { 116 // objects[1] = null; 117 } 118 119 return objects; 120 } 121 122 /** 123 * Traverses the <tt>Filter</tt> -tree and returns the first BBOX-Operation that is found. Be 124 * aware of some limitations, using a shape datastore, only very simple filters are supported, 125 * joins with or, and not are not supported. 126 * <p> 127 * 128 * @param filter 129 * search starts here 130 * @return the first found bbox or <code>null</code> if no bbox was found. 131 */ 132 public static Envelope firstBBOX( ComplexFilter filter ) { 133 134 Envelope result = null; 135 if ( filter == null ) { 136 return result; 137 } 138 139 // special case: Filter contains only the BBOX-Operation 140 if ( filter.getOperation().getOperatorId() != OperationDefines.BBOX ) { 141 Stack<Operation> operations = new Stack<Operation>(); 142 operations.push( filter.getOperation() ); 143 while ( !operations.isEmpty() && result == null ) { 144 Operation operation = operations.pop(); 145 switch ( operation.getOperatorId() ) { 146 case OperationDefines.BBOX: 147 // found BBOX 148 result = ( (SpatialOperation) operation ).getGeometry().getEnvelope(); 149 break; 150 case OperationDefines.AND: 151 List<Operation> arguments = ( (LogicalOperation) operation ).getArguments(); 152 for ( Operation arg : arguments ) { 153 operations.push( arg ); 154 } 155 break; 156 } 157 } 158 } else { 159 result = ( (SpatialOperation) filter.getOperation() ).getGeometry().getEnvelope(); 160 } 161 return result; 162 } 163 164 /** 165 * Traverses the <tt>Filter</tt> -tree and returns all spatial filter operations. Their 166 * logical relationships are ignored, because within the intended target context, only AND 167 * operations are possible. 168 * 169 * @param filter 170 * search starts here 171 * @return <tt>Filter</tt>-array 172 */ 173 public static SpatialOperation[] extractSpatialFilter( ComplexFilter filter ) { 174 175 ArrayList<SpatialOperation> spatialOps = new ArrayList<SpatialOperation>(); 176 177 // sanity check (Filter empty) 178 if ( filter == null ) { 179 return ( new SpatialOperation[0] ); 180 } 181 182 Stack<Operation> operations = new Stack<Operation>(); 183 operations.push( filter.getOperation() ); 184 185 while ( !operations.isEmpty() ) { 186 // get the top element from the stack 187 Operation operation = operations.pop(); 188 189 switch ( OperationDefines.getTypeById( operation.getOperatorId() ) ) { 190 case OperationDefines.TYPE_SPATIAL: { 191 spatialOps.add( (SpatialOperation) operation ); 192 break; 193 } 194 case OperationDefines.TYPE_LOGICAL: { 195 List<Operation> arguments = ( (LogicalOperation) operation ).getArguments(); 196 for ( int i = 0; i < arguments.size(); i++ ) { 197 operations.push( arguments.get( i ) ); 198 } 199 break; 200 } 201 default: { 202 break; 203 } 204 } 205 206 } 207 208 return spatialOps.toArray( ( new SpatialOperation[spatialOps.size()] ) ); 209 } 210 211 /** 212 * returns all {@link PropertyPath} definitions from the passed {@link Filter} 213 * 214 * @see PropertyPath 215 * @see Filter 216 * 217 * @param filter 218 * @return all PropertyPath definitions from the passed Filter 219 * @throws PropertyPathResolvingException 220 */ 221 public static List<PropertyPath> extractPropertyPaths( Filter filter ) 222 throws PropertyPathResolvingException { 223 224 List<PropertyPath> pp = new ArrayList<PropertyPath>(); 225 226 if ( filter instanceof ComplexFilter ) { 227 pp = extractPropertyNameMapFromOperation( ( (ComplexFilter) filter ).getOperation(), pp ); 228 } else if ( filter instanceof FeatureFilter ) { 229 // TODO 230 // throw new PropertyPathResolvingException( "FeatureFilter not implemented yet." ); 231 } 232 233 return pp; 234 235 } 236 237 private static List<PropertyPath> extractPropertyNameMapFromOperation( Operation operation, List<PropertyPath> list ) 238 throws PropertyPathResolvingException { 239 switch ( OperationDefines.getTypeById( operation.getOperatorId() ) ) { 240 case OperationDefines.TYPE_SPATIAL: { 241 list.add( ( (SpatialOperation) operation ).getPropertyName().getValue() ); 242 break; 243 } 244 case OperationDefines.TYPE_COMPARISON: { 245 extractPropertyPaths( (ComparisonOperation) operation, list ); 246 break; 247 } 248 case OperationDefines.TYPE_LOGICAL: { 249 extractPropertyPaths( (LogicalOperation) operation, list ); 250 break; 251 } 252 default: { 253 break; 254 } 255 } 256 return list; 257 } 258 259 private static List<PropertyPath> extractPropertyPaths( ComparisonOperation operation, List<PropertyPath> list ) 260 throws PropertyPathResolvingException { 261 switch ( operation.getOperatorId() ) { 262 case OperationDefines.PROPERTYISEQUALTO: 263 case OperationDefines.PROPERTYISLESSTHAN: 264 case OperationDefines.PROPERTYISGREATERTHAN: 265 case OperationDefines.PROPERTYISLESSTHANOREQUALTO: 266 case OperationDefines.PROPERTYISGREATERTHANOREQUALTO: { 267 extractPropertyPaths( ( (PropertyIsCOMPOperation) operation ).getFirstExpression(), list ); 268 extractPropertyPaths( ( (PropertyIsCOMPOperation) operation ).getSecondExpression(), list ); 269 break; 270 } 271 case OperationDefines.PROPERTYISLIKE: { 272 list.add( ( (PropertyIsLikeOperation) operation ).getPropertyName().getValue() ); 273 break; 274 } 275 case OperationDefines.PROPERTYISNULL: { 276 extractPropertyPaths( ( (PropertyIsNullOperation) operation ).getPropertyName(), list ); 277 break; 278 } 279 case OperationDefines.PROPERTYISBETWEEN: { 280 extractPropertyPaths( ( (PropertyIsBetweenOperation) operation ).getLowerBoundary(), list ); 281 extractPropertyPaths( ( (PropertyIsBetweenOperation) operation ).getUpperBoundary(), list ); 282 list.add( ( (PropertyIsBetweenOperation) operation ).getPropertyName().getValue() ); 283 break; 284 } 285 default: { 286 break; 287 } 288 } 289 return list; 290 } 291 292 private static List<PropertyPath> extractPropertyPaths( LogicalOperation operation, List<PropertyPath> list ) 293 throws PropertyPathResolvingException { 294 List<Operation> operationList = operation.getArguments(); 295 Iterator<Operation> it = operationList.iterator(); 296 while ( it.hasNext() ) { 297 extractPropertyNameMapFromOperation( it.next(), list ); 298 } 299 return list; 300 } 301 302 /** 303 * returns all {@link PropertyPath} definitions from the passed {@link Expression} 304 * 305 * @see PropertyPath 306 * @see Expression 307 * 308 * @param expression 309 * @param list 310 * @return all PropertyPath definitions from the passed Expression 311 * @throws PropertyPathResolvingException 312 */ 313 public static List<PropertyPath> extractPropertyPaths( Expression expression, List<PropertyPath> list ) 314 throws PropertyPathResolvingException { 315 switch ( expression.getExpressionId() ) { 316 case ExpressionDefines.PROPERTYNAME: { 317 list.add( ( (PropertyName) expression ).getValue() ); 318 break; 319 } 320 case ExpressionDefines.ADD: 321 case ExpressionDefines.SUB: 322 case ExpressionDefines.MUL: 323 case ExpressionDefines.DIV: { 324 extractPropertyPaths( ( (ArithmeticExpression) expression ).getFirstExpression(), list ); 325 extractPropertyPaths( ( (ArithmeticExpression) expression ).getSecondExpression(), list ); 326 break; 327 } 328 case ExpressionDefines.FUNCTION: { 329 // TODO: What about PropertyNames used here? 330 break; 331 } 332 case ExpressionDefines.EXPRESSION: 333 case ExpressionDefines.LITERAL: { 334 break; 335 } 336 } 337 return list; 338 } 339 340 }