001 //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.4_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 }