package mil.nga.giat.geowave.core.store.data.visibility;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.commons.lang3.ArrayUtils;
import mil.nga.giat.geowave.core.index.ByteArrayId;
import mil.nga.giat.geowave.core.index.Mergeable;
import mil.nga.giat.geowave.core.store.adapter.statistics.AbstractDataStatistics;
import mil.nga.giat.geowave.core.store.adapter.statistics.DataStatistics;
import mil.nga.giat.geowave.core.store.base.DataStoreEntryInfo;
import mil.nga.giat.geowave.core.store.base.DataStoreEntryInfo.FieldInfo;
import mil.nga.giat.geowave.core.store.callback.DeleteCallback;
public class FieldVisibilityCount<T> extends
AbstractDataStatistics<T> implements
DeleteCallback<T>
{
public static final ByteArrayId STATS_TYPE = new ByteArrayId(
"FIELD_VISIBILITY_COUNT");
private final Map<ByteArrayId, Long> countsPerVisibility;
protected FieldVisibilityCount() {
super();
countsPerVisibility = new HashMap<ByteArrayId, Long>();
}
private FieldVisibilityCount(
final ByteArrayId dataAdapterId,
final ByteArrayId statisticsId,
final Map<ByteArrayId, Long> countsPerVisibility ) {
super(
dataAdapterId,
composeId(statisticsId));
this.countsPerVisibility = countsPerVisibility;
}
public FieldVisibilityCount(
final ByteArrayId dataAdapterId,
final ByteArrayId statisticsId ) {
super(
dataAdapterId,
composeId(statisticsId));
countsPerVisibility = new HashMap<ByteArrayId, Long>();
}
public static ByteArrayId composeId(
ByteArrayId statisticsId ) {
return composeId(
STATS_TYPE.getString(),
statisticsId.getString());
}
@Override
public byte[] toBinary() {
int bufferSize = 4;
final List<byte[]> serializedCounts = new ArrayList<byte[]>();
for (final Entry<ByteArrayId, Long> entry : countsPerVisibility.entrySet()) {
final byte[] key = entry.getKey().getBytes();
final ByteBuffer buf = ByteBuffer.allocate(key.length + 12);
buf.putInt(key.length);
buf.put(key);
buf.putLong(entry.getValue());
byte[] serializedEntry = buf.array();
serializedCounts.add(serializedEntry);
bufferSize += serializedEntry.length;
}
ByteBuffer buf = super.binaryBuffer(bufferSize);
buf.putInt(serializedCounts.size());
for (byte[] count : serializedCounts) {
buf.put(count);
}
return buf.array();
}
@Override
public DataStatistics<T> duplicate() {
return new FieldVisibilityCount<T>(
dataAdapterId,
statisticsId,
this.countsPerVisibility);
}
@Override
public void fromBinary(
final byte[] bytes ) {
final ByteBuffer buf = super.binaryBuffer(bytes);
final int size = buf.getInt();
countsPerVisibility.clear();
for (int i = 0; i < size; i++) {
final int idCount = buf.getInt();
final byte[] id = new byte[idCount];
buf.get(id);
final long count = buf.getLong();
countsPerVisibility.put(
new ByteArrayId(
id),
count);
}
}
@Override
public void entryIngested(
final DataStoreEntryInfo entryInfo,
final T entry ) {
updateEntry(
entryInfo,
1);
}
private void updateEntry(
final DataStoreEntryInfo entryInfo,
final int incrementValue ) {
if ((entryInfo != null) && (entryInfo.getFieldInfo() != null)) {
final List<FieldInfo<?>> fields = entryInfo.getFieldInfo();
for (final FieldInfo<?> field : fields) {
ByteArrayId visibility = new ByteArrayId(
new byte[] {});
if (field.getVisibility() != null) {
visibility = new ByteArrayId(
field.getVisibility());
}
Long count = countsPerVisibility.get(visibility);
if (count == null) {
count = 0L;
}
countsPerVisibility.put(
visibility,
count + incrementValue);
}
}
}
@Override
public void entryDeleted(
final DataStoreEntryInfo entryInfo,
final T entry ) {
updateEntry(
entryInfo,
-1);
}
@Override
public void merge(
final Mergeable merge ) {
if ((merge != null) && (merge instanceof FieldVisibilityCount)) {
final Map<ByteArrayId, Long> otherCounts = ((FieldVisibilityCount) merge).countsPerVisibility;
for (final Entry<ByteArrayId, Long> entry : otherCounts.entrySet()) {
Long count = countsPerVisibility.get(entry.getKey());
if (count == null) {
count = 0L;
}
countsPerVisibility.put(
entry.getKey(),
count + entry.getValue());
}
}
}
}