package mil.nga.giat.geowave.core.store.index; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import mil.nga.giat.geowave.core.index.ByteArrayId; import mil.nga.giat.geowave.core.index.PersistenceUtils; import mil.nga.giat.geowave.core.index.StringUtils; 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 class is a concrete implementation of a common index model. Data * adapters will map their adapter specific fields to these fields that are * common for a given index. This way distributable filters will not need to * handle any adapter-specific transformation, but can use the common index * fields. * */ public class BasicIndexModel implements CommonIndexModel { private NumericDimensionField<?>[] dimensions; // the first dimension of a particular field ID will be the persistence // model used private Map<ByteArrayId, NumericDimensionField<?>> fieldIdToPeristenceMap; private transient String id; protected BasicIndexModel() {} public BasicIndexModel( final NumericDimensionField<?>[] dimensions ) { init(dimensions); } private void init( final NumericDimensionField<?>[] dimensions ) { this.dimensions = dimensions; fieldIdToPeristenceMap = new HashMap<ByteArrayId, NumericDimensionField<?>>(); for (final NumericDimensionField<?> d : dimensions) { if (!fieldIdToPeristenceMap.containsKey(d.getFieldId())) { fieldIdToPeristenceMap.put( d.getFieldId(), d); } } } @SuppressWarnings("unchecked") @Override public FieldWriter<Object, CommonIndexValue> getWriter( final ByteArrayId fieldId ) { final NumericDimensionField<?> dimension = fieldIdToPeristenceMap.get(fieldId); if (dimension != null) { return (FieldWriter<Object, CommonIndexValue>) dimension.getWriter(); } return null; } @SuppressWarnings("unchecked") @Override public FieldReader<CommonIndexValue> getReader( final ByteArrayId fieldId ) { final NumericDimensionField<?> dimension = fieldIdToPeristenceMap.get(fieldId); if (dimension != null) { return (FieldReader<CommonIndexValue>) dimension.getReader(); } return null; } @Override public NumericDimensionField<?>[] getDimensions() { return dimensions; } @Override public int hashCode() { final int prime = 31; int result = 1; final String className = getClass().getName(); result = (prime * result) + ((className == null) ? 0 : className.hashCode()); result = (prime * result) + Arrays.hashCode(dimensions); 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 BasicIndexModel other = (BasicIndexModel) obj; return Arrays.equals( dimensions, other.dimensions); } @Override public byte[] toBinary() { int byteBufferLength = 4; final List<byte[]> dimensionBinaries = new ArrayList<byte[]>( dimensions.length); for (final NumericDimensionField<?> dimension : dimensions) { final byte[] dimensionBinary = PersistenceUtils.toBinary(dimension); byteBufferLength += (4 + dimensionBinary.length); dimensionBinaries.add(dimensionBinary); } final ByteBuffer buf = ByteBuffer.allocate(byteBufferLength); buf.putInt(dimensions.length); for (final byte[] dimensionBinary : dimensionBinaries) { buf.putInt(dimensionBinary.length); buf.put(dimensionBinary); } return buf.array(); } @Override public void fromBinary( final byte[] bytes ) { final ByteBuffer buf = ByteBuffer.wrap(bytes); final int numDimensions = buf.getInt(); dimensions = new NumericDimensionField[numDimensions]; for (int i = 0; i < numDimensions; i++) { final byte[] dim = new byte[buf.getInt()]; buf.get(dim); dimensions[i] = PersistenceUtils.fromBinary( dim, NumericDimensionField.class); } init(dimensions); } @Override public String getId() { if (id == null) { id = StringUtils.intToString(hashCode()); } return id; } }