package mil.nga.giat.geowave.datastore.accumulo.util; import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import org.apache.accumulo.core.data.Key; import org.apache.accumulo.core.data.Value; import org.apache.accumulo.core.iterators.user.WholeRowIterator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import mil.nga.giat.geowave.core.index.ByteArrayId; import mil.nga.giat.geowave.core.store.adapter.DataAdapter; import mil.nga.giat.geowave.core.store.adapter.IndexedAdapterPersistenceEncoding; import mil.nga.giat.geowave.core.store.data.PersistentDataset; import mil.nga.giat.geowave.core.store.data.PersistentValue; import mil.nga.giat.geowave.core.store.data.field.FieldReader; import mil.nga.giat.geowave.core.store.index.CommonIndexValue; import mil.nga.giat.geowave.core.store.index.PrimaryIndex; import mil.nga.giat.geowave.core.store.index.SecondaryIndexUtils; public class AccumuloSecondaryIndexUtils { private final static Logger LOGGER = LoggerFactory.getLogger(AccumuloSecondaryIndexUtils.class); /** * Decodes an Accumulo key-value pair from the result of a secondary index * scan back into the original type using the given data adapter * * @param key * @param value * @param adapter * @param indexModel * @return */ public static <T> T decodeRow( final Key key, final Value value, final DataAdapter<T> adapter, final PrimaryIndex index ) { Map<Key, Value> rowMapping; try { rowMapping = WholeRowIterator.decodeRow( key, value); } catch (final IOException e) { LOGGER.error("Could not decode row from iterator. Ensure whole row iterators are being used."); return null; } final PersistentDataset<CommonIndexValue> commonData = new PersistentDataset<CommonIndexValue>(); final PersistentDataset<Object> extendedData = new PersistentDataset<Object>(); final PersistentDataset<byte[]> unknownData = new PersistentDataset<byte[]>(); ByteArrayId dataId = null; Map<ByteArrayId, byte[]> fieldIdToValueMap = new HashMap<>(); for (final Entry<Key, Value> entry : rowMapping.entrySet()) { final byte[] cqBytes = entry.getKey().getColumnQualifierData().getBackingArray(); final String dataIdString = SecondaryIndexUtils.getDataId(cqBytes); if (dataId == null) { dataId = new ByteArrayId( dataIdString); } final ByteArrayId fieldId = SecondaryIndexUtils.getFieldId(cqBytes); final byte[] fieldValue = entry.getValue().get(); fieldIdToValueMap.put( fieldId, fieldValue); } for (final Entry<ByteArrayId, byte[]> entry : fieldIdToValueMap.entrySet()) { final ByteArrayId fieldId = entry.getKey(); final byte[] fieldValueBytes = entry.getValue(); final FieldReader<? extends CommonIndexValue> indexFieldReader = index.getIndexModel().getReader( fieldId); if (indexFieldReader != null) { final CommonIndexValue indexValue = indexFieldReader.readField(fieldValueBytes); final PersistentValue<CommonIndexValue> val = new PersistentValue<CommonIndexValue>( fieldId, indexValue); commonData.addValue(val); } else { final FieldReader<?> fieldReader = adapter.getReader(fieldId); if (fieldReader != null) { final Object fieldValue = fieldReader.readField(fieldValueBytes); final PersistentValue<Object> val = new PersistentValue<Object>( fieldId, fieldValue); extendedData.addValue(val); } else { unknownData.addValue(new PersistentValue<byte[]>( fieldId, fieldValueBytes)); } } } final IndexedAdapterPersistenceEncoding encodedData = new IndexedAdapterPersistenceEncoding( adapter.getAdapterId(), dataId, null, 0, commonData, unknownData, extendedData); return adapter.decode( encodedData, index); } }