package net.notdot.bdbdatastore.server;
import java.util.Comparator;
import java.util.List;
import net.notdot.bdbdatastore.Indexing;
import com.google.appengine.entity.Entity;
import com.google.appengine.entity.Entity.Path;
import com.google.appengine.entity.Entity.PropertyValue;
import com.google.appengine.entity.Entity.Reference;
import com.google.protobuf.ByteString;
public class EntityKeyComparator implements Comparator<Indexing.EntityKey> {
public final static EntityKeyComparator instance = new EntityKeyComparator();
public static Indexing.EntityKey toEntityKey(Entity.PropertyValue.ReferenceValue refval) {
Entity.Path.Builder path = Entity.Path.newBuilder();
List<Entity.PropertyValue.ReferenceValue.PathElement> elements = refval.getPathElementList();
for(Entity.PropertyValue.ReferenceValue.PathElement pathel : elements) {
Entity.Path.Element.Builder element = Entity.Path.Element.newBuilder();
element.setType(pathel.getType());
if(pathel.hasName())
element.setName(pathel.getName());
if(pathel.hasId())
element.setId(pathel.getId());
path.addElement(element);
}
ByteString kind = elements.get(elements.size() - 1).getType();
return Indexing.EntityKey.newBuilder().setKind(kind).setPath(path).build();
}
public static PropertyValue toPropertyValue(Reference key) {
Entity.PropertyValue.ReferenceValue.Builder builder = Entity.PropertyValue.ReferenceValue.newBuilder();
builder.setApp(key.getApp());
for(Entity.Path.Element pathEl : key.getPath().getElementList()) {
Entity.PropertyValue.ReferenceValue.PathElement.Builder elt = Entity.PropertyValue.ReferenceValue.PathElement.newBuilder();
elt.setType(pathEl.getType());
if(pathEl.hasName())
elt.setName(pathEl.getName());
if(pathEl.hasId())
elt.setId(elt.getId());
builder.addPathElement(elt);
}
return Entity.PropertyValue.newBuilder().setReferenceValue(builder).build();
}
private static int compareElements(Entity.Path.Element e1, Entity.Path.Element e2) {
int ret = e1.getType().asReadOnlyByteBuffer().compareTo(e2.getType().asReadOnlyByteBuffer());
if(ret != 0)
return ret;
//IDs are considered less than names
if(e1.hasId()) {
if(e2.hasName())
return -1;
long e1id = e1.getId();
long e2id = e2.getId();
if(e1id < e2id)
return -1;
if(e1id > e2id)
return 1;
return 0;
} else {
if(e2.hasId())
return 1;
return e1.getName().asReadOnlyByteBuffer().compareTo(e2.getName().asReadOnlyByteBuffer());
}
}
public int compare(Indexing.EntityKey o1, Indexing.EntityKey o2) {
Entity.Path p1 = o1.getPath();
Entity.Path p2 = o2.getPath();
// Compare kinds
int ret = o1.getKind().asReadOnlyByteBuffer().compareTo(o2.getKind().asReadOnlyByteBuffer());
if(ret != 0)
return ret;
// Compare paths
return comparePaths(p1, p2);
}
public static int comparePaths(Path p1, Path p2) {
int p1len = p1.getElementCount();
int p2len = p2.getElementCount();
int ret = 0;
for(int i = 0; i < Math.min(p1len, p2len); i++) {
ret = compareElements(p1.getElement(i), p2.getElement(i));
if(ret != 0)
return ret;
}
return p1len - p2len;
}
}