001    //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_testing/src/org/deegree/model/filterencoding/ArithmeticExpression.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 <Add> / <Sub>/ <Mul> or <DIV> element
045     * as defined in the Expression DTD.
046     *
047     * @author <a href="mailto:schneider@lat-lon.de">Markus Schneider</a>
048     * @author last edited by: $Author: mschneider $
049     *
050     * @version $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18. Jun 2009) $
051     */
052    public class ArithmeticExpression extends Expression {
053    
054        /**
055         * The first operand.
056         *
057         */
058        Expression expr1;
059    
060        /**
061         * The second operand.
062         *
063         */
064        Expression expr2;
065    
066        /**
067         * Constructs a new ArithmeticExpression.
068         *
069         * @param id
070         * @param expr1
071         * @param expr2
072         */
073        public ArithmeticExpression( int id, Expression expr1, Expression expr2 ) {
074            this.id = id;
075            this.expr1 = expr1;
076            this.expr2 = expr2;
077        }
078    
079        /**
080         * Given a DOM-fragment, a corresponding Expression-object is built. This method recursively
081         * calls other buildFromDOM () - methods to validate the structure of the DOM-fragment.
082         *
083         * @param element
084         * @return the new instance
085         *
086         * @throws FilterConstructionException
087         *             if the structure of the DOM-fragment is invalid
088         */
089        public static Expression buildFromDOM( Element element )
090                                throws FilterConstructionException {
091    
092            // check if root element's name is 'Add' / 'Sub' / 'Mul' or 'Div'
093            String name = element.getLocalName();
094            int id = ExpressionDefines.getIdByName( name );
095            switch ( id ) {
096            case ExpressionDefines.ADD:
097            case ExpressionDefines.SUB:
098            case ExpressionDefines.MUL:
099            case ExpressionDefines.DIV: {
100                break;
101            }
102            default: {
103                throw new FilterConstructionException( "Element's name does not match 'Add' / 'Sub' / 'Mul' or 'Div'!" );
104            }
105            }
106    
107            // determine the arguments
108            ElementList children = XMLTools.getChildElements( element );
109            if ( children.getLength() != 2 )
110                throw new FilterConstructionException( "'" + name + "' requires exactly 2 elements!" );
111    
112            Expression expr1 = Expression.buildFromDOM( children.item( 0 ) );
113            Expression expr2 = Expression.buildFromDOM( children.item( 1 ) );
114    
115            return new ArithmeticExpression( id, expr1, expr2 );
116        }
117    
118        /**
119         * Produces an indented XML representation of this object.
120         *
121         * @return XML representation of this object.
122         */
123        @Override
124        public StringBuffer toXML() {
125            StringBuffer sb = new StringBuffer();
126    
127            sb.append( "<ogc:" ).append( getExpressionName() ).append( ">" );
128            sb.append( expr1.toXML() );
129            sb.append( expr2.toXML() );
130            sb.append( "</ogc:" ).append( getExpressionName() ).append( ">" );
131            return sb;
132        }
133    
134        /**
135         * Returns this <tt>ArithmeticExpression/tt>'s value (to be used in the
136         * evaluation of complex <tt>Expression</tt>s).
137         * TODO: Improve datatype handling.
138         * @param feature that determines the concrete values of
139         *                <tt>PropertyNames</tt> in the expression
140         * @return the resulting value (as <tt>Double</tt>)
141         * @throws FilterEvaluationException if the expressions are not numerical
142         */
143        @Override
144        public Object evaluate( Feature feature )
145                                throws FilterEvaluationException {
146    
147            Object o1 = expr1.evaluate( feature );
148            Object o2 = expr2.evaluate( feature );
149    
150            if ( !( o1 instanceof Number && o2 instanceof Number ) ) {
151                throw new FilterEvaluationException( "ADD/SUB/DIV/MUL may only be applied to numerical expressions." );
152            }
153            double d1 = ( (Number) o1 ).doubleValue();
154            double d2 = ( (Number) o2 ).doubleValue();
155            switch ( id ) {
156            case ExpressionDefines.ADD:
157                return new Double( d1 + d2 );
158            case ExpressionDefines.SUB:
159                return new Double( d1 - d2 );
160            case ExpressionDefines.MUL:
161                return new Double( d1 * d2 );
162            case ExpressionDefines.DIV:
163                return new Double( d1 / d2 );
164            default: {
165                throw new FilterEvaluationException( "Unknown ArithmeticExpression: '" + getExpressionName() + "'!" );
166            }
167            }
168        }
169    
170        /**
171         * returns the first expression
172         *
173         * @return the first expression
174         */
175        public Expression getFirstExpression() {
176            return expr1;
177        }
178    
179        /**
180         * returns the second expression
181         *
182         * @return the second expression
183         */
184        public Expression getSecondExpression() {
185            return expr2;
186        }
187    }