001 //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.4_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: 25586 $, $Date: 2010-07-28 16:50:09 +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 }