package mil.nga.giat.geowave.adapter.vector.stats;
import mil.nga.giat.geowave.adapter.vector.util.FeatureDataUtils;
import mil.nga.giat.geowave.core.geotime.store.statistics.BoundingBoxDataStatistics;
import mil.nga.giat.geowave.core.index.ByteArrayId;
import mil.nga.giat.geowave.core.store.adapter.statistics.DataStatistics;
import net.sf.json.JSONException;
import net.sf.json.JSONObject;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;
import com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
public class FeatureBoundingBoxStatistics extends
BoundingBoxDataStatistics<SimpleFeature> implements
FeatureStatistic
{
private static final ByteArrayId STATS_TYPE = new ByteArrayId(
"FEATURE_BBOX");
private SimpleFeatureType persistedType;
private SimpleFeatureType reprojectedType;
private MathTransform transform;
protected FeatureBoundingBoxStatistics() {
super();
}
public FeatureBoundingBoxStatistics(
final ByteArrayId dataAdapterId,
final String statisticsId ) {
this(
dataAdapterId,
statisticsId,
null,
null,
null);
}
public FeatureBoundingBoxStatistics(
final ByteArrayId dataAdapterId,
final String statisticsId,
final SimpleFeatureType persistedType,
final SimpleFeatureType reprojectedType,
final MathTransform transform ) {
super(
dataAdapterId,
composeId(
STATS_TYPE.getString(),
statisticsId));
this.persistedType = persistedType;
this.reprojectedType = reprojectedType;
this.transform = transform;
}
public static final ByteArrayId composeId(
final String fieldName ) {
return composeId(
STATS_TYPE.getString(),
fieldName);
}
@Override
public String getFieldName() {
return decomposeNameFromId(getStatisticsId());
}
public Geometry composeGeometry(
final CoordinateReferenceSystem system ) {
final Envelope bounds = new Envelope(
getMinX(),
getMaxX(),
getMinY(),
getMaxY());
return new GeometryFactory().toGeometry(bounds);
}
@Override
protected Envelope getEnvelope(
final SimpleFeature entry ) {
// incorporate the bounding box of the entry's envelope
final Object o;
if ((persistedType != null) && (reprojectedType != null) && (transform != null)) {
o = FeatureDataUtils.defaultCRSTransform(
entry,
persistedType,
reprojectedType,
transform).getAttribute(
getFieldName());
}
else {
o = entry.getAttribute(getFieldName());
}
if ((o != null) && (o instanceof Geometry)) {
final Geometry geometry = (Geometry) o;
if (!geometry.isEmpty()) {
return geometry.getEnvelopeInternal();
}
}
return null;
}
@Override
public DataStatistics<SimpleFeature> duplicate() {
return new FeatureBoundingBoxStatistics(
dataAdapterId,
getFieldName(),
persistedType,
reprojectedType,
transform);
}
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer.append(
"bbox[adapter=").append(
super.getDataAdapterId().getString());
buffer.append(
", field=").append(
getFieldName());
if (isSet()) {
buffer.append(
", minX=").append(
minX);
buffer.append(
", maxX=").append(
maxX);
buffer.append(
", minY=").append(
minY);
buffer.append(
", maxY=").append(
maxY);
}
else {
buffer.append(", No Values");
}
buffer.append("]");
return buffer.toString();
}
/**
* Convert Feature Bounding Box statistics to a JSON object
*/
public JSONObject toJSONObject()
throws JSONException {
JSONObject jo = new JSONObject();
jo.put(
"type",
STATS_TYPE.getString());
jo.put(
"statisticsId",
statisticsId.getString());
jo.put(
"field_identifier",
getFieldName());
if (isSet()) {
jo.put(
"minX",
minX);
jo.put(
"maxX",
maxX);
jo.put(
"minY",
minY);
jo.put(
"maxY",
maxY);
}
else {
jo.put(
"boundaries",
"No Values");
}
return jo;
}
}