package mil.nga.giat.geowave.datastore.accumulo;
import java.io.IOException;
import org.apache.accumulo.core.data.Key;
import org.apache.accumulo.core.data.PartialKey;
import org.apache.accumulo.core.data.Value;
import org.apache.accumulo.core.iterators.SortedKeyValueIterator;
import org.apache.accumulo.core.iterators.user.TransformingIterator;
import org.apache.accumulo.core.security.ColumnVisibility;
import org.apache.commons.lang.ArrayUtils;
import org.apache.hadoop.io.Text;
import mil.nga.giat.geowave.core.index.Mergeable;
import mil.nga.giat.geowave.core.index.PersistenceUtils;
import mil.nga.giat.geowave.core.index.StringUtils;
public class MergingVisibilityCombiner extends
TransformingIterator
{
private static final byte[] AMPRISAND = StringUtils.stringToBinary("&");
@Override
protected PartialKey getKeyPrefix() {
return PartialKey.ROW_COLFAM_COLQUAL;
}
@Override
protected void transformRange(
final SortedKeyValueIterator<Key, Value> input,
final KVBuffer output )
throws IOException {
Mergeable currentMergeable = null;
Key outputKey = null;
while (input.hasTop()) {
final Value val = input.getTopValue();
// the SortedKeyValueIterator uses the same instance of topKey to
// hold keys (a wrapper)
final Key currentKey = new Key(
input.getTopKey());
if (outputKey == null) {
outputKey = currentKey;
}
else if ((currentMergeable != null) && !outputKey.getRowData().equals(
currentKey.getRowData())) {
output.append(
outputKey,
new Value(
PersistenceUtils.toBinary(currentMergeable)));
currentMergeable = null;
outputKey = currentKey;
continue;
}
else {
final Text combinedVisibility = new Text(
combineVisibilities(
currentKey.getColumnVisibility().getBytes(),
outputKey.getColumnVisibility().getBytes()));
outputKey = replaceColumnVisibility(
outputKey,
combinedVisibility);
}
final Mergeable mergeable = getMergeable(
currentKey,
val.get());
// hopefully its never the case that null mergeables are stored,
// but just in case, check
if (mergeable != null) {
if (currentMergeable == null) {
currentMergeable = mergeable;
}
else {
currentMergeable.merge(mergeable);
}
}
input.next();
}
if (currentMergeable != null) {
output.append(
outputKey,
new Value(
getBinary(currentMergeable)));
}
}
protected Mergeable getMergeable(
final Key key,
final byte[] binary ) {
return PersistenceUtils.fromBinary(
binary,
Mergeable.class);
}
protected byte[] getBinary(
final Mergeable mergeable ) {
return PersistenceUtils.toBinary(mergeable);
}
private static byte[] combineVisibilities(
final byte[] vis1,
final byte[] vis2 ) {
if ((vis1 == null) || (vis1.length == 0)) {
return vis2;
}
if ((vis2 == null) || (vis2.length == 0)) {
return vis1;
}
return new ColumnVisibility(
ArrayUtils.addAll(
ArrayUtils.addAll(
ColumnVisibility.quote(vis1),
AMPRISAND),
ColumnVisibility.quote(vis2))).flatten();
}
}