package mil.nga.giat.geowave.core.geotime.store.dimension; import java.nio.ByteBuffer; import mil.nga.giat.geowave.core.geotime.index.dimension.TemporalBinningStrategy.Unit; import mil.nga.giat.geowave.core.geotime.index.dimension.TimeDefinition; import mil.nga.giat.geowave.core.index.ByteArrayId; import mil.nga.giat.geowave.core.index.ByteArrayUtils; import mil.nga.giat.geowave.core.index.PersistenceUtils; import mil.nga.giat.geowave.core.index.StringUtils; import mil.nga.giat.geowave.core.index.dimension.NumericDimensionDefinition; import mil.nga.giat.geowave.core.index.dimension.bin.BinRange; import mil.nga.giat.geowave.core.index.sfc.data.NumericData; import mil.nga.giat.geowave.core.index.sfc.data.NumericRange; import mil.nga.giat.geowave.core.store.data.field.FieldReader; import mil.nga.giat.geowave.core.store.data.field.FieldWriter; import mil.nga.giat.geowave.core.store.dimension.NumericDimensionField; /** * This field definition can be used for temporal data (either as a time range * or a single instant in time). * */ public class TimeField implements NumericDimensionField<Time> { // DOUBLE null terminate to be extra sure this is a reserved field ID private final static ByteArrayId DEFAULT_FIELD_ID = new ByteArrayId( ByteArrayUtils.combineArrays( StringUtils.stringToBinary("time"), new byte[] { 0, 0 })); private NumericDimensionDefinition baseDefinition; private final TimeAdapter adapter; private ByteArrayId fieldId; protected TimeField() { adapter = new TimeAdapter(); } public TimeField( final Unit timeUnit ) { this( timeUnit, DEFAULT_FIELD_ID); } public TimeField( final Unit timeUnit, final ByteArrayId fieldId ) { this( new TimeDefinition( timeUnit), fieldId); } @Override public NumericData getFullRange() { return new NumericRange( 0, System.currentTimeMillis() + 1); } public TimeField( final NumericDimensionDefinition baseDefinition, final ByteArrayId fieldId ) { this.baseDefinition = baseDefinition; adapter = new TimeAdapter(); this.fieldId = fieldId; } @Override public double normalize( final double value ) { return baseDefinition.normalize(value); } @Override public double denormalize( final double value ) { return baseDefinition.denormalize(value); } @Override public BinRange[] getNormalizedRanges( final NumericData index ) { return baseDefinition.getNormalizedRanges(index); } @Override public NumericRange getDenormalizedRange( final BinRange range ) { return baseDefinition.getDenormalizedRange(range); } @Override public int getFixedBinIdSize() { return baseDefinition.getFixedBinIdSize(); } @Override public double getRange() { return baseDefinition.getRange(); } @Override public NumericRange getBounds() { return baseDefinition.getBounds(); } @Override public NumericData getNumericData( final Time dataElement ) { return dataElement.toNumericData(); } @Override public ByteArrayId getFieldId() { return fieldId; } @Override public FieldWriter<?, Time> getWriter() { return adapter; } @Override public FieldReader<Time> getReader() { return adapter; } @Override public NumericDimensionDefinition getBaseDefinition() { return baseDefinition; } @Override public byte[] toBinary() { final byte[] dimensionBinary = PersistenceUtils.toBinary(baseDefinition); final ByteBuffer buf = ByteBuffer.allocate(dimensionBinary.length + fieldId.getBytes().length + 4); buf.putInt(fieldId.getBytes().length); buf.put(fieldId.getBytes()); buf.put(dimensionBinary); return buf.array(); } @Override public void fromBinary( final byte[] bytes ) { final ByteBuffer buf = ByteBuffer.wrap(bytes); final int fieldIdLength = buf.getInt(); final byte[] fieldIdBinary = new byte[fieldIdLength]; buf.get(fieldIdBinary); fieldId = new ByteArrayId( fieldIdBinary); final byte[] dimensionBinary = new byte[bytes.length - fieldIdLength - 4]; buf.get(dimensionBinary); baseDefinition = PersistenceUtils.fromBinary( dimensionBinary, NumericDimensionDefinition.class); } @Override public int hashCode() { final int prime = 31; int result = 1; result = (prime * result) + ((baseDefinition == null) ? 0 : baseDefinition.hashCode()); result = (prime * result) + ((fieldId == null) ? 0 : fieldId.hashCode()); return result; } @Override public boolean equals( final Object obj ) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final TimeField other = (TimeField) obj; if (baseDefinition == null) { if (other.baseDefinition != null) { return false; } } else if (!baseDefinition.equals(other.baseDefinition)) { return false; } if (fieldId == null) { if (other.fieldId != null) { return false; } } else if (!fieldId.equals(other.fieldId)) { return false; } return true; } }