001: package org.geotools.feature.iso.simple;
002:
003: import java.util.ArrayList;
004: import java.util.Arrays;
005: import java.util.Collection;
006: import java.util.Collections;
007: import java.util.HashMap;
008: import java.util.List;
009: import java.util.Map;
010:
011: import org.opengis.feature.Attribute;
012: import org.opengis.feature.GeometryAttribute;
013: import org.opengis.feature.simple.SimpleFeature;
014: import org.opengis.feature.simple.SimpleFeatureType;
015: import org.opengis.feature.type.AttributeDescriptor;
016: import org.opengis.feature.type.AttributeType;
017: import org.opengis.feature.type.Name;
018: import org.opengis.feature.type.PropertyDescriptor;
019: import org.opengis.geometry.BoundingBox;
020: import org.opengis.referencing.crs.CoordinateReferenceSystem;
021:
022: /**
023: * This class is designed to be fast and lighweight, making use of the
024: * assumptions of SimpleFeature to do everything in the easiest manner possible.
025: * <p>
026: * This code operates under the assumption that the most common use will be
027: * through the SimpleFeatureAPI and that we should lazyly create any wrapers
028: * (such as AttributeDescriptor)as needed.
029: * </p>
030: * <p>
031: * In the interests of going quick we will not perform any tests here and allow
032: * a subclass classed StrickSimpleFeature to provide a decent implementation as
033: * required.
034: * </p>
035: *
036: * @author Jody Garnett
037: */
038: public class ArraySimpleFeature implements SimpleFeature {
039: SimpleFeatureType type;
040:
041: private String id;
042:
043: Object values[];
044:
045: private List list; // list of values
046:
047: private List attributes; // attribute descriptors (wrapers)
048:
049: private int defaultIndex;
050:
051: private Map userData;
052:
053: public ArraySimpleFeature(SimpleFeatureType type, String id) {
054: this (type, id, new Object[type.getProperties().size()]);
055: }
056:
057: public ArraySimpleFeature(SimpleFeatureType type, String id,
058: Object[] values) {
059: this .type = type;
060: this .id = id;
061: this .values = values;
062: this .list = Arrays.asList(values);
063: this .defaultIndex = type.indexOf(type.getDefaultGeometry()
064: .getName().getLocalPart());
065: }
066:
067: public List getTypes() {
068: return type.getTypes();
069: }
070:
071: public Object getUserData(Object key) {
072: if (userData != null) {
073: return userData.get(key);
074: }
075: return null;
076: }
077:
078: public void putUserData(Object key, Object value) {
079: if (userData == null) {
080: userData = new HashMap();
081: }
082: userData.put(key, value);
083: }
084:
085: public List getValues() {
086: return list;
087: }
088:
089: public AttributeType getType() {
090: return type;
091: }
092:
093: public Object getValue(String name) {
094: return values[type.indexOf(name)];
095: }
096:
097: public Object getValue(int index) {
098: return values[index];
099: }
100:
101: public void setValue(String name, Object value) {
102: values[type.indexOf(name)] = value;
103: }
104:
105: public void setValue(int index, Object value) {
106: values[index] = value;
107: }
108:
109: public int getNumberOfAttributes() {
110: return values.length;
111: }
112:
113: public Object getDefaultGeometryValue() {
114: int index = type.indexOf(type.getDefaultGeometry().getName()
115: .getLocalPart());
116: return getValue(index);
117: }
118:
119: /**
120: * List of AttributeDescriptors in the order indicated by SimpleFeatureType.
121: *
122: * This method will mostly be called by generic feature code that has not
123: * been optimized for the helper methods contained in this class.
124: *
125: * AttributeDescriptors here will be wrappers around two core real objects:
126: * <ul>
127: * <li>value[index]
128: * <li>type.get( index )
129: * </ul>
130: */
131: public synchronized Object getValue() {
132: if (attributes == null) {
133: attributes = new ArrayList(values.length);
134: final int LENGTH = values.length;
135: for (int i = 0; i < LENGTH; i++) {
136: if (i == defaultIndex) {
137: list.add(new IndexGeometryAttribute(this , i));
138: } else {
139: list.add(new IndexAttribute(this , i));
140: }
141: }
142: }
143: return attributes;
144: }
145:
146: /**
147: * Always will return null because.
148: * <p>
149: * To be used with a descriptor this SimpleFeature would be being used as an
150: * attirbute in another Feature, not something we are interested in please
151: * just go use a normal implementation, we are optimized and limited.
152: */
153: public AttributeDescriptor getDescriptor() {
154: return null;
155: }
156:
157: /**
158: * We are expecting an List of Attributes with type and values compattible
159: * with our contents.
160: */
161: public void setValue(Object list) throws IllegalArgumentException {
162: List attributes = (List) list;
163: final int LENGTH = values.length;
164: for (int i = 0; i < LENGTH; i++) {
165: Attribute attribute = (Attribute) attributes.get(i);
166: values[i] = attribute.getValue();
167: }
168: }
169:
170: public Collection attributes() {
171: return getAttributes();
172: }
173:
174: public Collection associations() {
175: return Collections.EMPTY_LIST;
176: }
177:
178: public List getValue(Name name) {
179: return Collections.singletonList(getValue(name.getLocalPart()));
180: }
181:
182: public boolean nillable() {
183: return false;
184: }
185:
186: public String getID() {
187: return id; // Feature ID
188: }
189:
190: public PropertyDescriptor descriptor() {
191: return null; // lack descriptor, not suitable use for SimpleFeature
192: }
193:
194: public Name name() {
195: return null; // lack name
196: }
197:
198: public CoordinateReferenceSystem getCRS() {
199: return type.getCRS();
200: }
201:
202: public void setCRS(CoordinateReferenceSystem crs) {
203: if (!type.getCRS().equals(crs)) {
204: throw new IllegalArgumentException(
205: "Provided crs does not match");
206: }
207: }
208:
209: public BoundingBox getBounds() {
210: return getDefaultGeometry().getBounds();
211: }
212:
213: public GeometryAttribute getDefaultGeometry() {
214: return (GeometryAttribute) attributes.get(defaultIndex);
215: }
216:
217: public void setDefaultGeometryValue(GeometryAttribute geom) {
218: values[defaultIndex] = geom.getValue();
219: }
220:
221: public Object operation(String arg0, Object arg1) {
222: throw new UnsupportedOperationException(
223: "operation not supported yet");
224: }
225:
226: public Object operation(Name arg0, List arg1) {
227: throw new UnsupportedOperationException(
228: "operation not supported yet");
229: }
230:
231: public List getAttributes() {
232: return attributes;
233: }
234:
235: public void setDefaultGeometryValue(Object geometry) {
236: }
237:
238: public void setValue(List /*<Property>*/values) {
239: setValues(values);
240: }
241:
242: public void setValues(List /*<Attribute>*/values) {
243: // assume values are in the right order
244: for (int i = 0; i < this .values.length; i++) {
245: this .values[i] = values.get(i);
246: }
247: }
248:
249: public void setValues(Object[] values) {
250: System.arraycopy(values, 0, this .values, 0, this .values.length);
251: }
252:
253: public void setDefaultGeometry(GeometryAttribute geometryAttribute) {
254: setDefaultGeometryValue(geometryAttribute == null ? null
255: : geometryAttribute.getValue());
256: }
257:
258: public List get(Name name) {
259: int index = type.indexOf(name.getLocalPart());
260: Object value = getValue(index);
261: Attribute att;
262: if (index == defaultIndex) {
263: att = new IndexGeometryAttribute(this , index);
264: } else {
265: att = new IndexAttribute(this, index);
266: }
267: return Collections.singletonList(att);
268: }
269:
270: }
|