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 }