package org.openntf.domino.graph2.impl;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.openntf.domino.big.impl.NoteCoordinate;
import org.openntf.domino.graph2.DKeyResolver;
import org.openntf.domino.graph2.annotations.FramedEdgeList;
import org.openntf.domino.graph2.annotations.FramedVertexList;
import org.openntf.domino.graph2.builtin.DEdgeFrame;
import org.openntf.domino.graph2.builtin.ViewVertex;
import org.openntf.domino.graph2.impl.DConfiguration.DTypeManager;
import org.openntf.domino.graph2.impl.DConfiguration.DTypeRegistry;
import org.openntf.domino.types.CaseInsensitiveString;
import org.openntf.domino.utils.DominoUtils;
import com.tinkerpop.blueprints.Direction;
import com.tinkerpop.blueprints.Edge;
import com.tinkerpop.blueprints.Element;
import com.tinkerpop.blueprints.Graph;
import com.tinkerpop.blueprints.TransactionalGraph;
import com.tinkerpop.blueprints.Vertex;
import com.tinkerpop.frames.EdgeFrame;
import com.tinkerpop.frames.FrameInitializer;
import com.tinkerpop.frames.FramedGraphConfiguration;
import com.tinkerpop.frames.FramedTransactionalGraph;
import com.tinkerpop.frames.VertexFrame;
import com.tinkerpop.frames.modules.javahandler.JavaFrameInitializer;
public class DFramedTransactionalGraph<T extends TransactionalGraph> extends FramedTransactionalGraph<T> {
public class FramedElementIterable<T> implements Iterable<T> {
protected final Class<T> kind;
protected final Iterable<Element> iterable;
protected final DFramedTransactionalGraph<? extends Graph> framedGraph;
public FramedElementIterable(final DFramedTransactionalGraph<? extends Graph> framedGraph, final Iterable<Element> iterable,
final Class<T> kind) {
this.framedGraph = framedGraph;
this.iterable = iterable;
this.kind = kind;
}
@Override
public Iterator<T> iterator() {
return new Iterator<T>() {
private Iterator<Element> iterator = iterable.iterator();
@Override
public void remove() {
throw new UnsupportedOperationException();
}
@Override
public boolean hasNext() {
return this.iterator.hasNext();
}
@Override
public T next() {
return framedGraph.frame(this.iterator.next(), kind);
}
};
}
}
public DFramedTransactionalGraph(final T baseGraph, final FramedGraphConfiguration config) {
super(baseGraph, config);
}
public DTypeRegistry getTypeRegistry() {
Graph graph = this.getBaseGraph();
if (graph instanceof DGraph) {
DConfiguration config = (DConfiguration) ((DGraph) graph).getConfiguration();
return config.getTypeRegistry();
}
return null;
}
public DTypeManager getTypeManager() {
Graph graph = this.getBaseGraph();
if (graph instanceof DGraph) {
DConfiguration config = (DConfiguration) ((DGraph) graph).getConfiguration();
return config.getTypeManager();
}
return null;
}
private String getTypedId(final Object id) {
String result = null;
if (id != null && id instanceof String) {
String idStr = (String) id;
if (idStr.length() == 16) {
if (DominoUtils.isReplicaId(idStr)) {
result = idStr;
}
} else if (idStr.length() > 16) {
if (idStr.length() == 32) {
if (DominoUtils.isUnid(idStr)) {
result = null;
}
} else {
String prefix = idStr.substring(0, 16);
if (DominoUtils.isReplicaId(prefix)) {
result = prefix;
}
}
}
}
return result;
}
@Override
public <F> F addVertex(final Object id, final Class<F> kind) {
DGraph base = (DGraph) this.getBaseGraph();
org.openntf.domino.graph2.DElementStore store = null;
if (kind != null) {
store = base.findElementStore(kind);
}
if (store == null) {
if (id instanceof NoteCoordinate) {
store = base.findElementStore(id);
} else {
String typeid = getTypedId(id);
if (typeid == null) {
store = base.getDefaultElementStore();
} else {
store = base.findElementStore(typeid);
}
}
}
Vertex vertex = store.addVertex(id);
return frame(vertex, kind);
}
public <F> F getVertex(final Class<F> kind, final Object context, final Object... args) {
DGraph base = (DGraph) this.getBaseGraph();
org.openntf.domino.graph2.DElementStore store = base.findElementStore(kind);
Object id = store.getIdentity(kind, context, args);
return getVertex(id, kind);
}
public <F> Iterable<F> getElements(final Class<F> kind) {
org.openntf.domino.graph2.DElementStore store = null;
DGraph base = (DGraph) this.getBaseGraph();
store = base.findElementStore(kind);
if (store != null) {
String formulaFilter = org.openntf.domino.graph2.DGraph.Utils.getFramedElementFormula(kind);
Iterable<Element> elements = (org.openntf.domino.graph2.impl.DElementIterable) store.getElements(formulaFilter);
// if (elements instanceof List) {
// int size = ((List) elements).size();
// System.out.println("TEMP DEBUG Found a list of size " + size + " for kind " + kind.getName());
// }
return this.frameElements(elements, kind);
} else {
// System.out.println("TEMP DEBUG Unable to find an element store for type " + kind.getName());
return null;
}
}
protected Class<?> getClassFromName(final String classname) {
Class<?> chkClass = getTypeRegistry().getType(VertexFrame.class, classname);
if (chkClass == null) {
chkClass = getTypeRegistry().getType(EdgeFrame.class, classname);
}
if (chkClass == null) {
chkClass = getTypeRegistry().findClassByName(classname);
}
if (chkClass == null) {
// System.out.println("TEMP DEBUG Unable to find an element store for type " + classname);
}
return chkClass;
}
public <F> Iterable<F> getElements(final String classname) {
org.openntf.domino.graph2.DElementStore store = null;
DGraph base = (DGraph) this.getBaseGraph();
Class<?> chkClass = getClassFromName(classname);
if (chkClass != null) {
store = base.findElementStore(chkClass);
if (store != null) {
String formulaFilter = org.openntf.domino.graph2.DGraph.Utils.getFramedElementFormula(chkClass);
Iterable<Element> elements = (org.openntf.domino.graph2.impl.DElementIterable) store.getElements(formulaFilter);
// if (elements instanceof List) {
// int size = ((List) elements).size();
// System.out.println("TEMP DEBUG Found a list of size " + size + " for kind " + classname);
// }
return this.frameElements(elements, null);
} else {
// System.out.println("TEMP DEBUG Unable to find an element store for type " + classname);
return null;
}
} else {
throw new IllegalArgumentException("Class " + classname + " not registered in graph");
}
}
public <F> Iterable<F> getFilteredElements(final String classname, final List<CharSequence> keys,
final List<CaseInsensitiveString> values) {
// System.out.println("Getting a filtered list of elements of type " + classname);
org.openntf.domino.graph2.DElementStore store = null;
DGraph base = (DGraph) this.getBaseGraph();
Class<?> chkClass = getClassFromName(classname);
if (chkClass != null) {
store = base.findElementStore(chkClass);
if (store != null) {
List<String> keystrs = CaseInsensitiveString.toStrings(keys);
List<Object> valobj = new ArrayList<Object>(values);
String formulaFilter = org.openntf.domino.graph2.DGraph.Utils.getFramedElementFormula(keystrs, valobj, chkClass);
Iterable<Element> elements = (org.openntf.domino.graph2.impl.DElementIterable) store.getElements(formulaFilter);
return this.frameElements(elements, null);
} else {
return null;
}
} else {
throw new IllegalArgumentException("Class " + classname + " not registered in graph");
}
}
public <F> Iterable<F> getFilteredElementsPartial(final String classname, final List<CharSequence> keys,
final List<CaseInsensitiveString> values) {
// System.out.println("Getting a filtered list of elements of type " + classname);
org.openntf.domino.graph2.DElementStore store = null;
DGraph base = (DGraph) this.getBaseGraph();
Class<?> chkClass = getClassFromName(classname);
if (chkClass != null) {
store = base.findElementStore(chkClass);
if (store != null) {
List<String> keystrs = CaseInsensitiveString.toStrings(keys);
List<Object> valobj = new ArrayList<Object>(values);
String formulaFilter = org.openntf.domino.graph2.DGraph.Utils.getFramedElementPartialFormula(keystrs, valobj, chkClass);
Iterable<Element> elements = (org.openntf.domino.graph2.impl.DElementIterable) store.getElements(formulaFilter);
return this.frameElements(elements, null);
} else {
return null;
}
} else {
throw new IllegalArgumentException("Class " + classname + " not registered in graph");
}
}
public <F> Iterable<F> getFilteredElementsStarts(final String classname, final List<CharSequence> keys,
final List<CaseInsensitiveString> values) {
// System.out.println("Getting a filtered list of elements of type " + classname);
org.openntf.domino.graph2.DElementStore store = null;
DGraph base = (DGraph) this.getBaseGraph();
Class<?> chkClass = getClassFromName(classname);
if (chkClass != null) {
store = base.findElementStore(chkClass);
if (store != null) {
List<String> keystrs = CaseInsensitiveString.toStrings(keys);
List<Object> valobj = new ArrayList<Object>(values);
String formulaFilter = org.openntf.domino.graph2.DGraph.Utils.getFramedElementStartsFormula(keystrs, valobj, chkClass);
Iterable<Element> elements = (org.openntf.domino.graph2.impl.DElementIterable) store.getElements(formulaFilter);
return this.frameElements(elements, null);
} else {
return null;
}
} else {
throw new IllegalArgumentException("Class " + classname + " not registered in graph");
}
}
public Element getElement(final Object id) {
DGraph base = (DGraph) this.getBaseGraph();
org.openntf.domino.graph2.DElementStore store = null;
if (id instanceof NoteCoordinate) {
store = base.findElementStore(id);
// System.out.println("Got element store from NoteCoordinate " + id.toString());
} else {
String typeid = getTypedId(id);
store = base.findElementStore(typeid);
}
Element elem = store.getElement(id);
return elem;
}
public <F> F getElement(final Object id, final Class<F> kind) {
F result = null;
DGraph base = (DGraph) this.getBaseGraph();
org.openntf.domino.graph2.DElementStore store = null;
if (id instanceof NoteCoordinate) {
store = base.findElementStore(id);
// System.out.println("Got element store from NoteCoordinate " + id.toString());
} else {
String typeid = getTypedId(id);
if (typeid == null) {
store = base.findElementStore(kind);
} else {
store = base.findElementStore(typeid);
}
}
// System.out.println("Attempting to get an element from element store " + System.identityHashCode(store));
Element elem = store.getElement(id);
if (null == elem) {
result = null;
} else if (elem instanceof Edge) {
result = frame((Edge) elem, kind);
} else if (elem instanceof Vertex) {
result = frame((Vertex) elem, kind);
} else {
throw new IllegalStateException("Key " + id.toString() + " returned an element of type " + elem.getClass().getName());
}
// if (result == null) {
// System.out.println("Unable to resolve an element with id " + id.toString() + " though we did find a store "
// + store.getStoreKey());
// }
return result;
}
@Override
public <F> F getVertex(final Object id, final Class<F> kind) {
DGraph base = (DGraph) this.getBaseGraph();
org.openntf.domino.graph2.DElementStore store = null;
if (id instanceof NoteCoordinate) {
store = base.findElementStore(id);
} else {
String typeid = getTypedId(id);
if (typeid == null) {
store = base.findElementStore(kind);
} else {
store = base.findElementStore(typeid);
}
}
Vertex vertex = store.getVertex(id);
if (null == vertex) {
return null;
}
return frame(vertex, kind);
}
@Override
public <F> F getEdge(final Object id, final Class<F> kind) {
DGraph base = (DGraph) this.getBaseGraph();
org.openntf.domino.graph2.DElementStore store = null;
if (id instanceof NoteCoordinate) {
store = base.findElementStore(id);
} else {
String typeid = getTypedId(id);
if (typeid == null) {
store = base.findElementStore(kind);
} else {
store = base.findElementStore(typeid);
}
}
Edge edge = store.getEdge(id);
if (null == edge) {
return null;
}
// for (FrameInitializer initializer : getConfig().getFrameInitializers()) {
// initializer.initElement(kind, this, edge);
// }
return frame(edge, kind);
}
@Override
public <F> Iterable<F> getVertices(final String key, final Object value, final Class<F> kind) {
org.openntf.domino.graph2.DElementStore store = null;
DGraph base = (DGraph) this.getBaseGraph();
store = base.findElementStore(kind);
if (store != null) {
String formulaFilter = org.openntf.domino.graph2.DGraph.Utils.getFramedVertexFormula(key, value, kind);
Iterable<Vertex> vertices = store.getVertices(formulaFilter);
return this.frameVertices(vertices, kind);
} else {
return null;
}
}
public <F> F addEdge(final Object id, final Vertex outVertex, final Vertex inVertex, final String label) {
// if (id != null) {
// System.out.println("TEMP DEBUG Adding an edge with a forced id of " + String.valueOf(id));
// }
return (F) super.addEdge(id, outVertex, inVertex, label);
}
@Override
public <F> F addEdge(final Object id, final Vertex outVertex, final Vertex inVertex, final String label, final Direction direction,
final Class<F> kind) {
DGraph base = (DGraph) this.getBaseGraph();
org.openntf.domino.graph2.DElementStore store = null;
if (id instanceof NoteCoordinate) {
store = base.findElementStore(id);
} else {
String typeid = getTypedId(id);
if (typeid == null) {
store = base.findElementStore(kind);
} else {
store = base.findElementStore(typeid);
}
}
Edge edge = store.addEdge(id);
((DEdge) edge).setLabel(label);
((DEdge) edge).setInVertex(inVertex);
((DEdge) edge).setOutVertex(outVertex);
return frame(edge, kind);
}
@Override
public <F> Iterable<F> getEdges(final String key, final Object value, final Class<F> kind) {
org.openntf.domino.graph2.DElementStore store = null;
DGraph base = (DGraph) this.getBaseGraph();
store = base.findElementStore(kind);
if (store != null) {
String formulaFilter = org.openntf.domino.graph2.DGraph.Utils.getFramedEdgeFormula(key, value, kind);
Iterable<Edge> edges = store.getEdges(formulaFilter);
return this.frameEdges(edges, kind);
} else {
return null;
}
}
// public <F> F initializeAndFrame(final Edge edge, final Class<F> kind) {
// for (FrameInitializer initializer : getConfig().getFrameInitializers()) {
// initializer.initElement(kind, this, edge);
// }
// return frame(edge, kind);
// }
//
// @Deprecated
// public <F> F initializeAndFrame(final Edge edge, final Direction direction, final Class<F> kind) {
// for (FrameInitializer initializer : getConfig().getFrameInitializers()) {
// initializer.initElement(kind, this, edge);
// }
// return frame(edge, direction, kind);
// }
//
// public <F> F initializeAndFrame(final Vertex vertex, final Class<F> kind) {
// for (FrameInitializer initializer : getConfig().getFrameInitializers()) {
// initializer.initElement(kind, this, vertex);
// }
// return frame(vertex, kind);
// }
public <F> Iterable<F> frameElements(final Iterable<Element> elements, final Class<F> kind) {
Iterator<Element> it = elements.iterator();
if (it.hasNext()) {
Object chkElement = it.next();
if (chkElement instanceof Edge) {
return new FramedEdgeList(this, null, elements, kind);
}
if (chkElement instanceof Vertex) {
return new FramedVertexList(this, null, elements, kind);
}
}
return new FramedElementIterable(this, elements, kind);
}
public <F> F frame(final Element element, final Class<F> kind) {
// Class<F> klazz = kind;
// DConfiguration config = (DConfiguration) this.getConfig();
// config.getTypeManager().initElement(klazz, this, element);
// for (FrameInitializer initializer : getConfig().getFrameInitializers()) {
// if (!(initializer instanceof JavaFrameInitializer)) {
// initializer.initElement(klazz, this, element);
// }
// }
@SuppressWarnings("deprecation")
F result = null;
if (element instanceof Edge) {
result = frame((Edge) element, kind);
} else if (element instanceof Vertex) {
result = frame((Vertex) element, kind);
} else {
throw new IllegalStateException("Cannot frame an element of type " + element.getClass().getName());
}
// for (FrameInitializer initializer : getConfig().getFrameInitializers()) {
// if (initializer instanceof JavaFrameInitializer) {
// ((JavaFrameInitializer) initializer).initElement(klazz, this, result);
// }
// }
return result;
}
@Override
public <F> F frame(final Edge edge, final Class<F> kind) {
Class<F> klazz = (Class<F>) (kind == null ? EdgeFrame.class : kind);
DConfiguration config = (DConfiguration) this.getConfig();
config.getTypeManager().initElement(klazz, this, edge);
for (FrameInitializer initializer : getConfig().getFrameInitializers()) {
if (!(initializer instanceof JavaFrameInitializer)) {
initializer.initElement(klazz, this, edge);
}
}
@SuppressWarnings("deprecation")
F result = super.frame(edge, Direction.OUT, klazz);
for (FrameInitializer initializer : getConfig().getFrameInitializers()) {
if (initializer instanceof JavaFrameInitializer) {
((JavaFrameInitializer) initializer).initElement(klazz, this, result);
}
}
return result;
}
@Override
@Deprecated
public <F> F frame(final Edge edge, final Direction direction, final Class<F> kind) {
Class<F> klazz = (Class<F>) (kind == null ? DEdgeFrame.class : kind);
DConfiguration config = (DConfiguration) this.getConfig();
config.getTypeManager().initElement(klazz, this, edge);
for (FrameInitializer initializer : getConfig().getFrameInitializers()) {
if (!(initializer instanceof JavaFrameInitializer)) {
initializer.initElement(klazz, this, edge);
}
}
F result = super.frame(edge, direction, klazz);
for (FrameInitializer initializer : getConfig().getFrameInitializers()) {
if (initializer instanceof JavaFrameInitializer) {
((JavaFrameInitializer) initializer).initElement(klazz, this, result);
}
}
return result;
}
@Override
public <F> F frame(final Vertex vertex, Class<F> kind) {
if (vertex == null)
return null;
String chk = ((DVertex) vertex).getProperty("$FormulaClass", String.class);
boolean isView = "1".equals(chk);
if (isView) {
kind = (Class<F>) ViewVertex.class;
}
Class<F> klazz = (Class<F>) (kind == null ? VertexFrame.class : kind);
DConfiguration config = (DConfiguration) this.getConfig();
DTypeManager manager = config.getTypeManager();
// if (manager == null)
// System.out.println("TypeManager is null!??!??! How?");
manager.initElement(klazz, this, vertex);
for (FrameInitializer initializer : getConfig().getFrameInitializers()) {
if (!(initializer instanceof JavaFrameInitializer)) {
initializer.initElement(klazz, this, vertex);
}
}
F result = null;
try {
result = super.frame(vertex, klazz);
} catch (Exception e) {
System.out.println("Exception while attempting to frame a vertex " + vertex.getId() + " with class " + klazz.getName());
DominoUtils.handleException(e);
}
for (FrameInitializer initializer : getConfig().getFrameInitializers()) {
if (initializer instanceof JavaFrameInitializer) {
((JavaFrameInitializer) initializer).initElement(klazz, this, result);
}
}
// if (isView) {
// StringBuilder sb = new StringBuilder();
// Class<?>[] interfaces = result.getClass().getInterfaces();
// for (Class<?> inter : interfaces) {
// sb.append(inter.getName());
// sb.append(", ");
// }
// System.out.println("Requested a " + klazz.getName() + " and resulted in a [" + sb.toString() + "]");
// }
return result;
}
public org.openntf.domino.graph2.DElementStore getElementStore(final Class<?> kind) {
DGraph base = (DGraph) this.getBaseGraph();
return base.findElementStore(kind);
}
public void addKeyResolver(final DKeyResolver resolver) {
DGraph base = (DGraph) this.getBaseGraph();
base.addKeyResolver(resolver);
}
public DKeyResolver getKeyResolver(final Class<?> type) {
DGraph base = (DGraph) this.getBaseGraph();
return base.getKeyResolver(type);
}
}