package mil.nga.giat.geowave.core.geotime.store.statistics; import java.nio.ByteBuffer; import java.util.HashMap; import java.util.Map; import net.sf.json.JSONException; import net.sf.json.JSONObject; import com.vividsolutions.jts.geom.Envelope; import mil.nga.giat.geowave.core.geotime.index.dimension.LatitudeDefinition; import mil.nga.giat.geowave.core.geotime.index.dimension.LongitudeDefinition; import mil.nga.giat.geowave.core.index.ByteArrayId; import mil.nga.giat.geowave.core.index.Mergeable; import mil.nga.giat.geowave.core.index.dimension.NumericDimensionDefinition; import mil.nga.giat.geowave.core.index.sfc.data.NumericRange; import mil.nga.giat.geowave.core.store.adapter.statistics.AbstractDataStatistics; import mil.nga.giat.geowave.core.store.base.DataStoreEntryInfo; import mil.nga.giat.geowave.core.store.query.BasicQuery.ConstraintData; import mil.nga.giat.geowave.core.store.query.BasicQuery.ConstraintSet; abstract public class BoundingBoxDataStatistics<T> extends AbstractDataStatistics<T> { public final static ByteArrayId STATS_TYPE = new ByteArrayId( "BOUNDING_BOX"); protected double minX = Double.MAX_VALUE; protected double minY = Double.MAX_VALUE; protected double maxX = -Double.MAX_VALUE; protected double maxY = -Double.MAX_VALUE; protected BoundingBoxDataStatistics() { super(); } public BoundingBoxDataStatistics( final ByteArrayId dataAdapterId ) { super( dataAdapterId, STATS_TYPE); } public BoundingBoxDataStatistics( final ByteArrayId dataAdapterId, final ByteArrayId staticticsId ) { super( dataAdapterId, staticticsId); } public boolean isSet() { if ((minX == Double.MAX_VALUE) || (minY == Double.MAX_VALUE) || (maxX == -Double.MAX_VALUE) || (maxY == -Double.MAX_VALUE)) { return false; } return true; } public double getMinX() { return minX; } public double getMinY() { return minY; } public double getMaxX() { return maxX; } public double getMaxY() { return maxY; } public double getWidth() { return maxX - minX; } public double getHeight() { return maxY - minY; } @Override public byte[] toBinary() { final ByteBuffer buffer = super.binaryBuffer(32); buffer.putDouble(minX); buffer.putDouble(minY); buffer.putDouble(maxX); buffer.putDouble(maxY); return buffer.array(); } @Override public void fromBinary( final byte[] bytes ) { final ByteBuffer buffer = super.binaryBuffer(bytes); minX = buffer.getDouble(); minY = buffer.getDouble(); maxX = buffer.getDouble(); maxY = buffer.getDouble(); } @Override public void entryIngested( final DataStoreEntryInfo entryInfo, final T entry ) { final Envelope env = getEnvelope(entry); if (env != null) { minX = Math.min( minX, env.getMinX()); minY = Math.min( minY, env.getMinY()); maxX = Math.max( maxX, env.getMaxX()); maxY = Math.max( maxY, env.getMaxY()); } } public ConstraintSet getConstraints() { // Create a NumericRange object using the x axis final NumericRange rangeLongitude = new NumericRange( minX, maxX); // Create a NumericRange object using the y axis final NumericRange rangeLatitude = new NumericRange( minY, maxY); final Map<Class<? extends NumericDimensionDefinition>, ConstraintData> constraintsPerDimension = new HashMap<Class<? extends NumericDimensionDefinition>, ConstraintData>(); // Create and return a new IndexRange array with an x and y axis // range constraintsPerDimension.put( LongitudeDefinition.class, new ConstraintData( rangeLongitude, true)); constraintsPerDimension.put( LatitudeDefinition.class, new ConstraintData( rangeLatitude, true)); return new ConstraintSet( constraintsPerDimension); } abstract protected Envelope getEnvelope( final T entry ); @Override public void merge( final Mergeable statistics ) { if ((statistics != null) && (statistics instanceof BoundingBoxDataStatistics)) { final BoundingBoxDataStatistics<T> bboxStats = (BoundingBoxDataStatistics<T>) statistics; if (bboxStats.isSet()) { minX = Math.min( minX, bboxStats.minX); minY = Math.min( minY, bboxStats.minY); maxX = Math.max( maxX, bboxStats.maxX); maxY = Math.max( maxY, bboxStats.maxY); } } } public String toString() { StringBuffer buffer = new StringBuffer(); buffer.append( "bbox[adapter=").append( super.getDataAdapterId().getString()); 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 Fixed Bin Numeric 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()); 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; } }