001 //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/graphics/displayelements/ScaledFeature.java $ 002 /*---------------- FILE HEADER ------------------------------------------ 003 004 This file is part of deegree. 005 Copyright (C) 2001-2008 by: 006 EXSE, Department of Geography, University of Bonn 007 http://www.giub.uni-bonn.de/deegree/ 008 lat/lon GmbH 009 http://www.lat-lon.de 010 011 This library is free software; you can redistribute it and/or 012 modify it under the terms of the GNU Lesser General Public 013 License as published by the Free Software Foundation; either 014 version 2.1 of the License, or (at your option) any later version. 015 016 This library is distributed in the hope that it will be useful, 017 but WITHOUT ANY WARRANTY; without even the implied warranty of 018 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 019 Lesser General Public License for more details. 020 021 You should have received a copy of the GNU Lesser General Public 022 License along with this library; if not, write to the Free Software 023 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 024 025 Contact: 026 027 Andreas Poth 028 lat/lon GmbH 029 Aennchenstr. 19 030 53115 Bonn 031 Germany 032 E-Mail: poth@lat-lon.de 033 034 Prof. Dr. Klaus Greve 035 Department of Geography 036 University of Bonn 037 Meckenheimer Allee 166 038 53115 Bonn 039 Germany 040 E-Mail: greve@giub.uni-bonn.de 041 042 ---------------------------------------------------------------------------*/ 043 package org.deegree.graphics.displayelements; 044 045 import java.util.HashMap; 046 import java.util.Map; 047 048 import org.deegree.datatypes.QualifiedName; 049 import org.deegree.datatypes.Types; 050 import org.deegree.io.datastore.PropertyPathResolvingException; 051 import org.deegree.model.feature.Feature; 052 import org.deegree.model.feature.FeatureFactory; 053 import org.deegree.model.feature.FeatureProperty; 054 import org.deegree.model.feature.schema.FeatureType; 055 import org.deegree.model.feature.schema.PropertyType; 056 import org.deegree.model.spatialschema.Envelope; 057 import org.deegree.model.spatialschema.Geometry; 058 import org.deegree.model.spatialschema.GeometryException; 059 import org.deegree.ogcbase.PropertyPath; 060 061 /** 062 * This class is a wrapper for a Feature and a Feature itself. 063 * <p> 064 * It adds a special behavior/property to a feature that is required by deegree DisplayElements. 065 * This special behavior is an additional property named "$SCALE". In opposite to conventional 066 * properties this one can change its value during lifetime of a feature without changing the 067 * underlying feature itself. <br> 068 * The class is use to offer users the opportunity to use the scale of a map within expressions 069 * embedded in SLD rules/symbolizers, i.e. this enables a user to define that a symbol shall appear 070 * in 10m size independ of a map's scale. 071 * 072 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a> 073 * @author last edited by: $Author: apoth $ 074 * 075 * @version $Revision: 9340 $, $Date: 2007-12-27 13:32:12 +0100 (Do, 27 Dez 2007) $ 076 */ 077 public class ScaledFeature implements Feature { 078 079 private Feature feature; 080 081 private FeatureType ft; 082 083 private FeatureProperty[] props; 084 085 private Map<String, String> attributeMap = new HashMap<String, String>(); 086 087 /** 088 * 089 * @param feature 090 * feature wrap 091 * @param scale 092 * maps scale (should be -1 if not known) 093 */ 094 public ScaledFeature( Feature feature, double scale ) { 095 this.feature = feature; 096 PropertyType[] ftp = feature.getFeatureType().getProperties(); 097 PropertyType[] ftp2 = new PropertyType[ftp.length + 1]; 098 for ( int i = 0; i < ftp.length; i++ ) { 099 ftp2[i] = ftp[i]; 100 } 101 QualifiedName qn = new QualifiedName( feature.getName().getPrefix(), "$SCALE", feature.getName().getNamespace() ); 102 ftp2[ftp2.length - 1] = FeatureFactory.createSimplePropertyType( qn, Types.DOUBLE, false ); 103 FeatureProperty[] o = feature.getProperties(); 104 props = new FeatureProperty[o.length + 1]; 105 for ( int i = 0; i < o.length; i++ ) { 106 props[i] = o[i]; 107 } 108 props[props.length - 1] = FeatureFactory.createFeatureProperty( qn, new Double( scale ) ); 109 ft = FeatureFactory.createFeatureType( feature.getFeatureType().getName(), false, ftp2 ); 110 } 111 112 /** 113 * @return features owner 114 */ 115 public FeatureProperty getOwner() { 116 return feature.getOwner(); 117 } 118 119 /** 120 * @return feature description 121 */ 122 public String getDescription() { 123 return feature.getDescription(); 124 } 125 126 /** 127 * @return features name 128 */ 129 public QualifiedName getName() { 130 return feature.getName(); 131 } 132 133 /** 134 * @see Feature#getDefaultGeometryPropertyValue() 135 */ 136 public Geometry getDefaultGeometryPropertyValue() { 137 return feature.getDefaultGeometryPropertyValue(); 138 } 139 140 /** 141 * @return features envelope 142 */ 143 public Envelope getBoundedBy() 144 throws GeometryException { 145 return feature.getBoundedBy(); 146 } 147 148 /** 149 * @see Feature#getFeatureType() the returned feature type contains all properties of the 150 * wrapped feature plus a property named '$SCALE' 151 */ 152 public FeatureType getFeatureType() { 153 return ft; 154 } 155 156 /** 157 * @see Feature#getGeometryPropertyValues() 158 */ 159 public Geometry[] getGeometryPropertyValues() { 160 return feature.getGeometryPropertyValues(); 161 } 162 163 /** 164 * @see Feature#getId() 165 */ 166 public String getId() { 167 return feature.getId(); 168 } 169 170 /** 171 * @see Feature#getProperties() the returned array contains all properties of the wrapped 172 * feature plus a property named '$SCALE' 173 */ 174 public FeatureProperty[] getProperties() { 175 return props; 176 } 177 178 /** 179 * @see Feature#getProperties(int) The property '$SCALE' has the highest valid index 180 */ 181 public FeatureProperty[] getProperties( int index ) { 182 return new FeatureProperty[] { props[index] }; 183 } 184 185 /** 186 * @see Feature#getDefaultProperty(String) use '$SCALE' to access the scale property value 187 */ 188 public FeatureProperty getDefaultProperty( QualifiedName name ) { 189 QualifiedName qn = new QualifiedName( "$SCALE" ); 190 if ( name.equals( qn ) ) { 191 return props[props.length - 1]; 192 } 193 return feature.getDefaultProperty( name ); 194 } 195 196 /** 197 * @param name 198 * @return property array 199 */ 200 public FeatureProperty[] getProperties( QualifiedName name ) { 201 if ( name.getLocalName().equalsIgnoreCase( "$SCALE" ) ) { 202 return new FeatureProperty[] { props[props.length - 1] }; 203 } 204 return feature.getProperties( name ); 205 } 206 207 /** 208 * @param path 209 * @return property 210 */ 211 public FeatureProperty getDefaultProperty( PropertyPath path ) 212 throws PropertyPathResolvingException { 213 if ( path.getStep( 0 ).getPropertyName().getLocalName().equalsIgnoreCase( "$SCALE" ) ) { 214 return props[props.length - 1]; 215 } 216 return feature.getDefaultProperty( path ); 217 } 218 219 /** 220 * @see Feature#setProperty(FeatureProperty) 221 */ 222 public void setProperty( FeatureProperty property, int index ) { 223 feature.setProperty( property, index ); 224 } 225 226 /** 227 * sets the features scale. Expected is the scale denominator as defined by OGC SLD 228 * specification 229 * 230 * @param scale 231 */ 232 public void setScale( double scale ) { 233 // must be multiplied with pixel size to get scale as length 234 // of a pixels diagonal measured in meter 235 props[props.length - 1].setValue( scale * 0.00028 ); 236 } 237 238 /** 239 * returns the features scale 240 * 241 * @return the features scale 242 */ 243 public double getScale() { 244 return ( (Double) props[props.length - 1].getValue() ).doubleValue(); 245 } 246 247 /** 248 * @param property 249 */ 250 public void addProperty( FeatureProperty property ) { 251 this.feature.addProperty( property ); 252 } 253 254 /** 255 * @param propertyName 256 */ 257 public void removeProperty( QualifiedName propertyName ) { 258 this.feature.removeProperty( propertyName ); 259 } 260 261 /** 262 * @param oldProperty 263 * @param newProperty 264 */ 265 public void replaceProperty( FeatureProperty oldProperty, FeatureProperty newProperty ) { 266 this.feature.replaceProperty( oldProperty, newProperty ); 267 } 268 269 /** 270 * @param fid 271 */ 272 public void setId( String fid ) { 273 feature.setId( fid ); 274 } 275 276 /** 277 * Returns the attribute value of the attribute with the specified name. 278 * 279 * @param name 280 * name of the attribute 281 * @return the attribute value 282 */ 283 public String getAttribute( String name ) { 284 return this.attributeMap.get( name ); 285 } 286 287 /** 288 * Returns all attributes of the feature. 289 * 290 * @return all attributes, keys are names, values are attribute values 291 */ 292 public Map<String, String> getAttributes() { 293 return this.attributeMap; 294 } 295 296 /** 297 * Sets the value of the attribute with the given name. 298 * 299 * @param name 300 * name of the attribute 301 * @param value 302 * value to set 303 */ 304 public void setAttribute( String name, String value ) { 305 this.attributeMap.put( name, value ); 306 } 307 308 /** 309 * Sets the feature type of this feature. 310 * 311 * @param ft 312 * feature type to set 313 */ 314 public void setFeatureType( FeatureType ft ) { 315 feature.setFeatureType( ft ); 316 } 317 318 /* 319 * (non-Javadoc) 320 * 321 * @see org.deegree.model.feature.Feature#setEnvelopesUpdated() 322 */ 323 public void setEnvelopesUpdated() { 324 feature.setEnvelopesUpdated(); 325 } 326 }