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 }