package com.vividsolutions.jump.feature;
import java.util.*;
import com.vividsolutions.jts.geom.Geometry;
/**
* Subclasses need to implement only the four remaining Feature methods:
* #getAttribute, #setAttribute, #getAttributes, #setAttributes
*/
public abstract class AbstractBasicFeature implements Feature {
private FeatureSchema schema;
private int id;
/**
* A low-level accessor that is not normally used.
*/
public void setSchema(FeatureSchema schema) {
this.schema = schema;
}
/**
* Creates a new Feature based on the given metadata.
*
*@param featureSchema the metadata containing information on
* each column
*/
public AbstractBasicFeature(FeatureSchema featureSchema) {
id = FeatureUtil.nextID();
this.schema = featureSchema;
}
/**
* Returns a number that uniquely identifies this feature. This number is not
* persistent.
* @return n, where this feature is the nth Feature created by this application
*/
public int getID() {
return id;
}
/**
* Sets the specified attribute.
*
*@param attributeName the name of the attribute to set
*@param newAttribute the new attribute
*/
public void setAttribute(String attributeName, Object newAttribute) {
setAttribute(schema.getAttributeIndex(attributeName),
newAttribute);
}
/**
* Convenience method for setting the spatial attribute. JUMP Workbench
* PlugIns and CursorTools should not use this method directly, but should use an
* EditTransaction, so that the proper events are fired.
*
*@param geometry the new spatial attribute
*/
public void setGeometry(Geometry geometry) {
setAttribute(schema.getGeometryIndex(), geometry);
}
/**
* Returns the specified attribute.
*
*@param name the name of the attribute to get
*@return the attribute
*/
public Object getAttribute(String name) {
return getAttribute(schema.getAttributeIndex(name));
}
//<<TODO:DOC>>Update JavaDoc -- the attribute need not be a String [Jon Aquino]
/**
* Returns a String attribute. The attribute at the given index must be a
* String.
*
*@param attributeIndex the array index of the attribute
*@return the String attribute at the given index
*/
public String getString(int attributeIndex) {
// return (String) attributes[attributeIndex];
//Dave B changed this so you can convert Integers->Strings
//Automatic conversion of integers to strings is a bit hack-like.
//Instead one should do #getAttribute followed by #toString.
//#getString should be strict: it should throw an Exception if it is used
//on a non-String attribute. [Jon Aquino]
Object result = getAttribute(attributeIndex);
//We used to eat ArrayOutOfBoundsExceptions here. I've removed this behaviour
//because ArrayOutOfBoundsExceptions are bugs and should be exposed. [Jon Aquino]
//Is it valid for an attribute to be null? If not, we should put an
//Assert here [Jon Aquino]
if (result != null) {
return result.toString();
} else {
return "";
}
}
/**
* Returns a integer attribute.
*
*@param attributeIndex the index of the attribute to retrieve
*@return the integer attribute with the given name
*/
public int getInteger(int attributeIndex) {
return ((Integer) getAttribute(attributeIndex)).intValue();
}
/**
* Returns a double attribute.
*
*@param attributeIndex the index of the attribute to retrieve
*@return the double attribute with the given name
*/
public double getDouble(int attributeIndex) {
return ((Double) getAttribute(attributeIndex)).doubleValue();
}
//<<TODO:DOC>>Update JavaDoc -- the attribute need not be a String [Jon Aquino]
/**
* Returns a String attribute. The attribute with the given name must be a
* String.
*
*@param attributeName the name of the attribute to retrieve
*@return the String attribute with the given name
*/
public String getString(String attributeName) {
return getString(schema.getAttributeIndex(attributeName));
}
/**
* Convenience method for returning the spatial attribute.
*
*@return the feature's spatial attribute
*/
public Geometry getGeometry() {
return (Geometry) getAttribute(schema.getGeometryIndex());
}
/**
* Returns the feature's metadata
*
*@return the metadata describing the names and types of the attributes
*/
public FeatureSchema getSchema() {
return schema;
}
/**
* Clones this Feature. The geometry will also be cloned.
* @return a new Feature with the same attributes as this Feature
*/
public Object clone() {
return clone(true);
}
/**
* Clones this Feature.
* @param deep whether or not to clone the geometry
* @return a new Feature with the same attributes as this Feature
*/
public Feature clone(boolean deep) {
Feature clone = new BasicFeature(schema);
for (int i = 0; i < schema.getAttributeCount(); i++) {
if (schema.getAttributeType(i) == AttributeType.GEOMETRY) {
clone.setAttribute(i,
deep ? getGeometry().clone() : getGeometry());
} else {
clone.setAttribute(i, getAttribute(i));
}
}
return clone;
}
public int compareTo(Object o) {
return getGeometry().compareTo(((Feature) o).getGeometry());
}
}