001 //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_testing/src/org/deegree/model/filterencoding/PropertyIsCOMPOperation.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 org.deegree.framework.xml.ElementList; 039 import org.deegree.framework.xml.XMLTools; 040 import org.deegree.model.feature.Feature; 041 import org.w3c.dom.Element; 042 043 /** 044 * Encapsulates the information of a <PropertyIsCOMP>-element (as defined in Filter DTD). COMP can be one of the 045 * following: 046 * <ul> 047 * <li>EqualTo</li> 048 * <li>LessThan</li> 049 * <li>GreaterThan</li> 050 * <li>LessThanOrEqualTo</li> 051 * <li>GreaterThanOrEqualTo</li> 052 * </ul> 053 * 054 * @author <a href="mailto:schneider@lat-lon.de">Markus Schneider</a> 055 * @author last edited by: $Author: mschneider $ 056 * 057 * @version $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18. Jun 2009) $ 058 */ 059 public class PropertyIsCOMPOperation extends ComparisonOperation { 060 061 private Expression expr1; 062 063 private Expression expr2; 064 065 /** 066 * 067 * matchCase flag 068 */ 069 private boolean matchCase = true; 070 071 /** 072 * Creates a new PropertyIsCOMPOperation object. 073 * 074 * @param id 075 * @param expr1 076 * @param expr2 077 */ 078 public PropertyIsCOMPOperation( int id, Expression expr1, Expression expr2 ) { 079 this( id, expr1, expr2, true ); 080 } 081 082 /** 083 * @param id 084 * @param expr1 085 * @param expr2 086 * @param matchCase 087 */ 088 public PropertyIsCOMPOperation( int id, Expression expr1, Expression expr2, boolean matchCase ) { 089 super( id ); 090 this.expr1 = expr1; 091 this.expr2 = expr2; 092 this.matchCase = matchCase; 093 } 094 095 /** 096 * Given a DOM-fragment, a corresponding Operation-object is built. This method recursively calls other buildFromDOM 097 * () - methods to validate the structure of the DOM-fragment. 098 * 099 * @param element 100 * @return a Bean of the Dom 101 * 102 * @throws FilterConstructionException 103 * if the structure of the DOM-fragment is invalid 104 */ 105 public static Operation buildFromDOM( Element element ) 106 throws FilterConstructionException { 107 // check if root element's name is a known operator 108 String name = element.getLocalName(); 109 int operatorId = OperationDefines.getIdByName( name ); 110 boolean matchCase = true; 111 String tmp = element.getAttribute( "matchCase" ); 112 if ( tmp != null && tmp.length() > 0 ) { 113 try { 114 matchCase = Boolean.parseBoolean( tmp ); 115 } catch ( Exception e ) { 116 // nottin 117 } 118 } 119 120 switch ( operatorId ) { 121 case OperationDefines.PROPERTYISEQUALTO: 122 case OperationDefines.PROPERTYISNOTEQUALTO: 123 case OperationDefines.PROPERTYISLESSTHAN: 124 case OperationDefines.PROPERTYISGREATERTHAN: 125 case OperationDefines.PROPERTYISLESSTHANOREQUALTO: 126 case OperationDefines.PROPERTYISGREATERTHANOREQUALTO: 127 break; 128 default: 129 throw new FilterConstructionException( "'" + name + "' is not a PropertyIsOperator!" ); 130 } 131 132 ElementList children = XMLTools.getChildElements( element ); 133 134 if ( children.getLength() != 2 ) { 135 throw new FilterConstructionException( "'" + name + "' requires exactly 2 elements!" ); 136 } 137 138 Expression expr1 = Expression.buildFromDOM( children.item( 0 ) ); 139 Expression expr2 = Expression.buildFromDOM( children.item( 1 ) ); 140 141 return new PropertyIsCOMPOperation( operatorId, expr1, expr2, matchCase ); 142 } 143 144 /** 145 * returns the first <code>Expression</code> of the comparison 146 * 147 * @return the first <code>Expression</code> of the comparison 148 */ 149 public Expression getFirstExpression() { 150 return expr1; 151 } 152 153 /** 154 * returns the second <code>Expression</code> of the comparison 155 * 156 * @return the second <code>Expression</code> of the comparison 157 */ 158 public Expression getSecondExpression() { 159 return expr2; 160 } 161 162 /** 163 * returns matchCase flag 164 * 165 * @return matchCase flag 166 */ 167 public boolean isMatchCase() { 168 return matchCase; 169 } 170 171 public StringBuffer toXML() { 172 StringBuffer sb = new StringBuffer( 500 ); 173 sb.append( "<ogc:" ).append( getOperatorName() ); 174 if ( !matchCase ) 175 sb.append( " matchCase=\"false\"" ); 176 sb.append( ">" ); 177 sb.append( expr1.toXML() ); 178 sb.append( expr2.toXML() ); 179 sb.append( "</ogc:" ).append( getOperatorName() ).append( ">" ); 180 return sb; 181 } 182 183 public StringBuffer to100XML() { 184 return toXML(); 185 } 186 187 public StringBuffer to110XML() { 188 return toXML(); 189 } 190 191 /** 192 * Calculates the <tt>ComparisonOperation</tt>'s logical value based on the certain property values of the given 193 * <tt>Feature</tt>. TODO: Improve datatype handling. 194 * 195 * @param feature 196 * that determines the property values 197 * @return true, if the <tt>FeatureFilter</tt> evaluates to true, else false 198 * @throws FilterEvaluationException 199 * if the expressions to be compared are of different types 200 */ 201 public boolean evaluate( Feature feature ) 202 throws FilterEvaluationException { 203 Object value1 = expr1.evaluate( feature ); 204 Object value2 = expr2.evaluate( feature ); 205 206 if ( value1 == null || value2 == null ) 207 return false; 208 209 // Convert to comparable datatype 210 if ( ( value1 instanceof String && value2 instanceof Number ) 211 || ( value1 instanceof Number && value2 instanceof String ) ) { 212 if ( value1 instanceof String ) { 213 // Prefer numeric comparison 214 try { 215 value1 = Double.valueOf( (String) value1 ); 216 } catch ( NumberFormatException e ) { 217 value2 = value2.toString(); 218 } 219 } else { 220 try { 221 value2 = Double.valueOf( (String) value2 ); 222 } catch ( NumberFormatException e ) { 223 value1 = value1.toString(); 224 } 225 } 226 } 227 228 // compare Strings 229 if ( value1 instanceof String && value2 instanceof String ) { 230 switch ( getOperatorId() ) { 231 case OperationDefines.PROPERTYISEQUALTO: { 232 if ( ( value1 == null ) || ( value2 == null ) ) { 233 return false; 234 } 235 236 if ( matchCase ) { 237 return value1.equals( value2 ); 238 } 239 return ( (String) value1 ).equalsIgnoreCase( (String) value2 ); 240 241 } 242 case OperationDefines.PROPERTYISLESSTHAN: 243 case OperationDefines.PROPERTYISGREATERTHAN: 244 case OperationDefines.PROPERTYISLESSTHANOREQUALTO: 245 case OperationDefines.PROPERTYISGREATERTHANOREQUALTO: 246 throw new FilterEvaluationException( "'" + getOperatorName() + "' can not be applied to " 247 + "String values!" ); 248 default: 249 throw new FilterEvaluationException( "Unknown comparison operation: '" + getOperatorName() + "'!" ); 250 } 251 }// compare Doubles 252 else if ( ( value1 instanceof Number ) && ( value2 instanceof Number ) ) { 253 double d1 = Double.parseDouble( value1.toString() ); 254 double d2 = Double.parseDouble( value2.toString() ); 255 256 switch ( getOperatorId() ) { 257 case OperationDefines.PROPERTYISEQUALTO: 258 return d1 == d2; 259 case OperationDefines.PROPERTYISLESSTHAN: 260 return d1 < d2; 261 case OperationDefines.PROPERTYISGREATERTHAN: 262 return d1 > d2; 263 case OperationDefines.PROPERTYISLESSTHANOREQUALTO: 264 return d1 <= d2; 265 case OperationDefines.PROPERTYISGREATERTHANOREQUALTO: 266 return d1 >= d2; 267 default: 268 throw new FilterEvaluationException( "Unknown comparison operation: '" + getOperatorName() + "'!" ); 269 } 270 } else { 271 throw new FilterEvaluationException( "Can not apply operation '" + getOperatorName() + "' to " 272 + "different datatypes!" ); 273 } 274 } 275 }