001: //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/trunk/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 04:32:12 -0800 (Thu, 27 Dec 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()
102: .getPrefix(), "$SCALE", feature.getName()
103: .getNamespace());
104: ftp2[ftp2.length - 1] = FeatureFactory
105: .createSimplePropertyType(qn, Types.DOUBLE, false);
106: FeatureProperty[] o = feature.getProperties();
107: props = new FeatureProperty[o.length + 1];
108: for (int i = 0; i < o.length; i++) {
109: props[i] = o[i];
110: }
111: props[props.length - 1] = FeatureFactory.createFeatureProperty(
112: qn, new Double(scale));
113: ft = FeatureFactory.createFeatureType(feature.getFeatureType()
114: .getName(), false, ftp2);
115: }
116:
117: /**
118: * @return features owner
119: */
120: public FeatureProperty getOwner() {
121: return feature.getOwner();
122: }
123:
124: /**
125: * @return feature description
126: */
127: public String getDescription() {
128: return feature.getDescription();
129: }
130:
131: /**
132: * @return features name
133: */
134: public QualifiedName getName() {
135: return feature.getName();
136: }
137:
138: /**
139: * @see Feature#getDefaultGeometryPropertyValue()
140: */
141: public Geometry getDefaultGeometryPropertyValue() {
142: return feature.getDefaultGeometryPropertyValue();
143: }
144:
145: /**
146: * @return features envelope
147: */
148: public Envelope getBoundedBy() throws GeometryException {
149: return feature.getBoundedBy();
150: }
151:
152: /**
153: * @see Feature#getFeatureType() the returned feature type contains all properties of the
154: * wrapped feature plus a property named '$SCALE'
155: */
156: public FeatureType getFeatureType() {
157: return ft;
158: }
159:
160: /**
161: * @see Feature#getGeometryPropertyValues()
162: */
163: public Geometry[] getGeometryPropertyValues() {
164: return feature.getGeometryPropertyValues();
165: }
166:
167: /**
168: * @see Feature#getId()
169: */
170: public String getId() {
171: return feature.getId();
172: }
173:
174: /**
175: * @see Feature#getProperties() the returned array contains all properties of the wrapped
176: * feature plus a property named '$SCALE'
177: */
178: public FeatureProperty[] getProperties() {
179: return props;
180: }
181:
182: /**
183: * @see Feature#getProperties(int) The property '$SCALE' has the highest valid index
184: */
185: public FeatureProperty[] getProperties(int index) {
186: return new FeatureProperty[] { props[index] };
187: }
188:
189: /**
190: * @see Feature#getDefaultProperty(String) use '$SCALE' to access the scale property value
191: */
192: public FeatureProperty getDefaultProperty(QualifiedName name) {
193: QualifiedName qn = new QualifiedName("$SCALE");
194: if (name.equals(qn)) {
195: return props[props.length - 1];
196: }
197: return feature.getDefaultProperty(name);
198: }
199:
200: /**
201: * @param name
202: * @return property array
203: */
204: public FeatureProperty[] getProperties(QualifiedName name) {
205: if (name.getLocalName().equalsIgnoreCase("$SCALE")) {
206: return new FeatureProperty[] { props[props.length - 1] };
207: }
208: return feature.getProperties(name);
209: }
210:
211: /**
212: * @param path
213: * @return property
214: */
215: public FeatureProperty getDefaultProperty(PropertyPath path)
216: throws PropertyPathResolvingException {
217: if (path.getStep(0).getPropertyName().getLocalName()
218: .equalsIgnoreCase("$SCALE")) {
219: return props[props.length - 1];
220: }
221: return feature.getDefaultProperty(path);
222: }
223:
224: /**
225: * @see Feature#setProperty(FeatureProperty)
226: */
227: public void setProperty(FeatureProperty property, int index) {
228: feature.setProperty(property, index);
229: }
230:
231: /**
232: * sets the features scale. Expected is the scale denominator as defined by OGC SLD
233: * specification
234: *
235: * @param scale
236: */
237: public void setScale(double scale) {
238: // must be multiplied with pixel size to get scale as length
239: // of a pixels diagonal measured in meter
240: props[props.length - 1].setValue(scale * 0.00028);
241: }
242:
243: /**
244: * returns the features scale
245: *
246: * @return the features scale
247: */
248: public double getScale() {
249: return ((Double) props[props.length - 1].getValue())
250: .doubleValue();
251: }
252:
253: /**
254: * @param property
255: */
256: public void addProperty(FeatureProperty property) {
257: this .feature.addProperty(property);
258: }
259:
260: /**
261: * @param propertyName
262: */
263: public void removeProperty(QualifiedName propertyName) {
264: this .feature.removeProperty(propertyName);
265: }
266:
267: /**
268: * @param oldProperty
269: * @param newProperty
270: */
271: public void replaceProperty(FeatureProperty oldProperty,
272: FeatureProperty newProperty) {
273: this .feature.replaceProperty(oldProperty, newProperty);
274: }
275:
276: /**
277: * @param fid
278: */
279: public void setId(String fid) {
280: feature.setId(fid);
281: }
282:
283: /**
284: * Returns the attribute value of the attribute with the specified name.
285: *
286: * @param name
287: * name of the attribute
288: * @return the attribute value
289: */
290: public String getAttribute(String name) {
291: return this .attributeMap.get(name);
292: }
293:
294: /**
295: * Returns all attributes of the feature.
296: *
297: * @return all attributes, keys are names, values are attribute values
298: */
299: public Map<String, String> getAttributes() {
300: return this .attributeMap;
301: }
302:
303: /**
304: * Sets the value of the attribute with the given name.
305: *
306: * @param name
307: * name of the attribute
308: * @param value
309: * value to set
310: */
311: public void setAttribute(String name, String value) {
312: this .attributeMap.put(name, value);
313: }
314:
315: /**
316: * Sets the feature type of this feature.
317: *
318: * @param ft
319: * feature type to set
320: */
321: public void setFeatureType(FeatureType ft) {
322: feature.setFeatureType(ft);
323: }
324:
325: /*
326: * (non-Javadoc)
327: *
328: * @see org.deegree.model.feature.Feature#setEnvelopesUpdated()
329: */
330: public void setEnvelopesUpdated() {
331: feature.setEnvelopesUpdated();
332: }
333: }
|