001 //$HeadURL: http://svn.wald.intevation.org/svn/deegree/base/trunk/src/org/deegree/graphics/displayelements/ScaledFeature.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.graphics.displayelements; 037 038 import java.util.HashMap; 039 import java.util.Map; 040 041 import org.deegree.datatypes.QualifiedName; 042 import org.deegree.datatypes.Types; 043 import org.deegree.io.datastore.PropertyPathResolvingException; 044 import org.deegree.model.feature.DefaultFeature; 045 import org.deegree.model.feature.Feature; 046 import org.deegree.model.feature.FeatureCollection; 047 import org.deegree.model.feature.FeatureFactory; 048 import org.deegree.model.feature.FeatureProperty; 049 import org.deegree.model.feature.schema.FeatureType; 050 import org.deegree.model.feature.schema.PropertyType; 051 import org.deegree.model.spatialschema.Envelope; 052 import org.deegree.model.spatialschema.Geometry; 053 import org.deegree.model.spatialschema.GeometryException; 054 import org.deegree.ogcbase.PropertyPath; 055 056 /** 057 * This class is a wrapper for a Feature and a Feature itself. 058 * <p> 059 * It adds a special behavior/property to a feature that is required by deegree DisplayElements. This special behavior 060 * is an additional property named "$SCALE". In opposite to conventional properties this one can change its value during 061 * lifetime of a feature without changing the underlying feature itself. <br> 062 * The class is use to offer users the opportunity to use the scale of a map within expressions embedded in SLD 063 * rules/symbolizers, i.e. this enables a user to define that a symbol shall appear in 10m size independ of a map's 064 * scale. 065 * 066 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a> 067 * @author last edited by: $Author: apoth $ 068 * 069 * @version $Revision: 29966 $, $Date: 2011-03-09 15:19:04 +0100 (Wed, 09 Mar 2011) $ 070 */ 071 public class ScaledFeature implements Feature { 072 073 private Feature feature; 074 075 private FeatureType ft; 076 077 private FeatureProperty[] props; 078 079 private Map<String, String> attributeMap = new HashMap<String, String>(); 080 081 /** 082 * 083 * @param feature 084 * feature wrap 085 * @param scale 086 * maps scale (should be -1 if not known) 087 */ 088 public ScaledFeature( Feature feature, double scale ) { 089 this.feature = feature; 090 PropertyType[] ftp = feature.getFeatureType().getProperties(); 091 PropertyType[] ftp2 = new PropertyType[ftp.length + 1]; 092 for ( int i = 0; i < ftp.length; i++ ) { 093 ftp2[i] = ftp[i]; 094 } 095 QualifiedName qn = new QualifiedName( feature.getName().getPrefix(), "$SCALE", feature.getName().getNamespace() ); 096 ftp2[ftp2.length - 1] = FeatureFactory.createSimplePropertyType( qn, Types.DOUBLE, false ); 097 FeatureProperty[] o = feature.getProperties(); 098 props = new FeatureProperty[o.length + 1]; 099 for ( int i = 0; i < o.length; i++ ) { 100 props[i] = o[i]; 101 } 102 props[props.length - 1] = FeatureFactory.createFeatureProperty( qn, new Double( scale ) ); 103 ft = FeatureFactory.createFeatureType( feature.getFeatureType().getName(), false, ftp2 ); 104 } 105 106 /** 107 * @return features owner 108 */ 109 public FeatureProperty getOwner() { 110 return feature.getOwner(); 111 } 112 113 /** 114 * @return features name 115 */ 116 public QualifiedName getName() { 117 return feature.getName(); 118 } 119 120 /** 121 * @see Feature#getDefaultGeometryPropertyValue() 122 */ 123 public Geometry getDefaultGeometryPropertyValue() { 124 return feature.getDefaultGeometryPropertyValue(); 125 } 126 127 /** 128 * @return features envelope 129 */ 130 public Envelope getBoundedBy() 131 throws GeometryException { 132 return feature.getBoundedBy(); 133 } 134 135 /** 136 * @see Feature#getFeatureType() the returned feature type contains all properties of the wrapped feature plus a 137 * property named '$SCALE' 138 */ 139 public FeatureType getFeatureType() { 140 return ft; 141 } 142 143 /** 144 * @see Feature#getGeometryPropertyValues() 145 */ 146 public Geometry[] getGeometryPropertyValues() { 147 return feature.getGeometryPropertyValues(); 148 } 149 150 /** 151 * @see Feature#getId() 152 */ 153 public String getId() { 154 return feature.getId(); 155 } 156 157 /** 158 * @see Feature#getProperties() the returned array contains all properties of the wrapped feature plus a property 159 * named '$SCALE' 160 */ 161 public FeatureProperty[] getProperties() { 162 return props; 163 } 164 165 /** 166 * The property '$SCALE' has the highest valid index 167 */ 168 public FeatureProperty[] getProperties( int index ) { 169 return new FeatureProperty[] { props[index] }; 170 } 171 172 /** 173 * use '$SCALE' to access the scale property value 174 */ 175 public FeatureProperty getDefaultProperty( QualifiedName name ) { 176 QualifiedName qn = new QualifiedName( "$SCALE" ); 177 if ( name.equals( qn ) ) { 178 return props[props.length - 1]; 179 } 180 return feature.getDefaultProperty( name ); 181 } 182 183 /** 184 * @param name 185 * @return property array 186 */ 187 public FeatureProperty[] getProperties( QualifiedName name ) { 188 if ( name.getLocalName().equalsIgnoreCase( "$SCALE" ) ) { 189 return new FeatureProperty[] { props[props.length - 1] }; 190 } 191 return feature.getProperties( name ); 192 } 193 194 /** 195 * @param path 196 * @return property 197 */ 198 public FeatureProperty getDefaultProperty( PropertyPath path ) 199 throws PropertyPathResolvingException { 200 if ( path.getStep( 0 ).getPropertyName().getLocalName().equalsIgnoreCase( "$SCALE" ) ) { 201 return props[props.length - 1]; 202 } 203 return feature.getDefaultProperty( path ); 204 } 205 206 public void setProperty( FeatureProperty property, int index ) { 207 feature.setProperty( property, index ); 208 } 209 210 /** 211 * sets the features scale. Expected is the scale denominator as defined by OGC SLD specification 212 * 213 * @param scale 214 */ 215 public void setScale( double scale ) { 216 // must be multiplied with pixel size to get scale as length 217 // of a pixels diagonal measured in meter 218 props[props.length - 1].setValue( scale * 0.00028 ); 219 } 220 221 /** 222 * returns the features scale 223 * 224 * @return the features scale 225 */ 226 public double getScale() { 227 return ( (Double) props[props.length - 1].getValue() ).doubleValue(); 228 } 229 230 /** 231 * @param property 232 */ 233 public void addProperty( FeatureProperty property ) { 234 this.feature.addProperty( property ); 235 } 236 237 /** 238 * @param propertyName 239 */ 240 public void removeProperty( QualifiedName propertyName ) { 241 this.feature.removeProperty( propertyName ); 242 } 243 244 /** 245 * @param oldProperty 246 * @param newProperty 247 */ 248 public void replaceProperty( FeatureProperty oldProperty, FeatureProperty newProperty ) { 249 this.feature.replaceProperty( oldProperty, newProperty ); 250 } 251 252 /** 253 * @param fid 254 */ 255 public void setId( String fid ) { 256 feature.setId( fid ); 257 } 258 259 /** 260 * Returns the attribute value of the attribute with the specified name. 261 * 262 * @param name 263 * name of the attribute 264 * @return the attribute value 265 */ 266 public String getAttribute( String name ) { 267 return this.attributeMap.get( name ); 268 } 269 270 /** 271 * Returns all attributes of the feature. 272 * 273 * @return all attributes, keys are names, values are attribute values 274 */ 275 public Map<String, String> getAttributes() { 276 return this.attributeMap; 277 } 278 279 /** 280 * Sets the value of the attribute with the given name. 281 * 282 * @param name 283 * name of the attribute 284 * @param value 285 * value to set 286 */ 287 public void setAttribute( String name, String value ) { 288 this.attributeMap.put( name, value ); 289 } 290 291 /** 292 * Sets the feature type of this feature. 293 * 294 * @param ft 295 * feature type to set 296 */ 297 public void setFeatureType( FeatureType ft ) { 298 feature.setFeatureType( ft ); 299 } 300 301 /* 302 * (non-Javadoc) 303 * 304 * @see org.deegree.model.feature.Feature#setEnvelopesUpdated() 305 */ 306 public void setEnvelopesUpdated() { 307 feature.setEnvelopesUpdated(); 308 } 309 310 /* 311 * (non-Javadoc) 312 * 313 * @see org.deegree.model.feature.Feature#cloneDeep() 314 */ 315 public Feature cloneDeep() 316 throws CloneNotSupportedException { 317 Feature tmp = feature.cloneDeep(); 318 return new ScaledFeature( tmp, getScale() ); 319 } 320 321 @Override 322 public Object clone() 323 throws CloneNotSupportedException { 324 Feature tmp = (Feature) feature.clone(); 325 return new ScaledFeature( tmp, getScale() ); 326 } 327 328 @Override 329 public String toString() { 330 String ret = getClass().getName(); 331 ret = ""; 332 for ( int i = 0; i < props.length; i++ ) { 333 if ( props[i].getValue() instanceof FeatureCollection ) { 334 ret += ( " " + props[i].getName() + ": "); 335 ret += "\n"; 336 ret += ( " " +(FeatureCollection) props[i].getValue() ).toString(); 337 ret += "\n"; 338 } else if ( props[i].getValue() instanceof DefaultFeature ) { 339 ret += ( " " +props[i].getName() + ": "); 340 ret += "\n"; 341 ret += ( " " +(DefaultFeature) props[i].getValue() ).toString(); 342 ret += "\n"; 343 } else if ( props[i].getValue() instanceof Geometry ) { 344 ret += props[i].getName(); 345 ret += "\n"; 346 } else { 347 String o = "null"; 348 if ( props[i].getValue() != null ) { 349 o = props[i].getValue().toString(); 350 } 351 ret += (props[i].getName() + " = " + o ); 352 ret += "\n"; 353 } 354 } 355 return ret; 356 } 357 358 }