001    //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_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: apoth $
071     * 
072     * @version $Revision: 25585 $, $Date: 2010-07-28 16:49:15 +0200 (Mi, 28 Jul 2010) $
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 gml='http://www.opengis.net/gml'>" );
099            sb.append( "gml:" ).append( typeName.getLocalName() ).append( "</ogc:Literal>" );
100            sb.append( "</ogc:" ).append( getOperatorName() ).append( ">" );
101            return sb;
102        }
103    
104        public StringBuffer to100XML() {
105            return toXML();
106        }
107    
108        public StringBuffer to110XML() {
109            return toXML();
110        }
111    
112        /**
113         * Calculates the <code>Operation</code>'s logical value based on the certain property values of the given feature.
114         * 
115         * @param feature
116         *            that determines the values of <code>PropertyNames</code> in the expression
117         * @return true, if the <code>Operation</code> evaluates to true, else false
118         * @throws FilterEvaluationException
119         *             if the evaluation fails
120         */
121        public boolean evaluate( Feature feature )
122                                throws FilterEvaluationException {
123            boolean equals = false;
124            Object propertyValue = null;
125            try {
126                FeatureProperty property = feature.getDefaultProperty( propertyName.getValue() );
127                if ( property == null ) {
128                    return false;
129                }
130                propertyValue = property.getValue();
131            } catch ( PropertyPathResolvingException e ) {
132                String msg = "Error evaluating PropertyIsInstanceOf operation: " + e.getMessage();
133                throw new FilterEvaluationException( msg );
134            }
135    
136            if ( CommonNamespaces.GMLNS.equals( this.typeName.getNamespace() ) ) {
137                String localName = this.typeName.getLocalName();
138                if ( "Point".equals( localName ) ) {
139                    equals = propertyValue instanceof Point || propertyValue instanceof MultiPoint;
140                } else if ( "_Curve".equals( localName ) ) {
141                    equals = propertyValue instanceof Curve || propertyValue instanceof MultiCurve;
142                } else if ( "_Surface".equals( localName ) ) {
143                    equals = propertyValue instanceof Surface || propertyValue instanceof MultiSurface
144                             || propertyValue instanceof SurfacePatch;
145                } else {
146                    String msg = "Error evaluating PropertyIsInstanceOf operation: " + this.typeName
147                                 + " is not a supported type to check for.";
148                    throw new FilterEvaluationException( msg );
149                }
150            } else {
151                String msg = "Error evaluating PropertyIsInstanceOf operation: " + this.typeName
152                             + " is not a supported type to check for.";
153                throw new FilterEvaluationException( msg );
154            }
155            return equals;
156        }
157    
158        /**
159         * Given a DOM-fragment, a corresponding Operation-object is built. This method recursively calls other buildFromDOM
160         * () - methods to validate the structure of the DOM-fragment.
161         * 
162         * @param element
163         *            to build from
164         * @return the Bean of the DOM
165         * 
166         * @throws FilterConstructionException
167         *             if the structure of the DOM-fragment is invalid
168         */
169        public static Operation buildFromDOM( Element element )
170                                throws FilterConstructionException {
171    
172            // check if root element's name equals 'PropertyIsInstanceOf'
173            if ( !element.getLocalName().equals( "PropertyIsInstanceOf" ) )
174                throw new FilterConstructionException( "Name of element does not equal 'PropertyIsInstanceOf'!" );
175    
176            ElementList children = XMLTools.getChildElements( element );
177            if ( children.getLength() != 2 ) {
178                throw new FilterConstructionException( "'PropertyIsInstanceOf' requires exactly 2 elements!" );
179            }
180    
181            PropertyName propertyName = (PropertyName) PropertyName.buildFromDOM( children.item( 0 ) );
182            QualifiedName typeName = null;
183            try {
184                typeName = XMLTools.getRequiredNodeAsQualifiedName( element, "ogc:Literal/text()", nsContext );
185            } catch ( XMLParsingException e ) {
186                throw new FilterConstructionException( e.getMessage() );
187            }
188            return new PropertyIsInstanceOfOperation( propertyName, typeName );
189        }
190    
191        /**
192         * @return the propertyName of this Operation
193         */
194        public PropertyName getPropertyName() {
195            return propertyName;
196        }
197    
198        /**
199         * @return the typeName
200         */
201        public QualifiedName getTypeName() {
202            return typeName;
203        }
204    
205    }