001: //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/trunk/src/org/deegree/model/filterencoding/PropertyIsCOMPOperation.java $
002: /*---------------- FILE HEADER ------------------------------------------
003:
004: This file is part of deegree.
005: Copyright (C) 2001-2008 by:
006: EXSE, Department of Geography, University of Bonn
007: http://www.giub.uni-bonn.de/deegree/
008: lat/lon GmbH
009: http://www.lat-lon.de
010:
011: This library is free software; you can redistribute it and/or
012: modify it under the terms of the GNU Lesser General Public
013: License as published by the Free Software Foundation; either
014: version 2.1 of the License, or (at your option) any later version.
015:
016: This library is distributed in the hope that it will be useful,
017: but WITHOUT ANY WARRANTY; without even the implied warranty of
018: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
019: Lesser General Public License for more details.
020:
021: You should have received a copy of the GNU Lesser General Public
022: License along with this library; if not, write to the Free Software
023: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
024:
025: Contact:
026:
027: Andreas Poth
028: lat/lon GmbH
029: Aennchenstr. 19
030: 53115 Bonn
031: Germany
032: E-Mail: poth@lat-lon.de
033:
034: Prof. Dr. Klaus Greve
035: Department of Geography
036: University of Bonn
037: Meckenheimer Allee 166
038: 53115 Bonn
039: Germany
040: E-Mail: greve@giub.uni-bonn.de
041:
042:
043: ---------------------------------------------------------------------------*/
044: package org.deegree.model.filterencoding;
045:
046: import org.deegree.framework.xml.ElementList;
047: import org.deegree.framework.xml.XMLTools;
048: import org.deegree.model.feature.Feature;
049: import org.w3c.dom.Element;
050:
051: /**
052: * Encapsulates the information of a <PropertyIsCOMP>-element (as defined in Filter DTD). COMP can
053: * be one of the following:
054: * <ul>
055: * <li>EqualTo</li>
056: * <li>LessThan</li>
057: * <li>GreaterThan</li>
058: * <li>LessThanOrEqualTo</li>
059: * <li>GreaterThanOrEqualTo</li>
060: * </ul>
061: *
062: * @author Markus Schneider
063: * @author last edited by: $Author: apoth $
064: *
065: * @version $Revision: 9343 $, $Date: 2007-12-27 05:30:32 -0800 (Thu, 27 Dec 2007) $
066: */
067: public class PropertyIsCOMPOperation extends ComparisonOperation {
068:
069: private Expression expr1;
070:
071: private Expression expr2;
072:
073: /**
074: *
075: * matchCase flag
076: */
077: private boolean matchCase = true;
078:
079: /**
080: * Creates a new PropertyIsCOMPOperation object.
081: *
082: * @param id
083: * @param expr1
084: * @param expr2
085: */
086: public PropertyIsCOMPOperation(int id, Expression expr1,
087: Expression expr2) {
088: this (id, expr1, expr2, true);
089: }
090:
091: /**
092: * @param id
093: * @param expr1
094: * @param expr2
095: * @param matchCase
096: */
097: public PropertyIsCOMPOperation(int id, Expression expr1,
098: Expression expr2, boolean matchCase) {
099: super (id);
100: this .expr1 = expr1;
101: this .expr2 = expr2;
102: this .matchCase = matchCase;
103: }
104:
105: /**
106: * Given a DOM-fragment, a corresponding Operation-object is built. This method recursively
107: * calls other buildFromDOM () - methods to validate the structure of the DOM-fragment.
108: *
109: * @param element
110: * @return a Bean of the Dom
111: *
112: * @throws FilterConstructionException
113: * if the structure of the DOM-fragment is invalid
114: */
115: public static Operation buildFromDOM(Element element)
116: throws FilterConstructionException {
117: // check if root element's name is a known operator
118: String name = element.getLocalName();
119: int operatorId = OperationDefines.getIdByName(name);
120: boolean matchCase = true;
121: String tmp = element.getAttribute("matchCase");
122: if (tmp != null && tmp.length() > 0) {
123: try {
124: matchCase = Boolean.parseBoolean(tmp);
125: } catch (Exception e) {
126: // nottin
127: }
128: }
129:
130: switch (operatorId) {
131: case OperationDefines.PROPERTYISEQUALTO:
132: case OperationDefines.PROPERTYISLESSTHAN:
133: case OperationDefines.PROPERTYISGREATERTHAN:
134: case OperationDefines.PROPERTYISLESSTHANOREQUALTO:
135: case OperationDefines.PROPERTYISGREATERTHANOREQUALTO:
136: break;
137: default:
138: throw new FilterConstructionException("'" + name
139: + "' is not a PropertyIsOperator!");
140: }
141:
142: ElementList children = XMLTools.getChildElements(element);
143:
144: if (children.getLength() != 2) {
145: throw new FilterConstructionException("'" + name
146: + "' requires exactly 2 elements!");
147: }
148:
149: Expression expr1 = Expression.buildFromDOM(children.item(0));
150: Expression expr2 = Expression.buildFromDOM(children.item(1));
151:
152: return new PropertyIsCOMPOperation(operatorId, expr1, expr2,
153: matchCase);
154: }
155:
156: /**
157: * returns the first <code>Expression</code> of the comparison
158: *
159: * @return the first <code>Expression</code> of the comparison
160: */
161: public Expression getFirstExpression() {
162: return expr1;
163: }
164:
165: /**
166: * returns the second <code>Expression</code> of the comparison
167: *
168: * @return the second <code>Expression</code> of the comparison
169: */
170: public Expression getSecondExpression() {
171: return expr2;
172: }
173:
174: /**
175: * returns matchCase flag
176: *
177: * @return matchCase flag
178: */
179: public boolean isMatchCase() {
180: return matchCase;
181: }
182:
183: /**
184: * Produces an indented XML representation of this object.
185: *
186: * @return XML representation of this object.
187: */
188: public StringBuffer toXML() {
189: StringBuffer sb = new StringBuffer(500);
190: sb.append("<ogc:").append(getOperatorName());
191: if (!matchCase)
192: sb.append(" matchCase=\"false\"");
193: sb.append(">");
194: sb.append(expr1.toXML());
195: sb.append(expr2.toXML());
196: sb.append("</ogc:").append(getOperatorName()).append(">");
197: return sb;
198: }
199:
200: /**
201: * Calculates the <tt>ComparisonOperation</tt>'s logical value based on the certain property
202: * values of the given <tt>Feature</tt>. TODO: Improve datatype handling.
203: *
204: * @param feature
205: * that determines the property values
206: * @return true, if the <tt>FeatureFilter</tt> evaluates to true, else false
207: * @throws FilterEvaluationException
208: * if the expressions to be compared are of different types
209: */
210: public boolean evaluate(Feature feature)
211: throws FilterEvaluationException {
212: Object value1 = expr1.evaluate(feature);
213: Object value2 = expr2.evaluate(feature);
214:
215: if (value1 == null || value2 == null)
216: return false;
217:
218: // Convert to comparable datatype
219: if ((value1 instanceof String && value2 instanceof Number)
220: || (value1 instanceof Number && value2 instanceof String)) {
221: if (value1 instanceof String) {
222: // Prefer numeric comparison
223: try {
224: value1 = Double.valueOf((String) value1);
225: } catch (NumberFormatException e) {
226: value2 = value2.toString();
227: }
228: } else {
229: try {
230: value2 = Double.valueOf((String) value2);
231: } catch (NumberFormatException e) {
232: value1 = value1.toString();
233: }
234: }
235: }
236:
237: // compare Strings
238: if (value1 instanceof String && value2 instanceof String) {
239: switch (getOperatorId()) {
240: case OperationDefines.PROPERTYISEQUALTO: {
241: if ((value1 == null) || (value2 == null)) {
242: return false;
243: }
244:
245: if (matchCase) {
246: return value1.equals(value2);
247: }
248: return ((String) value1)
249: .equalsIgnoreCase((String) value2);
250:
251: }
252: case OperationDefines.PROPERTYISLESSTHAN:
253: case OperationDefines.PROPERTYISGREATERTHAN:
254: case OperationDefines.PROPERTYISLESSTHANOREQUALTO:
255: case OperationDefines.PROPERTYISGREATERTHANOREQUALTO:
256: throw new FilterEvaluationException("'"
257: + getOperatorName()
258: + "' can not be applied to " + "String values!");
259: default:
260: throw new FilterEvaluationException(
261: "Unknown comparison operation: '"
262: + getOperatorName() + "'!");
263: }
264: }// compare Doubles
265: else if ((value1 instanceof Number)
266: && (value2 instanceof Number)) {
267: double d1 = Double.parseDouble(value1.toString());
268: double d2 = Double.parseDouble(value2.toString());
269:
270: switch (getOperatorId()) {
271: case OperationDefines.PROPERTYISEQUALTO:
272: return d1 == d2;
273: case OperationDefines.PROPERTYISLESSTHAN:
274: return d1 < d2;
275: case OperationDefines.PROPERTYISGREATERTHAN:
276: return d1 > d2;
277: case OperationDefines.PROPERTYISLESSTHANOREQUALTO:
278: return d1 <= d2;
279: case OperationDefines.PROPERTYISGREATERTHANOREQUALTO:
280: return d1 >= d2;
281: default:
282: throw new FilterEvaluationException(
283: "Unknown comparison operation: '"
284: + getOperatorName() + "'!");
285: }
286: } else {
287: throw new FilterEvaluationException(
288: "Can not apply operation '" + getOperatorName()
289: + "' to " + "different datatypes!");
290: }
291: }
292: }
|