001    //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_testing/src/org/deegree/model/filterencoding/PropertyIsInstanceOfOperation.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.datatypes.QualifiedName;
039    import org.deegree.framework.xml.ElementList;
040    import org.deegree.framework.xml.NamespaceContext;
041    import org.deegree.framework.xml.XMLParsingException;
042    import org.deegree.framework.xml.XMLTools;
043    import org.deegree.io.datastore.PropertyPathResolvingException;
044    import org.deegree.model.feature.Feature;
045    import org.deegree.model.feature.FeatureProperty;
046    import org.deegree.model.spatialschema.Curve;
047    import org.deegree.model.spatialschema.MultiCurve;
048    import org.deegree.model.spatialschema.MultiPoint;
049    import org.deegree.model.spatialschema.MultiSurface;
050    import org.deegree.model.spatialschema.Point;
051    import org.deegree.model.spatialschema.Surface;
052    import org.deegree.model.spatialschema.SurfacePatch;
053    import org.deegree.ogcbase.CommonNamespaces;
054    import org.w3c.dom.Element;
055    
056    /**
057     * deegree-specific <code>ComparisonOperation</code> that allows to check the type of a property.
058     * <p>
059     * This is useful if the property has an abstract type with several concrete implementations, for example
060     * 'gml:_Geometry'.
061     * <p>
062     * NOTE: Currently supported types to test are:
063     * <ul>
064     * <li>gml:Point</li>
065     * <li>gml:_Curve</li>
066     * <li>gml:_Surface</li>
067     * </ul>
068     *
069     * @author <a href="mailto:schneider@lat-lon.de">Markus Schneider</a>
070     * @author last edited by: $Author: lbuesching $
071     *
072     * @version $Revision: 19319 $, $Date: 2009-08-25 09:17:13 +0200 (Di, 25. Aug 2009) $
073     */
074    public class PropertyIsInstanceOfOperation extends ComparisonOperation {
075    
076        private PropertyName propertyName;
077    
078        private QualifiedName typeName;
079    
080        private static NamespaceContext nsContext = CommonNamespaces.getNamespaceContext();
081    
082        /**
083         * Creates a new instance of <code>PropertyIsInstanceOfOperation</code>.
084         *
085         * @param propertyName
086         * @param typeName
087         */
088        public PropertyIsInstanceOfOperation( PropertyName propertyName, QualifiedName typeName ) {
089            super( OperationDefines.PROPERTYISINSTANCEOF );
090            this.propertyName = propertyName;
091            this.typeName = typeName;
092        }
093    
094        public StringBuffer toXML() {
095            StringBuffer sb = new StringBuffer();
096            sb.append( "<ogc:" ).append( getOperatorName() ).append( ">" );
097            sb.append( propertyName.toXML() );
098            sb.append( "<ogc:Literal>" ).append( typeName.getPrefixedName() ).append( "</ogc:Literal>" );
099            sb.append( "</ogc:" ).append( getOperatorName() ).append( ">" );
100            return sb;
101        }
102    
103        public StringBuffer to100XML() {
104            return toXML();
105        }
106    
107        public StringBuffer to110XML() {
108            return toXML();
109        }
110    
111        /**
112         * Calculates the <code>Operation</code>'s logical value based on the certain property values of the given feature.
113         *
114         * @param feature
115         *            that determines the values of <code>PropertyNames</code> in the expression
116         * @return true, if the <code>Operation</code> evaluates to true, else false
117         * @throws FilterEvaluationException
118         *             if the evaluation fails
119         */
120        public boolean evaluate( Feature feature )
121                                throws FilterEvaluationException {
122    
123            boolean equals = false;
124            Object propertyValue = null;
125            try {
126                FeatureProperty property = feature.getDefaultProperty( propertyName.getValue() );
127                propertyValue = property.getValue();
128            } catch ( PropertyPathResolvingException e ) {
129                String msg = "Error evaluating PropertyIsInstanceOf operation: " + e.getMessage();
130                throw new FilterEvaluationException( msg );
131            }
132    
133            if ( CommonNamespaces.GMLNS.equals( this.typeName.getNamespace() ) ) {
134                String localName = this.typeName.getLocalName();
135                if ( "Point".equals( localName ) ) {
136                    equals = propertyValue instanceof Point || propertyValue instanceof MultiPoint;
137                } else if ( "_Curve".equals( localName ) ) {
138                    equals = propertyValue instanceof Curve || propertyValue instanceof MultiCurve;
139                } else if ( "_Surface".equals( localName ) ) {
140                    equals = propertyValue instanceof Surface || propertyValue instanceof MultiSurface
141                             || propertyValue instanceof SurfacePatch;
142                } else {
143                    String msg = "Error evaluating PropertyIsInstanceOf operation: " + this.typeName
144                                 + " is not a supported type to check for.";
145                    throw new FilterEvaluationException( msg );
146                }
147            } else {
148                String msg = "Error evaluating PropertyIsInstanceOf operation: " + this.typeName
149                             + " is not a supported type to check for.";
150                throw new FilterEvaluationException( msg );
151            }
152            return equals;
153        }
154    
155        /**
156         * Given a DOM-fragment, a corresponding Operation-object is built. This method recursively calls other buildFromDOM
157         * () - methods to validate the structure of the DOM-fragment.
158         *
159         * @param element
160         *            to build from
161         * @return the Bean of the DOM
162         *
163         * @throws FilterConstructionException
164         *             if the structure of the DOM-fragment is invalid
165         */
166        public static Operation buildFromDOM( Element element )
167                                throws FilterConstructionException {
168    
169            // check if root element's name equals 'PropertyIsInstanceOf'
170            if ( !element.getLocalName().equals( "PropertyIsInstanceOf" ) )
171                throw new FilterConstructionException( "Name of element does not equal 'PropertyIsInstanceOf'!" );
172    
173            ElementList children = XMLTools.getChildElements( element );
174            if ( children.getLength() != 2 ) {
175                throw new FilterConstructionException( "'PropertyIsInstanceOf' requires exactly 2 elements!" );
176            }
177    
178            PropertyName propertyName = (PropertyName) PropertyName.buildFromDOM( children.item( 0 ) );
179            QualifiedName typeName = null;
180            try {
181                typeName = XMLTools.getRequiredNodeAsQualifiedName( element, "ogc:Literal/text()", nsContext );
182            } catch ( XMLParsingException e ) {
183                throw new FilterConstructionException( e.getMessage() );
184            }
185            return new PropertyIsInstanceOfOperation( propertyName, typeName );
186        }
187    
188        /**
189         * @return the propertyName of this Operation
190         */
191        public PropertyName getPropertyName() {
192            return propertyName;
193        }
194    
195        /**
196         * @return the typeName
197         */
198        public QualifiedName getTypeName() {
199            return typeName;
200        }
201        
202    }