package mil.nga.giat.geowave.mapreduce.output; import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Iterator; import org.apache.commons.lang3.ArrayUtils; import org.apache.hadoop.io.WritableComparator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import mil.nga.giat.geowave.core.index.ByteArrayId; import mil.nga.giat.geowave.core.store.adapter.AdapterStore; import mil.nga.giat.geowave.core.store.adapter.DataAdapter; import mil.nga.giat.geowave.core.store.adapter.WritableDataAdapter; import mil.nga.giat.geowave.mapreduce.GeoWaveKey; /** * This class encapsulates the unique identifier for GeoWave to ingest data * using a map-reduce GeoWave output format. The record writer must have bother * the adapter and the index for the data element to ingest. */ public class GeoWaveOutputKey<T> extends GeoWaveKey { private final static Logger LOGGER = LoggerFactory.getLogger(GeoWaveOutputKey.class); /** * */ private static final long serialVersionUID = 1L; private Collection<ByteArrayId> indexIds; transient private WritableDataAdapter<T> adapter; protected GeoWaveOutputKey() { super(); } public GeoWaveOutputKey( final ByteArrayId adapterId, final ByteArrayId indexId ) { super( adapterId); indexIds = Arrays.asList(indexId); } public GeoWaveOutputKey( final ByteArrayId adapterId, final Collection<ByteArrayId> indexIds ) { super( adapterId); this.indexIds = indexIds; } public GeoWaveOutputKey( final WritableDataAdapter<T> adapter, final Collection<ByteArrayId> indexIds ) { super( adapter.getAdapterId()); this.adapter = adapter; this.indexIds = indexIds; adapterId = adapter.getAdapterId(); } public Collection<ByteArrayId> getIndexIds() { return indexIds; } public WritableDataAdapter<T> getAdapter( final AdapterStore adapterCache ) { if (adapter != null) { return adapter; } final DataAdapter<?> adapter = adapterCache.getAdapter(adapterId); if (adapter instanceof WritableDataAdapter) { return (WritableDataAdapter<T>) adapter; } LOGGER.warn("Adapter is not writable"); return null; } @Override public int compareTo( final GeoWaveKey o ) { final int baseCompare = super.compareTo(o); if (baseCompare != 0) { return baseCompare; } if (o instanceof GeoWaveOutputKey) { final GeoWaveOutputKey other = (GeoWaveOutputKey) o; final byte[] thisIndex = getConcatenatedIndexId(); final byte[] otherIndex = other.getConcatenatedIndexId(); return WritableComparator.compareBytes( thisIndex, 0, thisIndex.length, otherIndex, 0, otherIndex.length); } return 1; } private byte[] getConcatenatedIndexId() { final Iterator<ByteArrayId> iterator = indexIds.iterator(); byte[] bytes = iterator.next().getBytes(); if (indexIds.size() > 1) { while (iterator.hasNext()) { bytes = ArrayUtils.addAll( bytes, iterator.next().getBytes()); } } return bytes; } @Override public int hashCode() { final int prime = 31; int result = super.hashCode(); result = (prime * result) + ((indexIds == null) ? 0 : indexIds.hashCode()); return result; } @Override public boolean equals( final Object obj ) { if (this == obj) { return true; } if (!super.equals(obj)) { return false; } if (getClass() != obj.getClass()) { return false; } final GeoWaveOutputKey other = (GeoWaveOutputKey) obj; if (indexIds == null) { if (other.indexIds != null) { return false; } } else if (!indexIds.equals(other.indexIds)) { return false; } return true; } @Override public void readFields( final DataInput input ) throws IOException { super.readFields(input); final byte indexIdCount = input.readByte(); indexIds = new ArrayList<ByteArrayId>(); for (int i = 0; i < indexIdCount; i++) { final int indexIdLength = input.readInt(); final byte[] indexIdBytes = new byte[indexIdLength]; input.readFully(indexIdBytes); indexIds.add(new ByteArrayId( indexIdBytes)); } } @Override public void write( final DataOutput output ) throws IOException { super.write(output); output.writeByte(indexIds.size()); for (final ByteArrayId indexId : indexIds) { output.writeInt(indexId.getBytes().length); output.write(indexId.getBytes()); } } }