001: package org.geotools.feature.iso;
002:
003: import java.util.Collection;
004: import java.util.HashMap;
005: import java.util.Iterator;
006: import java.util.List;
007: import java.util.Map;
008:
009: import org.geotools.geometry.jts.ReferencedEnvelope;
010: import org.opengis.feature.Attribute;
011: import org.opengis.feature.ComplexAttribute;
012: import org.opengis.feature.Feature;
013: import org.opengis.feature.GeometryAttribute;
014: import org.opengis.feature.type.AttributeDescriptor;
015: import org.opengis.feature.type.FeatureType;
016: import org.opengis.geometry.BoundingBox;
017: import org.opengis.referencing.crs.CoordinateReferenceSystem;
018:
019: import com.vividsolutions.jts.geom.Geometry;
020:
021: /**
022: * While in transition to the new FM, this class implements the deprecated
023: * {@linkplain org.opengis.feature.Feature} in order to no have to touch all the
024: * library.
025: * <p>
026: * NOTE all the methods from the old geotools Feature interface throws
027: * UnsupportedOperationException
028: * </p>
029: *
030: * @author gabriel
031: */
032: public class FeatureImpl extends ComplexAttributeImpl implements
033: Feature {
034:
035: private Map userData = new HashMap();
036:
037: /**
038: * Optional, may be null
039: */
040: CoordinateReferenceSystem crs;
041:
042: /**
043: * Optional, may be null
044: */
045: GeometryAttribute defaultGeometry;
046:
047: /**
048: * Create a Feature with the following content.
049: *
050: * @param values Collectio of Properties (aka Attributes and/or Associations)
051: * @param desc Nested descriptor
052: * @param id Feature ID
053: */
054: public FeatureImpl(Collection values, AttributeDescriptor desc,
055: String id) {
056: super (values, desc, id);
057: // super takes care of checking id since type is always
058: // identified
059: }
060:
061: /**
062: * Create a Feature with the following content.
063: *
064: * @param values Collectio of Properties (aka Attributes and/or Associations)
065: * @param type Type of feature to be created
066: * @param id Feature ID
067: */
068: public FeatureImpl(Collection values, FeatureType type, String id) {
069: super (values, type, id);
070: }
071:
072: public void putUserData(Object key, Object value) {
073: userData.put(key, value);
074: }
075:
076: public Object getUserData(Object key) {
077: return userData.get(key);
078: }
079:
080: public void setCRS(CoordinateReferenceSystem crs) {
081: this .crs = crs;
082: }
083:
084: public CoordinateReferenceSystem getCRS() {
085: // JD: commenting out the implementation of this method, there is too
086: // much jumping through hoops here, this is a data object, it should
087: // contain this logic. The logic should be present in the object
088: // constructing the feature.
089: return crs;
090: // FeatureType type = (FeatureType)getType();
091: // CoordinateReferenceSystem crs = type.getCRS();
092: // if (crs != null)
093: // return crs;
094: //
095: // GeometryType defaultGeomType =
096: // (GeometryType) type.getDefaultGeometry().getType();
097: //
098: // if (defaultGeomType != null) {
099: // // use the value of the Attribute, if found. Else
100: // // the one of the default type
101: // Geometry geom = (Geometry)getDefaultGeometry();
102: // if (geom != null) {
103: // Object instanceMetadata = geom.getUserData();
104: // if (instanceMetadata instanceof CoordinateReferenceSystem) {
105: // crs = (CoordinateReferenceSystem) instanceMetadata;
106: // }
107: // }
108: //
109: // if (crs == null) {
110: // crs = defaultGeomType.getCRS();
111: // }
112: // }
113: // return crs;
114: }
115:
116: /**
117: * Get the total bounds of this feature which is calculated by doing a union
118: * of the bounds of each geometry this feature is associated with.
119: *
120: * @return An Envelope containing the total bounds of this Feature.
121: *
122: * @task REVISIT: what to return if there are no geometries in the feature?
123: * For now we'll return a null envelope, make this part of interface?
124: * (IanS - by OGC standards, all Feature must have geom)
125: */
126: public BoundingBox getBounds() {
127:
128: ReferencedEnvelope bounds = new ReferencedEnvelope(getCRS());
129: if (((FeatureType) getType()).getDefaultGeometry() != null) {
130: for (Iterator itr = attributes().iterator(); itr.hasNext();) {
131: Attribute attribute = (Attribute) itr.next();
132: if (attribute instanceof GeometryAttribute) {
133: // JD: unsafe cast to geometry
134: Geometry geom = (Geometry) ((GeometryAttribute) attribute)
135: .getValue();
136: if (geom != null) {
137: bounds.expandToInclude(geom
138: .getEnvelopeInternal());
139: }
140: }
141: }
142: }
143: return bounds;
144: }
145:
146: public GeometryAttribute getDefaultGeometry() {
147: return defaultGeometry;
148:
149: // GeometryType geometryType = (GeometryType)
150: // ((FeatureType)getType()).getDefaultGeometry().getType();
151: //
152: // if (geometryType != null) {
153: // for (Iterator itr = attribtues.iterator(); itr.hasNext();) {
154: // Attribute attribute = (Attribute) itr.next();
155: // if (attribute instanceof GeometryAttribute) {
156: // if (attribute.getType().equals(geometryType)) {
157: // return (GeometryAttribute)attribute;
158: // }
159: // }
160: // }
161: // }
162: //
163: // return null;
164: }
165:
166: public void setDefaultGeometry(GeometryAttribute defaultGeometry) {
167: this .defaultGeometry = defaultGeometry;
168: }
169:
170: public void setDefaultGeometry(Geometry g) {
171: AttributeDescriptor geometry = ((FeatureType) getType())
172: .getDefaultGeometry();
173: if (geometry == null) {
174: throw new IllegalArgumentException(
175: "FeatureType has no default geometry attribute");
176: }
177:
178: List/* <Attribute> */geoms = get(geometry.getName());
179: if (geoms.size() > 0) {
180: Attribute att = (Attribute) geoms.get(0);
181: att.setValue(g);
182: }
183: }
184:
185: public String toString() {
186: StringBuffer sb = new StringBuffer(getClass().getName());
187: Collection/* <Attribute> */atts = this .properties;
188:
189: sb.append("<").append(this .ID);
190: if (DESCRIPTOR != null) {
191: sb.append(",").append(DESCRIPTOR.getName().getLocalPart());
192: }
193: sb.append(">");
194:
195: sb.append(getType().getName().getLocalPart()).append("=[");
196: for (Iterator itr = atts.iterator(); itr.hasNext();) {
197: Attribute att = (Attribute) itr.next();
198: sb.append(att.getDescriptor().getName().getLocalPart());
199: if (!(att instanceof ComplexAttribute)) {
200: sb.append('=');
201: sb.append(att.getValue());
202: }
203: if (itr.hasNext())
204: sb.append(",");
205: }
206: sb.append("]");
207: return sb.toString();
208: }
209:
210: // public Object clone(){
211: // //TODO: use builder to create new feature
212: // FeatureImpl copy = new FeatureImpl(ID, DESCRIPTOR,builder);
213: // copy.set(get());
214: // copy.setProperties(new HashMap(properties));
215: // return copy;
216: // }
217: }
|