package mil.nga.giat.geowave.analytic.partitioner;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import mil.nga.giat.geowave.analytic.PropertyManagement;
import mil.nga.giat.geowave.analytic.param.ParameterEnum;
import mil.nga.giat.geowave.core.index.ByteArrayId;
import org.apache.commons.codec.binary.Hex;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.io.Writable;
import org.apache.hadoop.mapreduce.JobContext;
/**
* Provide a partition for a data item.
*
*
* Multiple partitions are permitted. Only one partition is consider primary. A
* primary partition is the partition for an item in which the item is processed
* on behalf of itself. All other partitions are those partitions that require
* visibility to the a specific item for other items to reference. This approach
* supports nearest neighbor type queries. Consider that an item can only
* discover neighbors in its partition. However, the item can be discovered as a
* nearest neighbor in those partitions in which the item participates as a none
* primary.
*
* @param <T>
*/
public interface Partitioner<T> extends
Serializable
{
public void initialize(
final JobContext context,
final Class<?> scope )
throws IOException;
public List<PartitionData> getCubeIdentifiers(
final T entry );
public void partition(
T entry,
PartitionDataCallback callback )
throws Exception;
public Collection<ParameterEnum<?>> getParameters();
public void setup(
PropertyManagement runTimeProperties,
Class<?> scope,
Configuration configuration );
public static interface PartitionDataCallback
{
void partitionWith(
PartitionData data )
throws Exception;
}
/**
* Represents a partition associated with a specific item. The partition is
* marked as primary or secondary. A secondary partition is a neighboring
* partition to an item. The intent is inspect neighbor partitions to handle
* edge cases.
*
*/
public static class PartitionData implements
Serializable,
Writable
{
/**
*
*/
private static final long serialVersionUID = 1L;
private ByteArrayId id;
private ByteArrayId groupId = null;
private boolean isPrimary;
public ByteArrayId getId() {
return id;
}
public ByteArrayId getGroupId() {
return groupId;
}
public void setGroupId(
final ByteArrayId groupId ) {
this.groupId = groupId;
}
public boolean isPrimary() {
return isPrimary;
}
public PartitionData() {}
public PartitionData(
final ByteArrayId id,
final boolean primary ) {
super();
this.id = id;
this.isPrimary = primary;
}
@Override
public String toString() {
return "PartitionData [id=" + Hex.encodeHexString(id.getBytes()) + ", groupId="
+ (groupId == null ? "null" : groupId.getString()) + ", isPrimary=" + isPrimary + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = (prime * result) + ((id == null) ? 0 : id.hashCode());
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 PartitionData other = (PartitionData) obj;
if (id == null) {
if (other.id != null) {
return false;
}
}
else if (!id.equals(other.id)) {
return false;
}
return true;
}
@Override
public void readFields(
final DataInput dInput )
throws IOException {
final int idSize = dInput.readInt();
final byte[] idBytes = new byte[idSize];
dInput.readFully(idBytes);
id = new ByteArrayId(
idBytes);
final int groupIdSize = dInput.readInt();
if (groupIdSize > 0) {
final byte[] groupIdIdBytes = new byte[groupIdSize];
dInput.readFully(groupIdIdBytes);
groupId = new ByteArrayId(
groupIdIdBytes);
}
isPrimary = dInput.readBoolean();
}
@Override
public void write(
final DataOutput dOutput )
throws IOException {
final byte[] outputId = id.getBytes();
dOutput.writeInt(outputId.length);
dOutput.write(outputId);
if (groupId != null) {
final byte[] groupOutputId = groupId.getBytes();
dOutput.writeInt(groupOutputId.length);
dOutput.write(groupOutputId);
}
else {
dOutput.writeInt(0);
}
dOutput.writeBoolean(isPrimary);
}
public void setPrimary(
boolean isPrimary ) {
this.isPrimary = isPrimary;
}
}
}