//$Header: /home/deegree/jail/deegreerepository/deegree/src/org/deegree/model/feature/AbstractFeature.java,v 1.23 2006/11/02 10:18:23 mschneider Exp $
/*---------------- FILE HEADER ------------------------------------------
This file is part of deegree.
Copyright (C) 2001-2006 by:
EXSE, Department of Geography, University of Bonn
http://www.giub.uni-bonn.de/deegree/
lat/lon GmbH
http://www.lat-lon.de
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Contact:
Andreas Poth
lat/lon GmbH
Aennchenstr. 19
53115 Bonn
Germany
E-Mail: poth@lat-lon.de
Prof. Dr. Klaus Greve
Department of Geography
University of Bonn
Meckenheimer Allee 166
53115 Bonn
Germany
E-Mail: greve@giub.uni-bonn.de
---------------------------------------------------------------------------*/
package org.deegree.model.feature;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.deegree.datatypes.QualifiedName;
import org.deegree.model.feature.schema.FeatureType;
import org.deegree.model.spatialschema.Envelope;
import org.deegree.model.spatialschema.Geometry;
import org.deegree.model.spatialschema.GeometryException;
import org.deegree.model.spatialschema.GeometryFactory;
import org.deegree.model.spatialschema.Point;
/**
* @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
* @author last edited by: $Author: mschneider $
*
* @version 1.0. $Revision: 1.23 $, $Date: 2006/11/02 10:18:23 $
*/
abstract class AbstractFeature implements Feature {
private String id;
protected FeatureType featureType;
protected Envelope envelope;
protected boolean envelopeCalculated;
protected String description;
protected FeatureProperty owner;
private Map<String, String> attributeMap = new HashMap<String, String>();
/**
* @param id
* @param featureType
*/
AbstractFeature( String id, FeatureType featureType ) {
this.id = id;
this.featureType = featureType;
}
/**
* @param id
* @param featureType
*/
AbstractFeature( String id, FeatureType featureType, FeatureProperty owner ) {
this.id = id;
this.featureType = featureType;
this.owner = owner;
}
public String getDescription() {
return description;
}
public QualifiedName getName() {
return featureType.getName();
}
/**
* Returns the envelope / boundingbox of the feature. The bounding box
* will be created in a recursion. That means if a property of the feature (a)
* contains another feature (b) the bounding box of b will be merged with the
* bounding box calculated from the geometry properties of a. A feature has no
* geometry properties and no properties that are features (and having a
* bounding box theirself) <code>null</code> will be returned.
*/
public Envelope getBoundedBy()
throws GeometryException {
if ( !this.envelopeCalculated) {
getBoundedBy(new HashSet<Feature>());
}
return this.envelope;
}
public FeatureProperty getOwner() {
return this.owner;
}
/**
* returns the id of the Feature. the id has to be a name space that must be unique for each
* feature. use the adress of the datasource in addition to a number for example .
*/
public String getId() {
return id;
}
public void setId( String fid ) {
this.id = fid;
}
/**
* returns the FeatureType of this Feature
*
*/
public FeatureType getFeatureType() {
return featureType;
}
/**
* Sets the feature type of this feature.
*
* @param ft feature type to set
*/
public void setFeatureType( FeatureType ft ) {
this.featureType = ft;
}
/**
* resets the envelope of the feature so the next call of getBounds() will force a
* re-calculation
*
*/
protected void resetBounds() {
envelope = null;
}
/**
* Returns the attribute value of the attribute with the specified name.
*
* @param name name of the attribute
* @return the attribute value
*/
public String getAttribute( String name ) {
return this.attributeMap.get( name );
}
/**
* Returns all attributes of the feature.
*
* @return all attributes, keys are names, values are attribute values
*/
public Map<String, String> getAttributes() {
return this.attributeMap;
}
/**
* Sets the value of the attribute with the given name.
*
* @param name name of the attribute
* @param value value to set
*/
public void setAttribute( String name, String value ) {
this.attributeMap.put( name, value );
}
/**
* Returns the {@link Envelope} of the feature. If the envelope has not been calculated yet,
* it is calculated recursively, using the given feature set to detected cycles in the feature
* structure.
*
* @param features
* used to detected cycles in feature structure and prevent endless recursion
* @return envelope of the feature
* @throws GeometryException
*/
private Envelope getBoundedBy (Set<Feature> features) throws GeometryException {
if ( !this.envelopeCalculated) {
this.envelope = calcEnvelope(features);
this.envelopeCalculated = true;
}
return this.envelope;
}
/**
* Calculates the envelope of the feature recursively. Respects all geometry properties
* and sub features of the feature.
*
* @param features
* used to detected cycles in feature structure and prevent endless recursion
* @return envelope of the feature
* @throws GeometryException
*/
private Envelope calcEnvelope(Set<Feature> features)
throws GeometryException {
Envelope combinedEnvelope = null;
if (features.contains(this)) {
return combinedEnvelope;
}
features.add(this);
FeatureProperty[] props = getProperties();
for ( FeatureProperty prop : props ) {
if ( prop != null ) {
Object propValue = prop.getValue();
if ( propValue instanceof Geometry ) {
Geometry geom = (Geometry) propValue;
Envelope env = null;
if ( geom instanceof Point ) {
env = GeometryFactory.createEnvelope( ( (Point) geom ).getPosition(),
( (Point) geom ).getPosition(),
geom.getCoordinateSystem() );
} else {
env = geom.getEnvelope();
}
if (combinedEnvelope == null) {
combinedEnvelope = env;
} else {
combinedEnvelope = combinedEnvelope.merge( env );
}
} else if ( propValue instanceof AbstractFeature ) {
Envelope subEnvelope = ( (AbstractFeature) propValue ).getBoundedBy(features);
if ( combinedEnvelope == null ) {
combinedEnvelope = subEnvelope;
} else if ( subEnvelope != null ) {
combinedEnvelope = combinedEnvelope.merge( subEnvelope );
}
}
}
}
return combinedEnvelope;
}
}
/***************************************************************************************************
* $Log: AbstractFeature.java,v $
* Revision 1.23 2006/11/02 10:18:23 mschneider
* Fixed #getBoundedBy(). Changed visibility of constructors to package protected.
*
* Revision 1.22 2006/10/31 16:53:19 mschneider
* Fixed null CRS in #getBoundedBy(Set<Feature>).
*
* Revision 1.21 2006/08/09 17:02:56 mschneider
* Fixed endless recursion in getBoundedBy().
*
* Revision 1.20 2006/05/09 15:51:37 poth
* *** empty log message ***
*
* Revision 1.19 2006/04/26 15:09:37 poth
* *** empty log message ***
*
* Revision 1.18 2006/04/26 13:34:09 poth
* *** empty log message ***
*
* Revision 1.17 2006/04/06 20:25:27 poth
* *** empty log message ***
*
* Revision 1.16 2006/03/30 21:20:26 poth
* *** empty log message ***
*
* Revision 1.15 2006/02/24 13:28:13 mschneider
* Added method setFeatureType().
*
* Revision 1.14 2006/02/09 14:54:19 mschneider
* Added "attributes" to Features.
*
* Revision 1.13 2006/02/03 18:12:07 mschneider
* Added method setId().
*
* Revision 1.12 2006/01/31 16:24:43 mschneider
* Changes due to refactoring of org.deegree.model.feature package.
*
* Revision 1.11 2006/01/30 16:20:10 mschneider
* Feature has a name on it's own now (and not from it's feature type). This is useful, because some features have no feature type.
*
* Revision 1.10 2005/12/11 18:31:05 poth
* no message
*
* Revision 1.9 2005/12/06 13:45:20 poth
* System.out.println substituted by logging api
*
* Revision 1.8 2005/12/05 09:25:17 deshmukh
* *** empty log message ***
*
* Revision 1.7 2005/11/21 18:41:26 mschneider
* Added methods for precise modification of the feature's properties.
*
* Revision 1.6 2005/11/16 13:44:59 mschneider
* Merge of wfs development branch.
*
* Revision 1.5.2.1 2005/11/14 19:51:41 mschneider
* Fixed compilation problems.
*
* Revision 1.5 2005/08/30 13:40:03 poth no message
*
* Revision 1.4 2005/08/24 16:09:26 mschneider Renamed GenericName to QualifiedName.
*
* Revision 1.3 2005/08/22 13:50:07 poth no message
*
* Revision 1.2 2005/06/16 08:27:31 poth no message
*
* Revision 1.1 2005/01/28 11:16:59 poth no message
*
**************************************************************************************************/