package org.openntf.domino.graph2;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import org.openntf.domino.graph2.impl.DConfiguration.DTypeManager;
import org.openntf.domino.graph2.impl.DFramedTransactionalGraph;
import org.openntf.domino.types.CaseInsensitiveString;
import org.openntf.domino.utils.TypeUtils;
import com.tinkerpop.blueprints.Edge;
import com.tinkerpop.blueprints.Vertex;
import com.tinkerpop.frames.EdgeFrame;
import com.tinkerpop.frames.FramedGraph;
import com.tinkerpop.frames.VertexFrame;
public enum DGraphUtils {
;
public abstract static class AbstractElementComparator {
protected List<CharSequence> keys_;
protected boolean desc_;
public AbstractElementComparator(final List<CharSequence> keys, final boolean desc) {
keys_ = keys;
desc_ = desc;
}
public AbstractElementComparator(final String key, final boolean desc) {
keys_ = new ArrayList<CharSequence>();
keys_.add(new CaseInsensitiveString(key));
desc_ = desc;
}
public Class<?> toCompatibleClass(final Class<?> class1, final Class<?> class2) {
if (class1.equals(class2))
return class1;
if (class2.isAssignableFrom(class1))
return class2;
if (class1.isAssignableFrom(class2))
return class1;
//TODO exhaustive search of class hierarchy & interfaces
return Object.class;
}
}
public static class VertexComparator extends AbstractElementComparator implements Comparator<Vertex> {
public VertexComparator(final List<CharSequence> keys, final boolean desc) {
super(keys, desc);
}
public VertexComparator(final String key, final boolean desc) {
super(key, desc);
}
@Override
@SuppressWarnings({ "rawtypes", "unchecked" })
public int compare(final Vertex e1, final Vertex e2) {
int result = 0;
ListIterator<CharSequence> li = keys_.listIterator(keys_.size());
while (li.hasPrevious()) {
CharSequence key = li.previous();
try {
Comparable val1 = e1.getProperty(key.toString());
Comparable val2 = e2.getProperty(key.toString());
int curComp = 0;
if (val1 instanceof String) {
curComp = String.CASE_INSENSITIVE_ORDER.compare((String) val1, (String) val2);
} else {
curComp = val1.compareTo(val2);
}
if (curComp != 0) {
if (desc_) {
result = curComp * -1;
} else {
result = curComp;
}
} else {
}
} catch (Throwable t) {
t.printStackTrace();
}
}
if (result == 0) {
// System.out.println("TEMP DEBUG: Found matching values for keys " + CaseInsensitiveString.toString(keys_));
}
return result;
}
}
public abstract static class AbstractFrameComparator {
protected List<CharSequence> keys_;
protected DFramedTransactionalGraph<?> graph_;
protected boolean desc_;
public AbstractFrameComparator(final FramedGraph<?> graph, final List<? extends CharSequence> keys, final boolean desc) {
if (graph instanceof DFramedTransactionalGraph) {
graph_ = (DFramedTransactionalGraph<?>) graph;
}
keys_ = (List<CharSequence>) keys;
desc_ = desc;
}
public AbstractFrameComparator(final FramedGraph<?> graph, final String key, final boolean desc) {
if (graph instanceof DFramedTransactionalGraph) {
graph_ = (DFramedTransactionalGraph<?>) graph;
}
keys_ = new ArrayList<CharSequence>();
keys_.add(new CaseInsensitiveString(key));
desc_ = desc;
}
public Class<?> getCompareType(final Object frame, final CharSequence key) {
return getFramedPropertyType(graph_, frame, key);
}
public Class<?> toCompatibleClass(final Class<?> class1, final Class<?> class2) {
if (class1.equals(class2))
return class1;
if (class2.isAssignableFrom(class1))
return class2;
if (class1.isAssignableFrom(class2))
return class1;
//TODO exhaustive search of class hierarchy & interfaces
return Object.class;
}
}
public static class EdgeFrameComparator extends AbstractFrameComparator implements Comparator<EdgeFrame> {
// public EdgeFrameComparator(final FramedGraph<?> graph, final List<CaseInsensitiveString> keys) {
// super(graph, keys, false);
// }
//
// public EdgeFrameComparator(final FramedGraph<?> graph, final String key) {
// super(graph, key, false);
// }
public EdgeFrameComparator(final FramedGraph<?> graph, final List<? extends CharSequence> keys, final boolean desc) {
super(graph, keys, desc);
}
public EdgeFrameComparator(final FramedGraph<?> graph, final String key, final boolean desc) {
super(graph, key, desc);
}
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
public int compare(final EdgeFrame e1, final EdgeFrame e2) {
int result = 0;
ListIterator<CharSequence> li = keys_.listIterator(keys_.size());
while (li.hasPrevious()) {
CharSequence key = li.previous();
Class<?> type1 = getCompareType(e1, key);
Class<?> type2 = getCompareType(e2, key);
Class<?> compareType = toCompatibleClass(type1, type2);
Object val1 = getFramedProperty(graph_, e1, key);
Object val2 = getFramedProperty(graph_, e2, key);
Comparable castVal1 = (Comparable) TypeUtils.objectToClass(val1, compareType, null);
Comparable castVal2 = (Comparable) TypeUtils.objectToClass(val2, compareType, null);
int curComp = castVal1.compareTo(castVal2);
if (curComp != 0) {
if (desc_) {
result = curComp * -1;
} else {
result = curComp;
}
}
}
return result;
}
}
public static class VertexFrameComparator extends AbstractFrameComparator implements Comparator<VertexFrame> {
// public VertexFrameComparator(final FramedGraph<?> graph, final List<CaseInsensitiveString> keys) {
// super(graph, keys, false);
// }
//
// public VertexFrameComparator(final FramedGraph<?> graph, final String key) {
// super(graph, key, false);
// }
public VertexFrameComparator(final FramedGraph<?> graph, final List<? extends CharSequence> keys, final boolean desc) {
super(graph, keys, desc);
}
public VertexFrameComparator(final FramedGraph<?> graph, final String key, final boolean desc) {
super(graph, key, desc);
}
@Override
@SuppressWarnings({ "rawtypes", "unchecked" })
public int compare(final VertexFrame e1, final VertexFrame e2) {
int result = 0;
ListIterator<CharSequence> li = keys_.listIterator(keys_.size());
while (li.hasPrevious()) {
CharSequence key = li.previous();
// System.out.println("TEMP DEBUG: Checking key " + key.toString());
try {
Class<?> type1 = getCompareType(e1, key);
Class<?> type2 = getCompareType(e2, key);
Class<?> compareType = toCompatibleClass(type1, type2);
Object val1 = getFramedProperty(graph_, e1, key);
Object val2 = getFramedProperty(graph_, e2, key);
Comparable castVal1 = (Comparable) TypeUtils.objectToClass(val1, compareType, null);
Comparable castVal2 = (Comparable) TypeUtils.objectToClass(val2, compareType, null);
int curComp = 0;
if (String.class.equals(compareType)) {
curComp = String.CASE_INSENSITIVE_ORDER.compare((String) val1, (String) val2);
} else {
curComp = castVal1.compareTo(castVal2);
}
if (curComp != 0) {
if (desc_) {
result = curComp * -1;
} else {
result = curComp;
}
} else {
// System.out.println("Got a matching values for key " + key.toString() + ": " + String.valueOf(castVal1) + ", "
// + String.valueOf(castVal2));
}
} catch (Throwable t) {
t.printStackTrace();
}
}
if (result == 0) {
// System.out.println("TEMP DEBUG: Found matching values for keys " + CaseInsensitiveString.toString(keys_));
}
return result;
}
}
public static Object getFramedProperty(final FramedGraph<?> graph, final Object frame, CharSequence key) {
Object result = null;
Map<CaseInsensitiveString, Method> getters = null;
if (frame instanceof EdgeFrame) {
getters = getGetters(graph, (EdgeFrame) frame);
} else {
if (key.toString().startsWith("@counts")) {
String labelStr = key.toString().substring("@counts".length());
key = new CaseInsensitiveString(labelStr);
getters = getCounters(graph, (VertexFrame) frame);
} else {
getters = getGetters(graph, (VertexFrame) frame);
}
}
Method crystal = getters.get(key);
if (crystal != null) {
try {
result = crystal.invoke(frame, (Object[]) null);
} catch (Exception e) {
if (frame instanceof EdgeFrame) {
result = ((EdgeFrame) frame).asEdge().getProperty(key.toString());
} else {
result = ((VertexFrame) frame).asVertex().getProperty(key.toString());
}
}
}
return result;
}
public static Object getFramedProperty(final FramedGraph<?> graph, final Object frame, final String key) {
CaseInsensitiveString lkey = new CaseInsensitiveString(key);
return getFramedProperty(graph, frame, lkey);
}
public static Class<?> getFramedPropertyType(final FramedGraph<?> graph, final Object frame, CharSequence key) {
Class<?> result = Object.class;
Map<CaseInsensitiveString, Method> getters = null;
if (frame instanceof EdgeFrame) {
getters = getGetters(graph, (EdgeFrame) frame);
} else {
getters = getGetters(graph, (VertexFrame) frame);
}
if (!(key instanceof CaseInsensitiveString)) {
key = new CaseInsensitiveString(key);
}
Method crystal = getters.get(key);
if (crystal != null) {
result = crystal.getReturnType();
}
return result;
}
public static boolean isType(final Object frame, final String typename) {
Class<?>[] interfaces = frame.getClass().getInterfaces();
for (Class<?> inter : interfaces) {
if (inter.getName().equals(typename))
return true;
}
return false;
}
public static Class<?> findInterface(final Object frame) {
Class<?>[] interfaces = frame.getClass().getInterfaces();
return interfaces[interfaces.length - 1];
}
public static Map<CaseInsensitiveString, Method> getGetters(final FramedGraph<?> graph, final VertexFrame frame) {
if (graph instanceof DFramedTransactionalGraph) {
DFramedTransactionalGraph<?> dgraph = (DFramedTransactionalGraph<?>) graph;
DTypeManager tman = dgraph.getTypeManager();
Vertex v = frame.asVertex();
Class<?> inter = findInterface(frame);
Class<?> type = tman.resolve(v, inter);
return dgraph.getTypeRegistry().getPropertiesGetters(type);
}
throw new IllegalArgumentException("Cannot discover registered getters for graph type " + graph.getClass().getName());
}
public static Map<CaseInsensitiveString, Method> getCounters(final FramedGraph<?> graph, final VertexFrame frame) {
if (graph instanceof DFramedTransactionalGraph) {
DFramedTransactionalGraph<?> dgraph = (DFramedTransactionalGraph<?>) graph;
DTypeManager tman = dgraph.getTypeManager();
Vertex v = frame.asVertex();
Class<?> inter = findInterface(frame);
Class<?> type = tman.resolve(v, inter);
return dgraph.getTypeRegistry().getCounters(type);
}
throw new IllegalArgumentException("Cannot discover registered getters for graph type " + graph.getClass().getName());
}
public static Map<CaseInsensitiveString, Method> getGetters(final FramedGraph<?> graph, final EdgeFrame frame) {
if (graph instanceof DFramedTransactionalGraph) {
DFramedTransactionalGraph<?> dgraph = (DFramedTransactionalGraph<?>) graph;
DTypeManager tman = dgraph.getTypeManager();
Edge e = frame.asEdge();
Class<?> inter = findInterface(frame);
Class<?> type = tman.resolve(e, inter);
return dgraph.getTypeRegistry().getPropertiesGetters(type);
}
throw new IllegalArgumentException("Cannot discover registered getters for graph type " + graph.getClass().getName());
}
}